diff options
Diffstat (limited to 'thirdparty/harfbuzz')
101 files changed, 6342 insertions, 2992 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-aat-layout.cc b/thirdparty/harfbuzz/src/hb-aat-layout.cc index e2d4de2ccd..caff204d67 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout.cc +++ b/thirdparty/harfbuzz/src/hb-aat-layout.cc @@ -108,7 +108,7 @@ static const hb_aat_feature_mapping_t feature_mappings[] = {HB_TAG ('f','r','a','c'), HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS, HB_AAT_LAYOUT_FEATURE_SELECTOR_DIAGONAL_FRACTIONS, HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_FRACTIONS}, {HB_TAG ('f','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_TEXT, (hb_aat_layout_feature_selector_t) 7}, {HB_TAG ('h','a','l','t'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_HALF_WIDTH_TEXT, (hb_aat_layout_feature_selector_t) 7}, - {HB_TAG ('h','i','s','t'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES, HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF}, + {HB_TAG ('h','i','s','t'), (hb_aat_layout_feature_type_t) 40, (hb_aat_layout_feature_selector_t) 0, (hb_aat_layout_feature_selector_t) 1}, {HB_TAG ('h','k','n','a'), HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_OFF}, {HB_TAG ('h','l','i','g'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES, HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF}, {HB_TAG ('h','n','g','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION, HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL, HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_TRANSLITERATION}, @@ -170,6 +170,7 @@ static const hb_aat_feature_mapping_t feature_mappings[] = {HB_TAG ('v','k','n','a'), HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_OFF}, {HB_TAG ('v','p','a','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT, (hb_aat_layout_feature_selector_t) 7}, {HB_TAG ('v','r','t','2'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION, HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_OFF}, + {HB_TAG ('v','r','t','r'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION, (hb_aat_layout_feature_selector_t) 2, (hb_aat_layout_feature_selector_t) 3}, {HB_TAG ('z','e','r','o'), HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS, HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_OFF}, }; diff --git a/thirdparty/harfbuzz/src/hb-algs.hh b/thirdparty/harfbuzz/src/hb-algs.hh index 3a3ab08046..c40a55cd1f 100644 --- a/thirdparty/harfbuzz/src/hb-algs.hh +++ b/thirdparty/harfbuzz/src/hb-algs.hh @@ -498,7 +498,7 @@ struct hb_pair_t template <typename Q1, typename Q2, hb_enable_if (hb_is_convertible (T1, Q1) && - hb_is_convertible (T2, T2))> + hb_is_convertible (T2, Q2))> operator hb_pair_t<Q1, Q2> () { return hb_pair_t<Q1, Q2> (first, second); } hb_pair_t<T1, T2> reverse () const 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-deserialize-text.hh b/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh index b599e9667c..06a605e225 100644 --- a/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh +++ b/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh @@ -478,7 +478,7 @@ _resume: case 18: #line 58 "hb-buffer-deserialize-text.rl" { - /* TODO Unescape delimeters. */ + /* TODO Unescape delimiters. */ if (!hb_font_glyph_from_string (font, tok, p - tok, &info.codepoint)) @@ -535,7 +535,7 @@ _resume: case 16: #line 58 "hb-buffer-deserialize-text.rl" { - /* TODO Unescape delimeters. */ + /* TODO Unescape delimiters. */ if (!hb_font_glyph_from_string (font, tok, p - tok, &info.codepoint)) @@ -635,7 +635,7 @@ _resume: } #line 58 "hb-buffer-deserialize-text.rl" { - /* TODO Unescape delimeters. */ + /* TODO Unescape delimiters. */ if (!hb_font_glyph_from_string (font, tok, p - tok, &info.codepoint)) @@ -645,7 +645,7 @@ _resume: case 17: #line 58 "hb-buffer-deserialize-text.rl" { - /* TODO Unescape delimeters. */ + /* TODO Unescape delimiters. */ if (!hb_font_glyph_from_string (font, tok, p - tok, &info.codepoint)) @@ -674,7 +674,7 @@ _resume: } #line 58 "hb-buffer-deserialize-text.rl" { - /* TODO Unescape delimeters. */ + /* TODO Unescape delimiters. */ if (!hb_font_glyph_from_string (font, tok, p - tok, &info.codepoint)) @@ -701,7 +701,7 @@ _resume: } #line 58 "hb-buffer-deserialize-text.rl" { - /* TODO Unescape delimeters. */ + /* TODO Unescape delimiters. */ if (!hb_font_glyph_from_string (font, tok, p - tok, &info.codepoint)) @@ -733,7 +733,7 @@ _again: case 16: #line 58 "hb-buffer-deserialize-text.rl" { - /* TODO Unescape delimeters. */ + /* TODO Unescape delimiters. */ if (!hb_font_glyph_from_string (font, tok, p - tok, &info.codepoint)) @@ -820,7 +820,7 @@ _again: } #line 58 "hb-buffer-deserialize-text.rl" { - /* TODO Unescape delimeters. */ + /* TODO Unescape delimiters. */ if (!hb_font_glyph_from_string (font, tok, p - tok, &info.codepoint)) diff --git a/thirdparty/harfbuzz/src/hb-buffer-verify.cc b/thirdparty/harfbuzz/src/hb-buffer-verify.cc new file mode 100644 index 0000000000..dea2c11c35 --- /dev/null +++ b/thirdparty/harfbuzz/src/hb-buffer-verify.cc @@ -0,0 +1,422 @@ +/* + * Copyright © 2022 Behdad Esfahbod + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#include "hb.hh" + +#ifndef HB_NO_BUFFER_VERIFY + +#include "hb-buffer.hh" + + +#define BUFFER_VERIFY_ERROR "buffer verify error: " +static inline void +buffer_verify_error (hb_buffer_t *buffer, + hb_font_t *font, + const char *fmt, + ...) HB_PRINTF_FUNC(3, 4); + +static inline void +buffer_verify_error (hb_buffer_t *buffer, + hb_font_t *font, + const char *fmt, + ...) +{ + va_list ap; + va_start (ap, fmt); + if (buffer->messaging ()) + { + buffer->message_impl (font, fmt, ap); + } + else + { + fprintf (stderr, "harfbuzz "); + vfprintf (stderr, fmt, ap); + fprintf (stderr, "\n"); + } + va_end (ap); +} + +static bool +buffer_verify_monotone (hb_buffer_t *buffer, + hb_font_t *font) +{ + /* Check that clusters are monotone. */ + if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES || + buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS) + { + bool is_forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer)); + + unsigned int num_glyphs; + hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs); + + for (unsigned int i = 1; i < num_glyphs; i++) + if (info[i-1].cluster != info[i].cluster && + (info[i-1].cluster < info[i].cluster) != is_forward) + { + buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "clusters are not monotone."); + return false; + } + } + + return true; +} + +static bool +buffer_verify_unsafe_to_break (hb_buffer_t *buffer, + hb_buffer_t *text_buffer, + hb_font_t *font, + const hb_feature_t *features, + unsigned int num_features, + const char * const *shapers) +{ + if (buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES && + buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS) + { + /* Cannot perform this check without monotone clusters. */ + return true; + } + + /* Check that breaking up shaping at safe-to-break is indeed safe. */ + + hb_buffer_t *fragment = hb_buffer_create_similar (buffer); + hb_buffer_set_flags (fragment, hb_buffer_get_flags (fragment) & ~HB_BUFFER_FLAG_VERIFY); + hb_buffer_t *reconstruction = hb_buffer_create_similar (buffer); + hb_buffer_set_flags (reconstruction, hb_buffer_get_flags (reconstruction) & ~HB_BUFFER_FLAG_VERIFY); + + unsigned int num_glyphs; + hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs); + + unsigned int num_chars; + hb_glyph_info_t *text = hb_buffer_get_glyph_infos (text_buffer, &num_chars); + + /* Chop text and shape fragments. */ + bool forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer)); + unsigned int start = 0; + unsigned int text_start = forward ? 0 : num_chars; + unsigned int text_end = text_start; + for (unsigned int end = 1; end < num_glyphs + 1; end++) + { + if (end < num_glyphs && + (info[end].cluster == info[end-1].cluster || + info[end-(forward?0:1)].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)) + continue; + + /* Shape segment corresponding to glyphs start..end. */ + if (end == num_glyphs) + { + if (forward) + text_end = num_chars; + else + text_start = 0; + } + else + { + if (forward) + { + unsigned int cluster = info[end].cluster; + while (text_end < num_chars && text[text_end].cluster < cluster) + text_end++; + } + else + { + unsigned int cluster = info[end - 1].cluster; + while (text_start && text[text_start - 1].cluster >= cluster) + text_start--; + } + } + assert (text_start < text_end); + + if (0) + printf("start %d end %d text start %d end %d\n", start, end, text_start, text_end); + + hb_buffer_clear_contents (fragment); + + hb_buffer_flags_t flags = hb_buffer_get_flags (fragment); + if (0 < text_start) + flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_BOT); + if (text_end < num_chars) + flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_EOT); + hb_buffer_set_flags (fragment, flags); + + hb_buffer_append (fragment, text_buffer, text_start, text_end); + if (!hb_shape_full (font, fragment, features, num_features, shapers)) + { + buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment."); + hb_buffer_destroy (reconstruction); + hb_buffer_destroy (fragment); + return false; + } + hb_buffer_append (reconstruction, fragment, 0, -1); + + start = end; + if (forward) + text_start = text_end; + else + text_end = text_start; + } + + bool ret = true; + hb_buffer_diff_flags_t diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0); + if (diff) + { + buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-break test failed."); + ret = false; + + /* Return the reconstructed result instead so it can be inspected. */ + hb_buffer_set_length (buffer, 0); + hb_buffer_append (buffer, reconstruction, 0, -1); + } + + hb_buffer_destroy (reconstruction); + hb_buffer_destroy (fragment); + + return ret; +} + +static bool +buffer_verify_unsafe_to_concat (hb_buffer_t *buffer, + hb_buffer_t *text_buffer, + hb_font_t *font, + const hb_feature_t *features, + unsigned int num_features, + const char * const *shapers) +{ + if (buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES && + buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS) + { + /* Cannot perform this check without monotone clusters. */ + return true; + } + + /* Check that shuffling up text before shaping at safe-to-concat points + * is indeed safe. */ + + /* This is what we do: + * + * 1. We shape text once. Then segment the text at all the safe-to-concat + * points; + * + * 2. Then we create two buffers, one containing all the even segments and + * one all the odd segments. + * + * 3. Because all these segments were safe-to-concat at both ends, we + * expect that concatenating them and shaping should NOT change the + * shaping results of each segment. As such, we expect that after + * shaping the two buffers, we still get cluster boundaries at the + * segment boundaries, and that those all are safe-to-concat points. + * Moreover, that there are NOT any safe-to-concat points within the + * segments. + * + * 4. Finally, we reconstruct the shaping results of the original text by + * simply interleaving the shaping results of the segments from the two + * buffers, and assert that the total shaping results is the same as + * the one from original buffer in step 1. + */ + + hb_buffer_t *fragments[2] {hb_buffer_create_similar (buffer), + hb_buffer_create_similar (buffer)}; + hb_buffer_set_flags (fragments[0], hb_buffer_get_flags (fragments[0]) & ~HB_BUFFER_FLAG_VERIFY); + hb_buffer_set_flags (fragments[1], hb_buffer_get_flags (fragments[1]) & ~HB_BUFFER_FLAG_VERIFY); + hb_buffer_t *reconstruction = hb_buffer_create_similar (buffer); + hb_buffer_set_flags (reconstruction, hb_buffer_get_flags (reconstruction) & ~HB_BUFFER_FLAG_VERIFY); + hb_segment_properties_t props; + hb_buffer_get_segment_properties (buffer, &props); + hb_buffer_set_segment_properties (fragments[0], &props); + hb_buffer_set_segment_properties (fragments[1], &props); + hb_buffer_set_segment_properties (reconstruction, &props); + + unsigned num_glyphs; + hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs); + + unsigned num_chars; + hb_glyph_info_t *text = hb_buffer_get_glyph_infos (text_buffer, &num_chars); + + bool forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer)); + + if (!forward) + hb_buffer_reverse (buffer); + + /* + * Split text into segments and collect into to fragment streams. + */ + { + unsigned fragment_idx = 0; + unsigned start = 0; + unsigned text_start = 0; + unsigned text_end = 0; + for (unsigned end = 1; end < num_glyphs + 1; end++) + { + if (end < num_glyphs && + (info[end].cluster == info[end-1].cluster || + info[end].mask & HB_GLYPH_FLAG_UNSAFE_TO_CONCAT)) + continue; + + /* Accumulate segment corresponding to glyphs start..end. */ + if (end == num_glyphs) + text_end = num_chars; + else + { + unsigned cluster = info[end].cluster; + while (text_end < num_chars && text[text_end].cluster < cluster) + text_end++; + } + assert (text_start < text_end); + + if (0) + printf("start %d end %d text start %d end %d\n", start, end, text_start, text_end); + +#if 0 + hb_buffer_flags_t flags = hb_buffer_get_flags (fragment); + if (0 < text_start) + flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_BOT); + if (text_end < num_chars) + flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_EOT); + hb_buffer_set_flags (fragment, flags); +#endif + + hb_buffer_append (fragments[fragment_idx], text_buffer, text_start, text_end); + + start = end; + text_start = text_end; + fragment_idx = 1 - fragment_idx; + } + } + + bool ret = true; + hb_buffer_diff_flags_t diff; + + /* + * Shape the two fragment streams. + */ + if (!hb_shape_full (font, fragments[0], features, num_features, shapers)) + { + buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment."); + ret = false; + goto out; + } + if (!hb_shape_full (font, fragments[1], features, num_features, shapers)) + { + buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment."); + ret = false; + goto out; + } + + if (!forward) + { + hb_buffer_reverse (fragments[0]); + hb_buffer_reverse (fragments[1]); + } + + /* + * Reconstruct results. + */ + { + unsigned fragment_idx = 0; + unsigned fragment_start[2] {0, 0}; + unsigned fragment_num_glyphs[2]; + hb_glyph_info_t *fragment_info[2]; + for (unsigned i = 0; i < 2; i++) + fragment_info[i] = hb_buffer_get_glyph_infos (fragments[i], &fragment_num_glyphs[i]); + while (fragment_start[0] < fragment_num_glyphs[0] || + fragment_start[1] < fragment_num_glyphs[1]) + { + unsigned fragment_end = fragment_start[fragment_idx] + 1; + while (fragment_end < fragment_num_glyphs[fragment_idx] && + (fragment_info[fragment_idx][fragment_end].cluster == fragment_info[fragment_idx][fragment_end - 1].cluster || + fragment_info[fragment_idx][fragment_end].mask & HB_GLYPH_FLAG_UNSAFE_TO_CONCAT)) + fragment_end++; + + hb_buffer_append (reconstruction, fragments[fragment_idx], fragment_start[fragment_idx], fragment_end); + + fragment_start[fragment_idx] = fragment_end; + fragment_idx = 1 - fragment_idx; + } + } + + if (!forward) + { + hb_buffer_reverse (buffer); + hb_buffer_reverse (reconstruction); + } + + /* + * Diff results. + */ + diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0); + if (diff) + { + buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-concat test failed."); + ret = false; + + /* Return the reconstructed result instead so it can be inspected. */ + hb_buffer_set_length (buffer, 0); + hb_buffer_append (buffer, reconstruction, 0, -1); + } + + +out: + hb_buffer_destroy (reconstruction); + hb_buffer_destroy (fragments[0]); + hb_buffer_destroy (fragments[1]); + + return ret; +} + +bool +hb_buffer_t::verify (hb_buffer_t *text_buffer, + hb_font_t *font, + const hb_feature_t *features, + unsigned int num_features, + const char * const *shapers) +{ + bool ret = true; + if (!buffer_verify_monotone (this, font)) + ret = false; + if (!buffer_verify_unsafe_to_break (this, text_buffer, font, features, num_features, shapers)) + ret = false; + if ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) != 0 && + !buffer_verify_unsafe_to_concat (this, text_buffer, font, features, num_features, shapers)) + ret = false; + if (!ret) + { + unsigned len = text_buffer->len; + hb_vector_t<char> bytes; + if (likely (bytes.resize (len * 10 + 16))) + { + hb_buffer_serialize_unicode (text_buffer, + 0, len, + bytes.arrayZ, bytes.length, + &len, + HB_BUFFER_SERIALIZE_FORMAT_TEXT, + HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS); + buffer_verify_error (this, font, BUFFER_VERIFY_ERROR "text was: %s.", bytes.arrayZ); + } + } + return ret; +} + + +#endif diff --git a/thirdparty/harfbuzz/src/hb-buffer.cc b/thirdparty/harfbuzz/src/hb-buffer.cc index e50afcb203..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; } @@ -1789,7 +1789,7 @@ hb_buffer_add_codepoints (hb_buffer_t *buffer, **/ HB_EXTERN void hb_buffer_append (hb_buffer_t *buffer, - hb_buffer_t *source, + const hb_buffer_t *source, unsigned int start, unsigned int end) { diff --git a/thirdparty/harfbuzz/src/hb-buffer.h b/thirdparty/harfbuzz/src/hb-buffer.h index 9fbd7b1ec3..14aaa5e1f5 100644 --- a/thirdparty/harfbuzz/src/hb-buffer.h +++ b/thirdparty/harfbuzz/src/hb-buffer.h @@ -117,7 +117,7 @@ typedef struct hb_glyph_info_t { * from there, and repeat. * At the start of next line a similar algorithm can * be implemented. That is: 1. Iterate forward from - * the line-break position untill the first cluster + * the line-break position until the first cluster * start position that is NOT unsafe-to-concat, 2. * shape the segment from beginning of the line to * that position, 3. check whether the resulting @@ -137,7 +137,11 @@ typedef struct hb_glyph_info_t { * clusters. * The #HB_GLYPH_FLAG_UNSAFE_TO_BREAK flag will * always imply this flag. - * Since: 3.3.0 + * To use this flag, you must enable the buffer flag + * @HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT during + * shaping, otherwise the buffer flag will not be + * reliably produced. + * Since: 4.0.0 * @HB_GLYPH_FLAG_DEFINED: All the currently defined flags. * * Flags for #hb_glyph_info_t. @@ -356,7 +360,19 @@ hb_buffer_guess_segment_properties (hb_buffer_t *buffer); * @HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE: * flag indicating that a dotted circle should * not be inserted in the rendering of incorrect - * character sequences (such at <0905 093E>). Since: 2.4 + * character sequences (such at <0905 093E>). Since: 2.4.0 + * @HB_BUFFER_FLAG_VERIFY: + * flag indicating that the hb_shape() call and its variants + * should perform various verification processes on the results + * of the shaping operation on the buffer. If the verification + * fails, then either a buffer message is sent, if a message + * handler is installed on the buffer, or a message is written + * to standard error. In either case, the shaping result might + * be modified to show the failed output. Since: 3.4.0 + * @HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT: + * flag indicating that the @HB_GLYPH_FLAG_UNSAFE_TO_CONCAT + * glyph-flag should be produced by the shaper. By default + * it will not be produced since it incurs a cost. Since: 4.0.0 * * Flags for #hb_buffer_t. * @@ -368,7 +384,9 @@ typedef enum { /*< flags >*/ HB_BUFFER_FLAG_EOT = 0x00000002u, /* End-of-text */ HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES = 0x00000004u, HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES = 0x00000008u, - HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE = 0x00000010u + HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE = 0x00000010u, + HB_BUFFER_FLAG_VERIFY = 0x00000020u, + HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT = 0x00000040u } hb_buffer_flags_t; HB_EXTERN void @@ -522,7 +540,7 @@ hb_buffer_add_codepoints (hb_buffer_t *buffer, HB_EXTERN void hb_buffer_append (hb_buffer_t *buffer, - hb_buffer_t *source, + const hb_buffer_t *source, unsigned int start, unsigned int end); @@ -619,24 +637,24 @@ hb_buffer_serialize_glyphs (hb_buffer_t *buffer, HB_EXTERN unsigned int hb_buffer_serialize_unicode (hb_buffer_t *buffer, - unsigned int start, - unsigned int end, - char *buf, - unsigned int buf_size, - unsigned int *buf_consumed, - hb_buffer_serialize_format_t format, - hb_buffer_serialize_flags_t flags); + unsigned int start, + unsigned int end, + char *buf, + unsigned int buf_size, + unsigned int *buf_consumed, + hb_buffer_serialize_format_t format, + hb_buffer_serialize_flags_t flags); HB_EXTERN unsigned int hb_buffer_serialize (hb_buffer_t *buffer, - unsigned int start, - unsigned int end, - char *buf, - unsigned int buf_size, - unsigned int *buf_consumed, - hb_font_t *font, - hb_buffer_serialize_format_t format, - hb_buffer_serialize_flags_t flags); + unsigned int start, + unsigned int end, + char *buf, + unsigned int buf_size, + unsigned int *buf_consumed, + hb_font_t *font, + hb_buffer_serialize_format_t format, + hb_buffer_serialize_flags_t flags); HB_EXTERN hb_bool_t hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, @@ -648,10 +666,10 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, HB_EXTERN hb_bool_t hb_buffer_deserialize_unicode (hb_buffer_t *buffer, - const char *buf, - int buf_len, - const char **end_ptr, - hb_buffer_serialize_format_t format); + const char *buf, + int buf_len, + const char **end_ptr, + hb_buffer_serialize_format_t format); diff --git a/thirdparty/harfbuzz/src/hb-buffer.hh b/thirdparty/harfbuzz/src/hb-buffer.hh index ac45f090a5..bc6992905e 100644 --- a/thirdparty/harfbuzz/src/hb-buffer.hh +++ b/thirdparty/harfbuzz/src/hb-buffer.hh @@ -212,6 +212,20 @@ struct hb_buffer_t HB_INTERNAL void enter (); HB_INTERNAL void leave (); +#ifndef HB_NO_BUFFER_VERIFY + HB_INTERNAL +#endif + bool verify (hb_buffer_t *text_buffer, + hb_font_t *font, + const hb_feature_t *features, + unsigned int num_features, + const char * const *shapers) +#ifndef HB_NO_BUFFER_VERIFY + ; +#else + { return true; } +#endif + unsigned int backtrack_len () const { return have_output ? out_len : idx; } unsigned int lookahead_len () const { return len - idx; } uint8_t next_serial () { return ++serial ? serial : ++serial; } @@ -446,6 +460,8 @@ struct hb_buffer_t } void unsafe_to_concat (unsigned int start = 0, unsigned int end = -1) { + if (likely ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0)) + return; _set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_CONCAT, start, end, true); @@ -458,6 +474,8 @@ struct hb_buffer_t } void unsafe_to_concat_from_outbuffer (unsigned int start = 0, unsigned int end = -1) { + if (likely ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0)) + return; _set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_CONCAT, start, end, false, true); diff --git a/thirdparty/harfbuzz/src/hb-common.cc b/thirdparty/harfbuzz/src/hb-common.cc index 249a8a8010..41229b9183 100644 --- a/thirdparty/harfbuzz/src/hb-common.cc +++ b/thirdparty/harfbuzz/src/hb-common.cc @@ -1065,7 +1065,7 @@ hb_variation_from_string (const char *str, int len, static inline void free_static_C_locale (); static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<hb_locale_t>, - hb_C_locale_lazy_loader_t> + hb_C_locale_lazy_loader_t> { static hb_locale_t create () { diff --git a/thirdparty/harfbuzz/src/hb-common.h b/thirdparty/harfbuzz/src/hb-common.h index 0384117a4d..7b897a6c51 100644 --- a/thirdparty/harfbuzz/src/hb-common.h +++ b/thirdparty/harfbuzz/src/hb-common.h @@ -130,6 +130,16 @@ typedef union _hb_var_int_t { int8_t i8[4]; } hb_var_int_t; +typedef union _hb_var_num_t { + float f; + uint32_t u32; + int32_t i32; + uint16_t u16[2]; + int16_t i16[2]; + uint8_t u8[4]; + int8_t i8[4]; +} hb_var_num_t; + /* hb_tag_t */ @@ -481,6 +491,7 @@ hb_language_get_default (void); * @HB_SCRIPT_TANGSA: `Tnsa`, Since: 3.0.0 * @HB_SCRIPT_TOTO: `Toto`, Since: 3.0.0 * @HB_SCRIPT_VITHKUQI: `Vith`, Since: 3.0.0 + * @HB_SCRIPT_MATH: `Zmth`, Since: 3.4.0 * @HB_SCRIPT_INVALID: No script set * * Data type for scripts. Each #hb_script_t's value is an #hb_tag_t corresponding @@ -697,6 +708,11 @@ typedef enum HB_SCRIPT_TOTO = HB_TAG ('T','o','t','o'), /*14.0*/ HB_SCRIPT_VITHKUQI = HB_TAG ('V','i','t','h'), /*14.0*/ + /* + * Since 3.4.0 + */ + HB_SCRIPT_MATH = HB_TAG ('Z','m','t','h'), + /* No script set. */ HB_SCRIPT_INVALID = HB_TAG_NONE, diff --git a/thirdparty/harfbuzz/src/hb-config.hh b/thirdparty/harfbuzz/src/hb-config.hh index 7d00d9088a..4b46dea938 100644 --- a/thirdparty/harfbuzz/src/hb-config.hh +++ b/thirdparty/harfbuzz/src/hb-config.hh @@ -55,6 +55,7 @@ #define HB_NO_ATEXIT #define HB_NO_BUFFER_MESSAGE #define HB_NO_BUFFER_SERIALIZE +#define HB_NO_BUFFER_VERIFY #define HB_NO_BITMAP #define HB_NO_CFF #define HB_NO_COLOR @@ -84,6 +85,7 @@ #ifdef HB_MINI #define HB_NO_AAT #define HB_NO_LEGACY +#define HB_NO_BORING_EXPANSION #endif #if defined(HAVE_CONFIG_OVERRIDE_H) || defined(HB_CONFIG_OVERRIDE_H) 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-draw.cc b/thirdparty/harfbuzz/src/hb-draw.cc index c0af6ce013..b31019b07e 100644 --- a/thirdparty/harfbuzz/src/hb-draw.cc +++ b/thirdparty/harfbuzz/src/hb-draw.cc @@ -25,237 +25,313 @@ #include "hb.hh" #ifndef HB_NO_DRAW -#ifdef HB_EXPERIMENTAL_API #include "hb-draw.hh" -#include "hb-ot.h" -#include "hb-ot-glyf-table.hh" -#include "hb-ot-cff1-table.hh" -#include "hb-ot-cff2-table.hh" /** - * hb_draw_funcs_set_move_to_func: - * @funcs: draw functions object - * @move_to: move-to callback + * SECTION:hb-draw + * @title: hb-draw + * @short_description: Glyph drawing + * @include: hb.h * - * Sets move-to callback to the draw functions object. - * - * Since: EXPERIMENTAL + * Functions for drawing (extracting) glyph shapes. **/ -void -hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *funcs, - hb_draw_move_to_func_t move_to) + +static void +hb_draw_move_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED, + hb_draw_state_t *st HB_UNUSED, + float to_x HB_UNUSED, float to_y HB_UNUSED, + void *user_data HB_UNUSED) {} + +static void +hb_draw_line_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED, + hb_draw_state_t *st HB_UNUSED, + float to_x HB_UNUSED, float to_y HB_UNUSED, + void *user_data HB_UNUSED) {} + +static void +hb_draw_quadratic_to_nil (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + float control_x, float control_y, + float to_x, float to_y, + void *user_data HB_UNUSED) { - if (unlikely (hb_object_is_immutable (funcs))) return; - funcs->move_to = move_to; + dfuncs->emit_cubic_to (draw_data, *st, + (st->current_x + 2.f * control_x) / 3.f, + (st->current_y + 2.f * control_y) / 3.f, + (to_x + 2.f * control_x) / 3.f, + (to_y + 2.f * control_y) / 3.f, + to_x, to_y); +} + +static void +hb_draw_cubic_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED, + hb_draw_state_t *st HB_UNUSED, + float control1_x HB_UNUSED, float control1_y HB_UNUSED, + float control2_x HB_UNUSED, float control2_y HB_UNUSED, + float to_x HB_UNUSED, float to_y HB_UNUSED, + void *user_data HB_UNUSED) {} + +static void +hb_draw_close_path_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED, + hb_draw_state_t *st HB_UNUSED, + void *user_data HB_UNUSED) {} + + +#define HB_DRAW_FUNC_IMPLEMENT(name) \ + \ +void \ +hb_draw_funcs_set_##name##_func (hb_draw_funcs_t *dfuncs, \ + hb_draw_##name##_func_t func, \ + void *user_data, \ + hb_destroy_func_t destroy) \ +{ \ + if (hb_object_is_immutable (dfuncs)) \ + return; \ + \ + if (dfuncs->destroy.name) \ + dfuncs->destroy.name (dfuncs->user_data.name); \ + \ + if (func) { \ + dfuncs->func.name = func; \ + dfuncs->user_data.name = user_data; \ + dfuncs->destroy.name = destroy; \ + } else { \ + dfuncs->func.name = hb_draw_##name##_nil; \ + dfuncs->user_data.name = nullptr; \ + dfuncs->destroy.name = nullptr; \ + } \ } +HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_DRAW_FUNC_IMPLEMENT + /** - * hb_draw_funcs_set_line_to_func: - * @funcs: draw functions object - * @line_to: line-to callback + * hb_draw_funcs_create: (Xconstructor) + * + * Creates a new draw callbacks object. * - * Sets line-to callback to the draw functions object. + * Return value: (transfer full): + * A newly allocated #hb_draw_funcs_t with a reference count of 1. The initial + * reference count should be released with hb_draw_funcs_destroy when you are + * done using the #hb_draw_funcs_t. This function never returns %NULL. If + * memory cannot be allocated, a special singleton #hb_draw_funcs_t object will + * be returned. * - * Since: EXPERIMENTAL + * Since: 4.0.0 **/ -void -hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *funcs, - hb_draw_line_to_func_t line_to) +hb_draw_funcs_t * +hb_draw_funcs_create () { - if (unlikely (hb_object_is_immutable (funcs))) return; - funcs->line_to = line_to; + hb_draw_funcs_t *dfuncs; + if (unlikely (!(dfuncs = hb_object_create<hb_draw_funcs_t> ()))) + return const_cast<hb_draw_funcs_t *> (&Null (hb_draw_funcs_t)); + + dfuncs->func = Null (hb_draw_funcs_t).func; + + return dfuncs; } +DEFINE_NULL_INSTANCE (hb_draw_funcs_t) = +{ + HB_OBJECT_HEADER_STATIC, + + { +#define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_nil, + HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_DRAW_FUNC_IMPLEMENT + } +}; + + /** - * hb_draw_funcs_set_quadratic_to_func: - * @funcs: draw functions object - * @move_to: quadratic-to callback + * hb_draw_funcs_reference: (skip) + * @dfuncs: draw functions + * + * Increases the reference count on @dfuncs by one. This prevents @buffer from + * being destroyed until a matching call to hb_draw_funcs_destroy() is made. * - * Sets quadratic-to callback to the draw functions object. + * Return value: (transfer full): + * The referenced #hb_draw_funcs_t. * - * Since: EXPERIMENTAL + * Since: 4.0.0 **/ -void -hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *funcs, - hb_draw_quadratic_to_func_t quadratic_to) +hb_draw_funcs_t * +hb_draw_funcs_reference (hb_draw_funcs_t *dfuncs) { - if (unlikely (hb_object_is_immutable (funcs))) return; - funcs->quadratic_to = quadratic_to; - funcs->is_quadratic_to_set = true; + return hb_object_reference (dfuncs); } /** - * hb_draw_funcs_set_cubic_to_func: - * @funcs: draw functions - * @cubic_to: cubic-to callback + * hb_draw_funcs_destroy: (skip) + * @dfuncs: draw functions * - * Sets cubic-to callback to the draw functions object. + * Deallocate the @dfuncs. + * Decreases the reference count on @dfuncs by one. If the result is zero, then + * @dfuncs and all associated resources are freed. See hb_draw_funcs_reference(). * - * Since: EXPERIMENTAL + * Since: 4.0.0 **/ void -hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *funcs, - hb_draw_cubic_to_func_t cubic_to) +hb_draw_funcs_destroy (hb_draw_funcs_t *dfuncs) { - if (unlikely (hb_object_is_immutable (funcs))) return; - funcs->cubic_to = cubic_to; + if (!hb_object_destroy (dfuncs)) return; + +#define HB_DRAW_FUNC_IMPLEMENT(name) \ + if (dfuncs->destroy.name) dfuncs->destroy.name (dfuncs->user_data.name); + HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_DRAW_FUNC_IMPLEMENT + + + hb_free (dfuncs); } /** - * hb_draw_funcs_set_close_path_func: - * @funcs: draw functions object - * @close_path: close-path callback + * hb_draw_funcs_make_immutable: + * @dfuncs: draw functions * - * Sets close-path callback to the draw functions object. + * Makes @dfuncs object immutable. * - * Since: EXPERIMENTAL + * Since: 4.0.0 **/ void -hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *funcs, - hb_draw_close_path_func_t close_path) +hb_draw_funcs_make_immutable (hb_draw_funcs_t *dfuncs) { - if (unlikely (hb_object_is_immutable (funcs))) return; - funcs->close_path = close_path; -} - -static void -_move_to_nil (hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, void *user_data HB_UNUSED) {} - -static void -_line_to_nil (hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, void *user_data HB_UNUSED) {} - -static void -_quadratic_to_nil (hb_position_t control_x HB_UNUSED, hb_position_t control_y HB_UNUSED, - hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, - void *user_data HB_UNUSED) {} - -static void -_cubic_to_nil (hb_position_t control1_x HB_UNUSED, hb_position_t control1_y HB_UNUSED, - hb_position_t control2_x HB_UNUSED, hb_position_t control2_y HB_UNUSED, - hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, - void *user_data HB_UNUSED) {} + if (hb_object_is_immutable (dfuncs)) + return; -static void -_close_path_nil (void *user_data HB_UNUSED) {} + hb_object_make_immutable (dfuncs); +} /** - * hb_draw_funcs_create: + * hb_draw_funcs_is_immutable: + * @dfuncs: draw functions * - * Creates a new draw callbacks object. + * Checks whether @dfuncs is immutable. + * + * Return value: %true if @dfuncs is immutable, %false otherwise * - * Since: EXPERIMENTAL + * Since: 4.0.0 **/ -hb_draw_funcs_t * -hb_draw_funcs_create () +hb_bool_t +hb_draw_funcs_is_immutable (hb_draw_funcs_t *dfuncs) { - hb_draw_funcs_t *funcs; - if (unlikely (!(funcs = hb_object_create<hb_draw_funcs_t> ()))) - return const_cast<hb_draw_funcs_t *> (&Null (hb_draw_funcs_t)); - - funcs->move_to = (hb_draw_move_to_func_t) _move_to_nil; - funcs->line_to = (hb_draw_line_to_func_t) _line_to_nil; - funcs->quadratic_to = (hb_draw_quadratic_to_func_t) _quadratic_to_nil; - funcs->is_quadratic_to_set = false; - funcs->cubic_to = (hb_draw_cubic_to_func_t) _cubic_to_nil; - funcs->close_path = (hb_draw_close_path_func_t) _close_path_nil; - return funcs; + return hb_object_is_immutable (dfuncs); } + /** - * hb_draw_funcs_reference: - * @funcs: draw functions + * hb_draw_move_to: + * @dfuncs: draw functions + * @draw_data: associated draw data passed by the caller + * @st: current draw state + * @to_x: X component of target point + * @to_y: Y component of target point * - * Add to callbacks object refcount. + * Perform a "move-to" draw operation. * - * Returns: The same object. - * Since: EXPERIMENTAL + * Since: 4.0.0 **/ -hb_draw_funcs_t * -hb_draw_funcs_reference (hb_draw_funcs_t *funcs) +void +hb_draw_move_to (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + float to_x, float to_y) { - return hb_object_reference (funcs); + dfuncs->move_to (draw_data, *st, + to_x, to_y); } /** - * hb_draw_funcs_destroy: - * @funcs: draw functions + * hb_draw_line_to: + * @dfuncs: draw functions + * @draw_data: associated draw data passed by the caller + * @st: current draw state + * @to_x: X component of target point + * @to_y: Y component of target point * - * Decreases refcount of callbacks object and deletes the object if it reaches - * to zero. + * Perform a "line-to" draw operation. * - * Since: EXPERIMENTAL + * Since: 4.0.0 **/ void -hb_draw_funcs_destroy (hb_draw_funcs_t *funcs) +hb_draw_line_to (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + float to_x, float to_y) { - if (!hb_object_destroy (funcs)) return; - - hb_free (funcs); + dfuncs->line_to (draw_data, *st, + to_x, to_y); } /** - * hb_draw_funcs_make_immutable: - * @funcs: draw functions + * hb_draw_quadratic_to: + * @dfuncs: draw functions + * @draw_data: associated draw data passed by the caller + * @st: current draw state + * @control_x: X component of control point + * @control_y: Y component of control point + * @to_x: X component of target point + * @to_y: Y component of target point * - * Makes funcs object immutable. + * Perform a "quadratic-to" draw operation. * - * Since: EXPERIMENTAL + * Since: 4.0.0 **/ void -hb_draw_funcs_make_immutable (hb_draw_funcs_t *funcs) +hb_draw_quadratic_to (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + float control_x, float control_y, + float to_x, float to_y) { - if (hb_object_is_immutable (funcs)) - return; - - hb_object_make_immutable (funcs); + dfuncs->quadratic_to (draw_data, *st, + control_x, control_y, + to_x, to_y); } /** - * hb_draw_funcs_is_immutable: - * @funcs: draw functions + * hb_draw_cubic_to: + * @dfuncs: draw functions + * @draw_data: associated draw data passed by the caller + * @st: current draw state + * @control1_x: X component of first control point + * @control1_y: Y component of first control point + * @control2_x: X component of second control point + * @control2_y: Y component of second control point + * @to_x: X component of target point + * @to_y: Y component of target point * - * Checks whether funcs is immutable. + * Perform a "cubic-to" draw operation. * - * Returns: If is immutable. - * Since: EXPERIMENTAL + * Since: 4.0.0 **/ -hb_bool_t -hb_draw_funcs_is_immutable (hb_draw_funcs_t *funcs) +void +hb_draw_cubic_to (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + float control1_x, float control1_y, + float control2_x, float control2_y, + float to_x, float to_y) { - return hb_object_is_immutable (funcs); + dfuncs->cubic_to (draw_data, *st, + control1_x, control1_y, + control2_x, control2_y, + to_x, to_y); } /** - * hb_font_draw_glyph: - * @font: a font object - * @glyph: a glyph id - * @funcs: draw callbacks object - * @user_data: parameter you like be passed to the callbacks when are called + * hb_draw_close_path: + * @dfuncs: draw functions + * @draw_data: associated draw data passed by the caller + * @st: current draw state * - * Draw a glyph. + * Perform a "close-path" draw operation. * - * Returns: Whether the font had the glyph and the operation completed successfully. - * Since: EXPERIMENTAL + * Since: 4.0.0 **/ -hb_bool_t -hb_font_draw_glyph (hb_font_t *font, hb_codepoint_t glyph, - const hb_draw_funcs_t *funcs, - void *user_data) +void +hb_draw_close_path (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st) { - if (unlikely (funcs == &Null (hb_draw_funcs_t) || - glyph >= font->face->get_num_glyphs ())) - return false; - - draw_helper_t draw_helper (funcs, user_data); - if (font->face->table.glyf->get_path (font, glyph, draw_helper)) return true; -#ifndef HB_NO_CFF - if (font->face->table.cff1->get_path (font, glyph, draw_helper)) return true; - if (font->face->table.cff2->get_path (font, glyph, draw_helper)) return true; -#endif - - return false; + dfuncs->close_path (draw_data, *st); } -#endif + #endif diff --git a/thirdparty/harfbuzz/src/hb-draw.h b/thirdparty/harfbuzz/src/hb-draw.h index f82cc34842..c45a53212a 100644 --- a/thirdparty/harfbuzz/src/hb-draw.h +++ b/thirdparty/harfbuzz/src/hb-draw.h @@ -33,65 +33,292 @@ HB_BEGIN_DECLS -#ifdef HB_EXPERIMENTAL_API -typedef void (*hb_draw_move_to_func_t) (hb_position_t to_x, hb_position_t to_y, void *user_data); -typedef void (*hb_draw_line_to_func_t) (hb_position_t to_x, hb_position_t to_y, void *user_data); -typedef void (*hb_draw_quadratic_to_func_t) (hb_position_t control_x, hb_position_t control_y, - hb_position_t to_x, hb_position_t to_y, - void *user_data); -typedef void (*hb_draw_cubic_to_func_t) (hb_position_t control1_x, hb_position_t control1_y, - hb_position_t control2_x, hb_position_t control2_y, - hb_position_t to_x, hb_position_t to_y, - void *user_data); -typedef void (*hb_draw_close_path_func_t) (void *user_data); + +/** + * hb_draw_state_t + * @path_open: Whether there is an open path + * @path_start_x: X component of the start of current path + * @path_start_y: Y component of the start of current path + * @current_x: X component of current point + * @current_y: Y component of current point + * + * Current drawing state. + * + * Since: 4.0.0 + **/ +typedef struct hb_draw_state_t { + hb_bool_t path_open; + + float path_start_x; + float path_start_y; + + float current_x; + float current_y; + + /*< private >*/ + hb_var_num_t reserved1; + hb_var_num_t reserved2; + hb_var_num_t reserved3; + hb_var_num_t reserved4; + hb_var_num_t reserved5; + hb_var_num_t reserved6; + hb_var_num_t reserved7; +} hb_draw_state_t; + +/** + * HB_DRAW_STATE_DEFAULT: + * + * The default #hb_draw_state_t at the start of glyph drawing. + */ +#define HB_DRAW_STATE_DEFAULT {0, 0.f, 0.f, 0.f, 0.f, {0.}, {0.}, {0.}} + /** * hb_draw_funcs_t: * * Glyph draw callbacks. * - * _move_to, _line_to and _cubic_to calls are necessary to be defined but we - * translate _quadratic_to calls to _cubic_to if the callback isn't defined. + * #hb_draw_move_to_func_t, #hb_draw_line_to_func_t and + * #hb_draw_cubic_to_func_t calls are necessary to be defined but we translate + * #hb_draw_quadratic_to_func_t calls to #hb_draw_cubic_to_func_t if the + * callback isn't defined. * - * Since: EXPERIMENTAL + * Since: 4.0.0 **/ + typedef struct hb_draw_funcs_t hb_draw_funcs_t; + +/** + * hb_draw_move_to_func_t: + * @dfuncs: draw functions object + * @draw_data: The data accompanying the draw functions + * @st: current draw state + * @to_x: X component of target point + * @to_y: Y component of target point + * @user_data: User data pointer passed by the caller + * + * A virtual method for the #hb_draw_funcs_t to perform a "move-to" draw + * operation. + * + * Since: 4.0.0 + * + **/ +typedef void (*hb_draw_move_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + float to_x, float to_y, + void *user_data); + +/** + * hb_draw_line_to_func_t: + * @dfuncs: draw functions object + * @draw_data: The data accompanying the draw functions + * @st: current draw state + * @to_x: X component of target point + * @to_y: Y component of target point + * @user_data: User data pointer passed by the caller + * + * A virtual method for the #hb_draw_funcs_t to perform a "line-to" draw + * operation. + * + * Since: 4.0.0 + * + **/ +typedef void (*hb_draw_line_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + float to_x, float to_y, + void *user_data); + +/** + * hb_draw_quadratic_to_func_t: + * @dfuncs: draw functions object + * @draw_data: The data accompanying the draw functions + * @st: current draw state + * @control_x: X component of control point + * @control_y: Y component of control point + * @to_x: X component of target point + * @to_y: Y component of target point + * @user_data: User data pointer passed by the caller + * + * A virtual method for the #hb_draw_funcs_t to perform a "quadratic-to" draw + * operation. + * + * Since: 4.0.0 + * + **/ +typedef void (*hb_draw_quadratic_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + float control_x, float control_y, + float to_x, float to_y, + void *user_data); + +/** + * hb_draw_cubic_to_func_t: + * @dfuncs: draw functions object + * @draw_data: The data accompanying the draw functions + * @st: current draw state + * @control1_x: X component of first control point + * @control1_y: Y component of first control point + * @control2_x: X component of second control point + * @control2_y: Y component of second control point + * @to_x: X component of target point + * @to_y: Y component of target point + * @user_data: User data pointer passed by the caller + * + * A virtual method for the #hb_draw_funcs_t to perform a "cubic-to" draw + * operation. + * + * Since: 4.0.0 + * + **/ +typedef void (*hb_draw_cubic_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + float control1_x, float control1_y, + float control2_x, float control2_y, + float to_x, float to_y, + void *user_data); + +/** + * hb_draw_close_path_func_t: + * @dfuncs: draw functions object + * @draw_data: The data accompanying the draw functions + * @st: current draw state + * @user_data: User data pointer passed by the caller + * + * A virtual method for the #hb_draw_funcs_t to perform a "close-path" draw + * operation. + * + * Since: 4.0.0 + * + **/ +typedef void (*hb_draw_close_path_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + void *user_data); + +/** + * hb_draw_funcs_set_move_to_func: + * @dfuncs: draw functions object + * @func: (closure user_data) (destroy destroy) (scope notified): move-to callback + * @user_data: Data to pass to @func + * @destroy: (nullable): The function to call when @user_data is not needed anymore + * + * Sets move-to callback to the draw functions object. + * + * Since: 4.0.0 + **/ HB_EXTERN void -hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *funcs, - hb_draw_move_to_func_t move_to); +hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *dfuncs, + hb_draw_move_to_func_t func, + void *user_data, hb_destroy_func_t destroy); +/** + * hb_draw_funcs_set_line_to_func: + * @dfuncs: draw functions object + * @func: (closure user_data) (destroy destroy) (scope notified): line-to callback + * @user_data: Data to pass to @func + * @destroy: (nullable): The function to call when @user_data is not needed anymore + * + * Sets line-to callback to the draw functions object. + * + * Since: 4.0.0 + **/ HB_EXTERN void -hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *funcs, - hb_draw_line_to_func_t line_to); +hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *dfuncs, + hb_draw_line_to_func_t func, + void *user_data, hb_destroy_func_t destroy); +/** + * hb_draw_funcs_set_quadratic_to_func: + * @dfuncs: draw functions object + * @func: (closure user_data) (destroy destroy) (scope notified): quadratic-to callback + * @user_data: Data to pass to @func + * @destroy: (nullable): The function to call when @user_data is not needed anymore + * + * Sets quadratic-to callback to the draw functions object. + * + * Since: 4.0.0 + **/ HB_EXTERN void -hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *funcs, - hb_draw_quadratic_to_func_t quadratic_to); +hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *dfuncs, + hb_draw_quadratic_to_func_t func, + void *user_data, hb_destroy_func_t destroy); +/** + * hb_draw_funcs_set_cubic_to_func: + * @dfuncs: draw functions + * @func: (closure user_data) (destroy destroy) (scope notified): cubic-to callback + * @user_data: Data to pass to @func + * @destroy: (nullable): The function to call when @user_data is not needed anymore + * + * Sets cubic-to callback to the draw functions object. + * + * Since: 4.0.0 + **/ HB_EXTERN void -hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *funcs, - hb_draw_cubic_to_func_t cubic_to); +hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *dfuncs, + hb_draw_cubic_to_func_t func, + void *user_data, hb_destroy_func_t destroy); +/** + * hb_draw_funcs_set_close_path_func: + * @dfuncs: draw functions object + * @func: (closure user_data) (destroy destroy) (scope notified): close-path callback + * @user_data: Data to pass to @func + * @destroy: (nullable): The function to call when @user_data is not needed anymore + * + * Sets close-path callback to the draw functions object. + * + * Since: 4.0.0 + **/ HB_EXTERN void -hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *funcs, - hb_draw_close_path_func_t close_path); +hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *dfuncs, + hb_draw_close_path_func_t func, + void *user_data, hb_destroy_func_t destroy); + HB_EXTERN hb_draw_funcs_t * hb_draw_funcs_create (void); HB_EXTERN hb_draw_funcs_t * -hb_draw_funcs_reference (hb_draw_funcs_t *funcs); +hb_draw_funcs_reference (hb_draw_funcs_t *dfuncs); HB_EXTERN void -hb_draw_funcs_destroy (hb_draw_funcs_t *funcs); +hb_draw_funcs_destroy (hb_draw_funcs_t *dfuncs); HB_EXTERN void -hb_draw_funcs_make_immutable (hb_draw_funcs_t *funcs); +hb_draw_funcs_make_immutable (hb_draw_funcs_t *dfuncs); HB_EXTERN hb_bool_t -hb_draw_funcs_is_immutable (hb_draw_funcs_t *funcs); -#endif +hb_draw_funcs_is_immutable (hb_draw_funcs_t *dfuncs); + + +HB_EXTERN void +hb_draw_move_to (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + float to_x, float to_y); + +HB_EXTERN void +hb_draw_line_to (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + float to_x, float to_y); + +HB_EXTERN void +hb_draw_quadratic_to (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + float control_x, float control_y, + float to_x, float to_y); + +HB_EXTERN void +hb_draw_cubic_to (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + float control1_x, float control1_y, + float control2_x, float control2_y, + float to_x, float to_y); + +HB_EXTERN void +hb_draw_close_path (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st); + HB_END_DECLS diff --git a/thirdparty/harfbuzz/src/hb-draw.hh b/thirdparty/harfbuzz/src/hb-draw.hh index 2aa0a5b4db..28bc9218e1 100644 --- a/thirdparty/harfbuzz/src/hb-draw.hh +++ b/thirdparty/harfbuzz/src/hb-draw.hh @@ -27,113 +27,205 @@ #include "hb.hh" -#ifdef HB_EXPERIMENTAL_API -struct hb_draw_funcs_t -{ - hb_object_header_t header; - hb_draw_move_to_func_t move_to; - hb_draw_line_to_func_t line_to; - hb_draw_quadratic_to_func_t quadratic_to; - bool is_quadratic_to_set; - hb_draw_cubic_to_func_t cubic_to; - hb_draw_close_path_func_t close_path; -}; +/* + * hb_draw_funcs_t + */ + +#define HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS \ + HB_DRAW_FUNC_IMPLEMENT (move_to) \ + HB_DRAW_FUNC_IMPLEMENT (line_to) \ + HB_DRAW_FUNC_IMPLEMENT (quadratic_to) \ + HB_DRAW_FUNC_IMPLEMENT (cubic_to) \ + HB_DRAW_FUNC_IMPLEMENT (close_path) \ + /* ^--- Add new callbacks here */ -struct draw_helper_t +struct hb_draw_funcs_t { - draw_helper_t (const hb_draw_funcs_t *funcs_, void *user_data_) - { - funcs = funcs_; - user_data = user_data_; - path_open = false; - path_start_x = current_x = path_start_y = current_y = 0; - } - ~draw_helper_t () { end_path (); } + hb_object_header_t header; - void move_to (hb_position_t x, hb_position_t y) + struct { +#define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_func_t name; + HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_DRAW_FUNC_IMPLEMENT + } func; + + struct { +#define HB_DRAW_FUNC_IMPLEMENT(name) void *name; + HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_DRAW_FUNC_IMPLEMENT + } user_data; + + struct { +#define HB_DRAW_FUNC_IMPLEMENT(name) hb_destroy_func_t name; + HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_DRAW_FUNC_IMPLEMENT + } destroy; + + void emit_move_to (void *draw_data, hb_draw_state_t &st, + float to_x, float to_y) + { func.move_to (this, draw_data, &st, + to_x, to_y, + user_data.move_to); } + void emit_line_to (void *draw_data, hb_draw_state_t &st, + float to_x, float to_y) + { func.line_to (this, draw_data, &st, + to_x, to_y, + user_data.line_to); } + void emit_quadratic_to (void *draw_data, hb_draw_state_t &st, + float control_x, float control_y, + float to_x, float to_y) + { func.quadratic_to (this, draw_data, &st, + control_x, control_y, + to_x, to_y, + user_data.quadratic_to); } + void emit_cubic_to (void *draw_data, hb_draw_state_t &st, + float control1_x, float control1_y, + float control2_x, float control2_y, + float to_x, float to_y) + { func.cubic_to (this, draw_data, &st, + control1_x, control1_y, + control2_x, control2_y, + to_x, to_y, + user_data.cubic_to); } + void emit_close_path (void *draw_data, hb_draw_state_t &st) + { func.close_path (this, draw_data, &st, + user_data.close_path); } + + + void move_to (void *draw_data, hb_draw_state_t &st, + float to_x, float to_y) { - if (path_open) end_path (); - current_x = path_start_x = x; - current_y = path_start_y = y; + if (st.path_open) close_path (draw_data, st); + st.current_x = to_x; + st.current_y = to_y; } - void line_to (hb_position_t x, hb_position_t y) + void line_to (void *draw_data, hb_draw_state_t &st, + float to_x, float to_y) { - if (equal_to_current (x, y)) return; - if (!path_open) start_path (); - funcs->line_to (x, y, user_data); - current_x = x; - current_y = y; + if (!st.path_open) start_path (draw_data, st); + emit_line_to (draw_data, st, to_x, to_y); + st.current_x = to_x; + st.current_y = to_y; } void - quadratic_to (hb_position_t control_x, hb_position_t control_y, - hb_position_t to_x, hb_position_t to_y) + quadratic_to (void *draw_data, hb_draw_state_t &st, + float control_x, float control_y, + float to_x, float to_y) { - if (equal_to_current (control_x, control_y) && equal_to_current (to_x, to_y)) - return; - if (!path_open) start_path (); - if (funcs->is_quadratic_to_set) - funcs->quadratic_to (control_x, control_y, to_x, to_y, user_data); - else - funcs->cubic_to (roundf ((current_x + 2.f * control_x) / 3.f), - roundf ((current_y + 2.f * control_y) / 3.f), - roundf ((to_x + 2.f * control_x) / 3.f), - roundf ((to_y + 2.f * control_y) / 3.f), - to_x, to_y, user_data); - current_x = to_x; - current_y = to_y; + if (!st.path_open) start_path (draw_data, st); + emit_quadratic_to (draw_data, st, control_x, control_y, to_x, to_y); + st.current_x = to_x; + st.current_y = to_y; } void - cubic_to (hb_position_t control1_x, hb_position_t control1_y, - hb_position_t control2_x, hb_position_t control2_y, - hb_position_t to_x, hb_position_t to_y) + cubic_to (void *draw_data, hb_draw_state_t &st, + float control1_x, float control1_y, + float control2_x, float control2_y, + float to_x, float to_y) { - if (equal_to_current (control1_x, control1_y) && - equal_to_current (control2_x, control2_y) && - equal_to_current (to_x, to_y)) - return; - if (!path_open) start_path (); - funcs->cubic_to (control1_x, control1_y, control2_x, control2_y, to_x, to_y, user_data); - current_x = to_x; - current_y = to_y; + if (!st.path_open) start_path (draw_data, st); + emit_cubic_to (draw_data, st, control1_x, control1_y, control2_x, control2_y, to_x, to_y); + st.current_x = to_x; + st.current_y = to_y; } - void end_path () + void + close_path (void *draw_data, hb_draw_state_t &st) { - if (path_open) + if (st.path_open) { - if ((path_start_x != current_x) || (path_start_y != current_y)) - funcs->line_to (path_start_x, path_start_y, user_data); - funcs->close_path (user_data); + if ((st.path_start_x != st.current_x) || (st.path_start_y != st.current_y)) + emit_line_to (draw_data, st, st.path_start_x, st.path_start_y); + emit_close_path (draw_data, st); } - path_open = false; - path_start_x = current_x = path_start_y = current_y = 0; + st.path_open = false; + st.path_start_x = st.current_x = st.path_start_y = st.current_y = 0; } protected: - bool equal_to_current (hb_position_t x, hb_position_t y) - { return current_x == x && current_y == y; } - void start_path () + void start_path (void *draw_data, hb_draw_state_t &st) { - if (path_open) end_path (); - path_open = true; - funcs->move_to (path_start_x, path_start_y, user_data); + assert (!st.path_open); + emit_move_to (draw_data, st, st.current_x, st.current_y); + st.path_open = true; + st.path_start_x = st.current_x; + st.path_start_y = st.current_y; } +}; +DECLARE_NULL_INSTANCE (hb_draw_funcs_t); - hb_position_t path_start_x; - hb_position_t path_start_y; +struct hb_draw_session_t +{ + hb_draw_session_t (hb_draw_funcs_t *funcs_, void *draw_data_, float slant_ = 0.f) + : slant {slant_}, not_slanted {slant == 0.f}, + funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT + {} - hb_position_t current_x; - hb_position_t current_y; + ~hb_draw_session_t () { close_path (); } - bool path_open; - const hb_draw_funcs_t *funcs; - void *user_data; + void move_to (float to_x, float to_y) + { + if (likely (not_slanted)) + funcs->move_to (draw_data, st, + to_x, to_y); + else + funcs->move_to (draw_data, st, + to_x + to_y * slant, to_y); + } + void line_to (float to_x, float to_y) + { + if (likely (not_slanted)) + funcs->line_to (draw_data, st, + to_x, to_y); + else + funcs->line_to (draw_data, st, + to_x + to_y * slant, to_y); + } + void + quadratic_to (float control_x, float control_y, + float to_x, float to_y) + { + if (likely (not_slanted)) + funcs->quadratic_to (draw_data, st, + control_x, control_y, + to_x, to_y); + else + funcs->quadratic_to (draw_data, st, + control_x + control_y * slant, control_y, + to_x + to_y * slant, to_y); + } + void + cubic_to (float control1_x, float control1_y, + float control2_x, float control2_y, + float to_x, float to_y) + { + if (likely (not_slanted)) + funcs->cubic_to (draw_data, st, + control1_x, control1_y, + control2_x, control2_y, + to_x, to_y); + else + funcs->cubic_to (draw_data, st, + control1_x + control1_y * slant, control1_y, + control2_x + control2_y * slant, control2_y, + to_x + to_y * slant, to_y); + } + void close_path () + { + funcs->close_path (draw_data, st); + } + + protected: + float slant; + bool not_slanted; + hb_draw_funcs_t *funcs; + void *draw_data; + hb_draw_state_t st; }; -#endif #endif /* HB_DRAW_HH */ diff --git a/thirdparty/harfbuzz/src/hb-font.cc b/thirdparty/harfbuzz/src/hb-font.cc index 350fcac139..db05f017a5 100644 --- a/thirdparty/harfbuzz/src/hb-font.cc +++ b/thirdparty/harfbuzz/src/hb-font.cc @@ -29,6 +29,7 @@ #include "hb.hh" #include "hb-font.hh" +#include "hb-draw.hh" #include "hb-machinery.hh" #include "hb-ot.h" @@ -501,6 +502,136 @@ hb_font_get_glyph_from_name_default (hb_font_t *font, return font->parent->get_glyph_from_name (name, len, glyph); } +static void +hb_font_get_glyph_shape_nil (hb_font_t *font HB_UNUSED, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, + void *draw_data, + void *user_data HB_UNUSED) +{ +} + + +typedef struct hb_font_get_glyph_shape_default_adaptor_t { + hb_draw_funcs_t *draw_funcs; + void *draw_data; + float x_scale; + float y_scale; +} hb_font_get_glyph_shape_default_adaptor_t; + +static void +hb_draw_move_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, + void *draw_data, + hb_draw_state_t *st, + float to_x, float to_y, + void *user_data HB_UNUSED) +{ + hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data; + float x_scale = adaptor->x_scale; + float y_scale = adaptor->y_scale; + + adaptor->draw_funcs->emit_move_to (adaptor->draw_data, *st, + x_scale * to_x, y_scale * to_y); +} + +static void +hb_draw_line_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data, + hb_draw_state_t *st, + float to_x, float to_y, + void *user_data HB_UNUSED) +{ + hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data; + float x_scale = adaptor->x_scale; + float y_scale = adaptor->y_scale; + + st->current_x *= x_scale; + st->current_y *= y_scale; + + adaptor->draw_funcs->emit_line_to (adaptor->draw_data, *st, + x_scale * to_x, y_scale * to_y); +} + +static void +hb_draw_quadratic_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data, + hb_draw_state_t *st, + float control_x, float control_y, + float to_x, float to_y, + void *user_data HB_UNUSED) +{ + hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data; + float x_scale = adaptor->x_scale; + float y_scale = adaptor->y_scale; + + st->current_x *= x_scale; + st->current_y *= y_scale; + + adaptor->draw_funcs->emit_quadratic_to (adaptor->draw_data, *st, + x_scale * control_x, y_scale * control_y, + x_scale * to_x, y_scale * to_y); +} + +static void +hb_draw_cubic_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data, + hb_draw_state_t *st, + float control1_x, float control1_y, + float control2_x, float control2_y, + float to_x, float to_y, + void *user_data HB_UNUSED) +{ + hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data; + float x_scale = adaptor->x_scale; + float y_scale = adaptor->y_scale; + + st->current_x *= x_scale; + st->current_y *= y_scale; + + adaptor->draw_funcs->emit_cubic_to (adaptor->draw_data, *st, + x_scale * control1_x, y_scale * control1_y, + x_scale * control2_x, y_scale * control2_y, + x_scale * to_x, y_scale * to_y); +} + +static void +hb_draw_close_path_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data, + hb_draw_state_t *st, + void *user_data HB_UNUSED) +{ + hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data; + + adaptor->draw_funcs->emit_close_path (adaptor->draw_data, *st); +} + +static const hb_draw_funcs_t _hb_draw_funcs_default = { + HB_OBJECT_HEADER_STATIC, + + { +#define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_default, + HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_DRAW_FUNC_IMPLEMENT + } +}; + +static void +hb_font_get_glyph_shape_default (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, + void *draw_data, + void *user_data HB_UNUSED) +{ + hb_font_get_glyph_shape_default_adaptor_t adaptor = { + draw_funcs, + draw_data, + (float) font->x_scale / (float) font->parent->x_scale, + (float) font->y_scale / (float) font->parent->y_scale + }; + + font->parent->get_glyph_shape (glyph, + const_cast<hb_draw_funcs_t *> (&_hb_draw_funcs_default), + &adaptor); +} + DEFINE_NULL_INSTANCE (hb_font_funcs_t) = { HB_OBJECT_HEADER_STATIC, @@ -1168,6 +1299,26 @@ hb_font_get_glyph_from_name (hb_font_t *font, return font->get_glyph_from_name (name, len, glyph); } +/** + * hb_font_get_glyph_shape: + * @font: #hb_font_t to work upon + * @glyph: : The glyph ID + * @dfuncs: #hb_draw_funcs_t to draw to + * @draw_data: User data to pass to draw callbacks + * + * Fetches the glyph shape that corresponds to a glyph in the specified @font. + * The shape is returned by way of calls to the callsbacks of the @dfuncs + * objects, with @draw_data passed to them. + * + * Since: 4.0.0 + **/ +void +hb_font_get_glyph_shape (hb_font_t *font, + hb_codepoint_t glyph, + hb_draw_funcs_t *dfuncs, void *draw_data) +{ + font->get_glyph_shape (glyph, dfuncs, draw_data); +} /* A bit higher-level, and with fallback */ @@ -1190,7 +1341,7 @@ hb_font_get_extents_for_direction (hb_font_t *font, hb_direction_t direction, hb_font_extents_t *extents) { - return font->get_extents_for_direction (direction, extents); + font->get_extents_for_direction (direction, extents); } /** * hb_font_get_glyph_advance_for_direction: @@ -1215,7 +1366,7 @@ hb_font_get_glyph_advance_for_direction (hb_font_t *font, hb_position_t *x, hb_position_t *y) { - return font->get_glyph_advance_for_direction (glyph, direction, x, y); + font->get_glyph_advance_for_direction (glyph, direction, x, y); } /** * hb_font_get_glyph_advances_for_direction: @@ -2044,12 +2195,16 @@ hb_font_get_ptem (hb_font_t *font) * @slant: synthetic slant value. * * Sets the "synthetic slant" of a font. By default is zero. - * Synthetic slant is the graphical skew that the renderer - * applies to the font at rendering time. + * Synthetic slant is the graphical skew applied to the font + * at rendering time. * * HarfBuzz needs to know this value to adjust shaping results, * metrics, and style values to match the slanted rendering. * + * <note>Note: The glyph shape fetched via the + * hb_font_get_glyph_shape() is slanted to reflect this value + * as well.</note> + * * <note>Note: The slant value is a ratio. For example, a * 20% slant would be represented as a 0.2 value.</note> * diff --git a/thirdparty/harfbuzz/src/hb-font.h b/thirdparty/harfbuzz/src/hb-font.h index a3bbb2e37b..9548857535 100644 --- a/thirdparty/harfbuzz/src/hb-font.h +++ b/thirdparty/harfbuzz/src/hb-font.h @@ -511,6 +511,25 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void * hb_codepoint_t *glyph, void *user_data); +/** + * hb_font_get_glyph_shape_func_t: + * @font: #hb_font_t to work upon + * @font_data: @font user data pointer + * @glyph: The glyph ID to query + * @draw_funcs: The draw functions to send the shape data to + * @draw_data: The data accompanying the draw functions + * @user_data: User data pointer passed by the caller + * + * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. + * + * Since: 4.0.0 + * + **/ +typedef void (*hb_font_get_glyph_shape_func_t) (hb_font_t *font, void *font_data, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, void *draw_data, + void *user_data); + /* func setters */ @@ -770,6 +789,22 @@ hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_from_name_func_t func, void *user_data, hb_destroy_func_t destroy); +/** + * hb_font_funcs_set_glyph_shape_func: + * @ffuncs: A font-function structure + * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign + * @user_data: Data to pass to @func + * @destroy: (nullable): The function to call when @user_data is not needed anymore + * + * Sets the implementation function for #hb_font_get_glyph_shape_func_t. + * + * Since: 4.0.0 + **/ +HB_EXTERN void +hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_shape_func_t func, + void *user_data, hb_destroy_func_t destroy); + /* func dispatch */ HB_EXTERN hb_bool_t @@ -850,6 +885,11 @@ hb_font_get_glyph_from_name (hb_font_t *font, const char *name, int len, /* -1 means nul-terminated */ hb_codepoint_t *glyph); +HB_EXTERN void +hb_font_get_glyph_shape (hb_font_t *font, + hb_codepoint_t glyph, + hb_draw_funcs_t *dfuncs, void *draw_data); + /* high-level funcs, with fallback */ @@ -1056,11 +1096,6 @@ HB_EXTERN void hb_font_set_var_named_instance (hb_font_t *font, unsigned instance_index); -#ifdef HB_EXPERIMENTAL_API -HB_EXTERN hb_bool_t -hb_font_draw_glyph (hb_font_t *font, hb_codepoint_t glyph, - const hb_draw_funcs_t *funcs, void *user_data); -#endif HB_END_DECLS diff --git a/thirdparty/harfbuzz/src/hb-font.hh b/thirdparty/harfbuzz/src/hb-font.hh index 0d73589e8c..70311b4a85 100644 --- a/thirdparty/harfbuzz/src/hb-font.hh +++ b/thirdparty/harfbuzz/src/hb-font.hh @@ -57,6 +57,7 @@ HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \ HB_FONT_FUNC_IMPLEMENT (glyph_name) \ HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \ + HB_FONT_FUNC_IMPLEMENT (glyph_shape) \ /* ^--- Add new callbacks here */ struct hb_font_funcs_t @@ -140,6 +141,8 @@ struct hb_font_t hb_position_t em_scalef_y (float v) { return em_scalef (v, y_scale); } float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); } float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); } + float em_fscalef_x (float v) { return em_fscalef (v, x_scale); } + float em_fscalef_y (float v) { return em_fscalef (v, y_scale); } hb_position_t em_scale_dir (int16_t v, hb_direction_t direction) { return em_mult (v, dir_mult (direction)); } @@ -373,6 +376,15 @@ struct hb_font_t klass->user_data.glyph_from_name); } + void get_glyph_shape (hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, void *draw_data) + { + klass->get.f.glyph_shape (this, user_data, + glyph, + draw_funcs, draw_data, + klass->user_data.glyph_shape); + } + /* A bit higher-level, and with fallback */ @@ -625,7 +637,9 @@ struct hb_font_t hb_position_t em_mult (int16_t v, int64_t mult) { return (hb_position_t) ((v * mult + 32768) >> 16); } hb_position_t em_scalef (float v, int scale) - { return (hb_position_t) roundf (v * scale / face->get_upem ()); } + { return (hb_position_t) roundf (em_fscalef (v, scale)); } + float em_fscalef (float v, int scale) + { return v * scale / face->get_upem (); } float em_fscale (int16_t v, int scale) { return (float) v * scale / face->get_upem (); } }; diff --git a/thirdparty/harfbuzz/src/hb-ft.cc b/thirdparty/harfbuzz/src/hb-ft.cc index 67691e3ff3..0cfbb22e31 100644 --- a/thirdparty/harfbuzz/src/hb-ft.cc +++ b/thirdparty/harfbuzz/src/hb-ft.cc @@ -33,12 +33,14 @@ #include "hb-ft.h" +#include "hb-draw.hh" #include "hb-font.hh" #include "hb-machinery.hh" #include "hb-cache.hh" #include FT_ADVANCES_H #include FT_MULTIPLE_MASTERS_H +#include FT_OUTLINE_H #include FT_TRUETYPE_TABLES_H @@ -380,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 @@ -565,6 +568,82 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED, return true; } +#ifndef HB_NO_DRAW + +static int +_hb_ft_move_to (const FT_Vector *to, + hb_draw_session_t *drawing) +{ + drawing->move_to (to->x, to->y); + return FT_Err_Ok; +} + +static int +_hb_ft_line_to (const FT_Vector *to, + hb_draw_session_t *drawing) +{ + drawing->line_to (to->x, to->y); + return FT_Err_Ok; +} + +static int +_hb_ft_conic_to (const FT_Vector *control, + const FT_Vector *to, + hb_draw_session_t *drawing) +{ + drawing->quadratic_to (control->x, control->y, + to->x, to->y); + return FT_Err_Ok; +} + +static int +_hb_ft_cubic_to (const FT_Vector *control1, + const FT_Vector *control2, + const FT_Vector *to, + hb_draw_session_t *drawing) +{ + drawing->cubic_to (control1->x, control1->y, + control2->x, control2->y, + to->x, to->y); + return FT_Err_Ok; +} + +static void +hb_ft_get_glyph_shape (hb_font_t *font HB_UNUSED, + void *font_data, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, void *draw_data, + void *user_data HB_UNUSED) +{ + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + hb_lock_t lock (ft_font->lock); + FT_Face ft_face = ft_font->ft_face; + + if (unlikely (FT_Load_Glyph (ft_face, glyph, + FT_LOAD_NO_BITMAP | ft_font->load_flags))) + return; + + if (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE) + return; + + const FT_Outline_Funcs outline_funcs = { + (FT_Outline_MoveToFunc) _hb_ft_move_to, + (FT_Outline_LineToFunc) _hb_ft_line_to, + (FT_Outline_ConicToFunc) _hb_ft_conic_to, + (FT_Outline_CubicToFunc) _hb_ft_cubic_to, + 0, /* shift */ + 0, /* delta */ + }; + + hb_draw_session_t draw_session (draw_funcs, draw_data, font->slant_xy); + + FT_Outline_Decompose (&ft_face->glyph->outline, + &outline_funcs, + &draw_session); +} +#endif + + static inline void free_static_ft_funcs (); static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft_font_funcs_lazy_loader_t> @@ -596,6 +675,10 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, nullptr, nullptr); hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, nullptr, nullptr); +#ifndef HB_NO_DRAW + hb_font_funcs_set_glyph_shape_func (funcs, hb_ft_get_glyph_shape, nullptr, nullptr); +#endif + hb_font_funcs_make_immutable (funcs); hb_atexit (free_static_ft_funcs); diff --git a/thirdparty/harfbuzz/src/hb-gobject-structs.cc b/thirdparty/harfbuzz/src/hb-gobject-structs.cc index 540b11f911..ef13f1e966 100644 --- a/thirdparty/harfbuzz/src/hb-gobject-structs.cc +++ b/thirdparty/harfbuzz/src/hb-gobject-structs.cc @@ -90,6 +90,7 @@ hb_gobject_##name##_get_type () \ HB_DEFINE_OBJECT_TYPE (buffer) HB_DEFINE_OBJECT_TYPE (blob) +HB_DEFINE_OBJECT_TYPE (draw_funcs) HB_DEFINE_OBJECT_TYPE (face) HB_DEFINE_OBJECT_TYPE (font) HB_DEFINE_OBJECT_TYPE (font_funcs) diff --git a/thirdparty/harfbuzz/src/hb-gobject-structs.h b/thirdparty/harfbuzz/src/hb-gobject-structs.h index 63467f80df..3914a2431a 100644 --- a/thirdparty/harfbuzz/src/hb-gobject-structs.h +++ b/thirdparty/harfbuzz/src/hb-gobject-structs.h @@ -49,6 +49,10 @@ hb_gobject_buffer_get_type (void); #define HB_GOBJECT_TYPE_BUFFER (hb_gobject_buffer_get_type ()) HB_EXTERN GType +hb_gobject_draw_funcs_get_type (void); +#define HB_GOBJECT_TYPE_DRAW_FUNCS (hb_gobject_draw_funcs_get_type ()) + +HB_EXTERN GType hb_gobject_face_get_type (void); #define HB_GOBJECT_TYPE_FACE (hb_gobject_face_get_type ()) diff --git a/thirdparty/harfbuzz/src/hb-machinery.hh b/thirdparty/harfbuzz/src/hb-machinery.hh index 5046ac1933..e52a6a4124 100644 --- a/thirdparty/harfbuzz/src/hb-machinery.hh +++ b/thirdparty/harfbuzz/src/hb-machinery.hh @@ -194,7 +194,8 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData> } const Returned * operator -> () const { return get (); } - const Returned & operator * () const { return *get (); } + template <typename U = Returned, hb_enable_if (!hb_is_same (U, void))> + const U & operator * () const { return *get (); } explicit operator bool () const { return get_stored () != Funcs::get_null (); } template <typename C> operator const C * () const { return get (); } @@ -272,14 +273,19 @@ struct hb_face_lazy_loader_t : hb_lazy_loader_t<T, hb_face_lazy_loader_t<T, WheresFace>, hb_face_t, WheresFace> {}; -template <typename T, unsigned int WheresFace> +template <typename T, unsigned int WheresFace, bool core=false> struct hb_table_lazy_loader_t : hb_lazy_loader_t<T, - hb_table_lazy_loader_t<T, WheresFace>, + hb_table_lazy_loader_t<T, WheresFace, core>, hb_face_t, WheresFace, hb_blob_t> { static hb_blob_t *create (hb_face_t *face) - { return hb_sanitize_context_t ().reference_table<T> (face); } + { + auto c = hb_sanitize_context_t (); + if (core) + c.set_num_glyphs (0); // So we don't recurse ad infinitum... + return c.reference_table<T> (face); + } static void destroy (hb_blob_t *p) { hb_blob_destroy (p); } static const hb_blob_t *get_null () diff --git a/thirdparty/harfbuzz/src/hb-ot-cff1-table.cc b/thirdparty/harfbuzz/src/hb-ot-cff1-table.cc index 3298fa35ae..df4554ac00 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cff1-table.cc +++ b/thirdparty/harfbuzz/src/hb-ot-cff1-table.cc @@ -442,13 +442,12 @@ bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph return true; } -#ifdef HB_EXPERIMENTAL_API struct cff1_path_param_t { cff1_path_param_t (const OT::cff1::accelerator_t *cff_, hb_font_t *font_, - draw_helper_t &draw_helper_, point_t *delta_) + hb_draw_session_t &draw_session_, point_t *delta_) { - draw_helper = &draw_helper_; + draw_session = &draw_session_; cff = cff_; font = font_; delta = delta_; @@ -458,14 +457,14 @@ struct cff1_path_param_t { point_t point = p; if (delta) point.move (*delta); - draw_helper->move_to (font->em_scalef_x (point.x.to_real ()), font->em_scalef_y (point.y.to_real ())); + draw_session->move_to (font->em_fscalef_x (point.x.to_real ()), font->em_fscalef_y (point.y.to_real ())); } void line_to (const point_t &p) { point_t point = p; if (delta) point.move (*delta); - draw_helper->line_to (font->em_scalef_x (point.x.to_real ()), font->em_scalef_y (point.y.to_real ())); + draw_session->line_to (font->em_fscalef_x (point.x.to_real ()), font->em_fscalef_y (point.y.to_real ())); } void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3) @@ -477,15 +476,15 @@ struct cff1_path_param_t point2.move (*delta); point3.move (*delta); } - draw_helper->cubic_to (font->em_scalef_x (point1.x.to_real ()), font->em_scalef_y (point1.y.to_real ()), - font->em_scalef_x (point2.x.to_real ()), font->em_scalef_y (point2.y.to_real ()), - font->em_scalef_x (point3.x.to_real ()), font->em_scalef_y (point3.y.to_real ())); + draw_session->cubic_to (font->em_fscalef_x (point1.x.to_real ()), font->em_fscalef_y (point1.y.to_real ()), + font->em_fscalef_x (point2.x.to_real ()), font->em_fscalef_y (point2.y.to_real ()), + font->em_fscalef_x (point3.x.to_real ()), font->em_fscalef_y (point3.y.to_real ())); } - void end_path () { draw_helper->end_path (); } + void end_path () { draw_session->close_path (); } hb_font_t *font; - draw_helper_t *draw_helper; + hb_draw_session_t *draw_session; point_t *delta; const OT::cff1::accelerator_t *cff; @@ -513,7 +512,7 @@ struct cff1_path_procs_path_t : path_procs_t<cff1_path_procs_path_t, cff1_cs_int }; static bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph, - draw_helper_t &draw_helper, bool in_seac = false, point_t *delta = nullptr); + hb_draw_session_t &draw_session, bool in_seac = false, point_t *delta = nullptr); struct cff1_cs_opset_path_t : cff1_cs_opset_t<cff1_cs_opset_path_t, cff1_path_param_t, cff1_path_procs_path_t> { @@ -530,14 +529,14 @@ struct cff1_cs_opset_path_t : cff1_cs_opset_t<cff1_cs_opset_path_t, cff1_path_pa hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ()); if (unlikely (!(!env.in_seac && base && accent - && _get_path (param.cff, param.font, base, *param.draw_helper, true) - && _get_path (param.cff, param.font, accent, *param.draw_helper, true, &delta)))) + && _get_path (param.cff, param.font, base, *param.draw_session, true) + && _get_path (param.cff, param.font, accent, *param.draw_session, true, &delta)))) env.set_error (); } }; bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph, - draw_helper_t &draw_helper, bool in_seac, point_t *delta) + hb_draw_session_t &draw_session, bool in_seac, point_t *delta) { if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false; @@ -546,7 +545,7 @@ bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoin const byte_str_t str = (*cff->charStrings)[glyph]; interp.env.init (str, *cff, fd); interp.env.set_in_seac (in_seac); - cff1_path_param_t param (cff, font, draw_helper, delta); + cff1_path_param_t param (cff, font, draw_session, delta); if (unlikely (!interp.interpret (param))) return false; /* Let's end the path specially since it is called inside seac also */ @@ -555,16 +554,15 @@ bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoin return true; } -bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const +bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const { #ifdef HB_NO_OT_FONT_CFF /* XXX Remove check when this code moves to .hh file. */ return true; #endif - return _get_path (this, font, glyph, draw_helper); + return _get_path (this, font, glyph, draw_session); } -#endif struct get_seac_param_t { diff --git a/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh b/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh index 6fb59315c9..542e3f4de3 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh @@ -1347,9 +1347,7 @@ struct cff1 HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const; HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const; -#ifdef HB_EXPERIMENTAL_API - HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const; -#endif + HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const; private: struct gname_t diff --git a/thirdparty/harfbuzz/src/hb-ot-cff2-table.cc b/thirdparty/harfbuzz/src/hb-ot-cff2-table.cc index 879b7cdb23..817fe064ce 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cff2-table.cc +++ b/thirdparty/harfbuzz/src/hb-ot-cff2-table.cc @@ -143,30 +143,29 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font, return true; } -#ifdef HB_EXPERIMENTAL_API struct cff2_path_param_t { - cff2_path_param_t (hb_font_t *font_, draw_helper_t &draw_helper_) + cff2_path_param_t (hb_font_t *font_, hb_draw_session_t &draw_session_) { - draw_helper = &draw_helper_; + draw_session = &draw_session_; font = font_; } void move_to (const point_t &p) - { draw_helper->move_to (font->em_scalef_x (p.x.to_real ()), font->em_scalef_y (p.y.to_real ())); } + { draw_session->move_to (font->em_fscalef_x (p.x.to_real ()), font->em_fscalef_y (p.y.to_real ())); } void line_to (const point_t &p) - { draw_helper->line_to (font->em_scalef_x (p.x.to_real ()), font->em_scalef_y (p.y.to_real ())); } + { draw_session->line_to (font->em_fscalef_x (p.x.to_real ()), font->em_fscalef_y (p.y.to_real ())); } void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3) { - draw_helper->cubic_to (font->em_scalef_x (p1.x.to_real ()), font->em_scalef_y (p1.y.to_real ()), - font->em_scalef_x (p2.x.to_real ()), font->em_scalef_y (p2.y.to_real ()), - font->em_scalef_x (p3.x.to_real ()), font->em_scalef_y (p3.y.to_real ())); + draw_session->cubic_to (font->em_fscalef_x (p1.x.to_real ()), font->em_fscalef_y (p1.y.to_real ()), + font->em_fscalef_x (p2.x.to_real ()), font->em_fscalef_y (p2.y.to_real ()), + font->em_fscalef_x (p3.x.to_real ()), font->em_fscalef_y (p3.y.to_real ())); } protected: - draw_helper_t *draw_helper; + hb_draw_session_t *draw_session; hb_font_t *font; }; @@ -193,7 +192,7 @@ struct cff2_path_procs_path_t : path_procs_t<cff2_path_procs_path_t, cff2_cs_int struct cff2_cs_opset_path_t : cff2_cs_opset_t<cff2_cs_opset_path_t, cff2_path_param_t, cff2_path_procs_path_t> {}; -bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const +bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const { #ifdef HB_NO_OT_FONT_CFF /* XXX Remove check when this code moves to .hh file. */ @@ -206,10 +205,9 @@ bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, d cff2_cs_interpreter_t<cff2_cs_opset_path_t, cff2_path_param_t> interp; const byte_str_t str = (*charStrings)[glyph]; interp.env.init (str, *this, fd, font->coords, font->num_coords); - cff2_path_param_t param (font, draw_helper); + cff2_path_param_t param (font, draw_session); if (unlikely (!interp.interpret (param))) return false; return true; } -#endif #endif diff --git a/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh b/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh index 6e1b01c8fe..b77e7f53fa 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh @@ -515,9 +515,7 @@ struct cff2 HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const; -#ifdef HB_EXPERIMENTAL_API - HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const; -#endif + HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const; }; typedef accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t> accelerator_subset_t; 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-deprecated.h b/thirdparty/harfbuzz/src/hb-ot-deprecated.h index ce6b6fef11..5192ff73e3 100644 --- a/thirdparty/harfbuzz/src/hb-ot-deprecated.h +++ b/thirdparty/harfbuzz/src/hb-ot-deprecated.h @@ -50,6 +50,21 @@ HB_BEGIN_DECLS */ #define HB_MATH_GLYPH_PART_FLAG_EXTENDER HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER +/* https://github.com/harfbuzz/harfbuzz/pull/3417 */ +/** + * HB_OT_MATH_SCRIPT: + * + * Use #HB_SCRIPT_MATH or #HB_OT_TAG_MATH_SCRIPT instead. + * + * <note>Previous versions of this documentation recommended passing + * #HB_OT_MATH_SCRIPT to hb_buffer_set_script() to enable math shaping, but this + * usage is no longer supported. Use #HB_SCRIPT_MATH instead.</note> + * + * Since: 1.3.3 + * Deprecated: 3.4.0 + */ +#define HB_OT_MATH_SCRIPT HB_OT_TAG_MATH_SCRIPT + /* Like hb_ot_layout_table_find_script, but takes zero-terminated array of scripts to test */ HB_EXTERN HB_DEPRECATED_FOR (hb_ot_layout_table_select_script) hb_bool_t diff --git a/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh b/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh index eff09838af..c05034b3bb 100644 --- a/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh +++ b/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh @@ -32,6 +32,11 @@ #define HB_OT_FACE_TABLE_LIST_HH #endif /* HB_OT_FACE_TABLE_LIST_HH */ /* Dummy header guards */ +#ifndef HB_OT_CORE_TABLE +#define HB_OT_CORE_TABLE(Namespace, Type) HB_OT_TABLE (Namespace, Type) +#define _HB_OT_CORE_TABLE_UNDEF +#endif + #ifndef HB_OT_ACCELERATOR #define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type) #define _HB_OT_ACCELERATOR_UNDEF @@ -46,7 +51,8 @@ /* OpenType fundamentals. */ -HB_OT_TABLE (OT, head) +HB_OT_CORE_TABLE (OT, head) +HB_OT_CORE_TABLE (OT, maxp) #if !defined(HB_NO_FACE_COLLECT_UNICODES) || !defined(HB_NO_OT_FONT) HB_OT_ACCELERATOR (OT, cmap) #endif @@ -74,6 +80,7 @@ HB_OT_TABLE (OT, VORG) #endif /* TrueType outlines. */ +HB_OT_CORE_TABLE (OT, loca) // Also used to determine number of glyphs HB_OT_ACCELERATOR (OT, glyf) /* CFF outlines. */ @@ -138,3 +145,7 @@ HB_OT_TABLE (OT, MATH) #ifdef _HB_OT_ACCELERATOR_UNDEF #undef HB_OT_ACCELERATOR #endif + +#ifdef _HB_OT_CORE_TABLE_UNDEF +#undef HB_OT_CORE_TABLE +#endif diff --git a/thirdparty/harfbuzz/src/hb-ot-face.hh b/thirdparty/harfbuzz/src/hb-ot-face.hh index e24d380bca..415dae8e20 100644 --- a/thirdparty/harfbuzz/src/hb-ot-face.hh +++ b/thirdparty/harfbuzz/src/hb-ot-face.hh @@ -63,10 +63,13 @@ struct hb_ot_face_t hb_face_t *face; /* MUST be JUST before the lazy loaders. */ #define HB_OT_TABLE(Namespace, Type) \ hb_table_lazy_loader_t<Namespace::Type, HB_OT_TABLE_ORDER (Namespace, Type)> Type; +#define HB_OT_CORE_TABLE(Namespace, Type) \ + hb_table_lazy_loader_t<Namespace::Type, HB_OT_TABLE_ORDER (Namespace, Type), true> Type; #define HB_OT_ACCELERATOR(Namespace, Type) \ hb_face_lazy_loader_t<Namespace::Type##_accelerator_t, HB_OT_TABLE_ORDER (Namespace, Type)> Type; #include "hb-ot-face-table-list.hh" #undef HB_OT_ACCELERATOR +#undef HB_OT_CORE_TABLE #undef HB_OT_TABLE }; diff --git a/thirdparty/harfbuzz/src/hb-ot-font.cc b/thirdparty/harfbuzz/src/hb-ot-font.cc index 9f0359a773..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; } @@ -257,6 +281,23 @@ hb_ot_get_font_v_extents (hb_font_t *font, } #endif +#ifndef HB_NO_DRAW +static void +hb_ot_get_glyph_shape (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, void *draw_data, + void *user_data) +{ + hb_draw_session_t draw_session (draw_funcs, draw_data, font->slant_xy); + if (font->face->table.glyf->get_path (font, glyph, draw_session)) return; +#ifndef HB_NO_CFF + if (font->face->table.cff1->get_path (font, glyph, draw_session)) return; + if (font->face->table.cff2->get_path (font, glyph, draw_session)) return; +#endif +} +#endif + static inline void free_static_ot_funcs (); static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot_font_funcs_lazy_loader_t> @@ -279,6 +320,10 @@ static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr); #endif +#ifndef HB_NO_DRAW + hb_font_funcs_set_glyph_shape_func (funcs, hb_ot_get_glyph_shape, nullptr, nullptr); +#endif + hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr); //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr); diff --git a/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh b/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh index 87a7d800c1..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) { @@ -936,7 +935,7 @@ struct glyf return; short_offset = 0 == head.indexToLocFormat; - loca_table = hb_sanitize_context_t ().reference_table<loca> (face); + loca_table = face->table.loca.get_blob (); // Needs no destruct! glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face); #ifndef HB_NO_VAR gvar = face->table.gvar; @@ -951,7 +950,6 @@ struct glyf } ~accelerator_t () { - loca_table.destroy (); glyf_table.destroy (); } @@ -1152,11 +1150,10 @@ struct glyf return operation_count; } -#ifdef HB_EXPERIMENTAL_API struct path_builder_t { hb_font_t *font; - draw_helper_t *draw_helper; + hb_draw_session_t *draw_session; struct optional_point_t { @@ -1171,10 +1168,10 @@ struct glyf { return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); } } first_oncurve, first_offcurve, last_offcurve; - path_builder_t (hb_font_t *font_, draw_helper_t &draw_helper_) + path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_) { font = font_; - draw_helper = &draw_helper_; + draw_session = &draw_session_; first_oncurve = first_offcurve = last_offcurve = optional_point_t (); } @@ -1184,10 +1181,6 @@ struct glyf * https://stackoverflow.com/a/20772557 */ void consume_point (const contour_point_t &point) { - /* Skip empty contours */ - if (unlikely (point.is_end_point && !first_oncurve.has_data && !first_offcurve.has_data)) - return; - bool is_on_curve = point.flag & Glyph::FLAG_ON_CURVE; optional_point_t p (point.x, point.y); if (!first_oncurve.has_data) @@ -1195,7 +1188,7 @@ struct glyf if (is_on_curve) { first_oncurve = p; - draw_helper->move_to (font->em_scalef_x (p.x), font->em_scalef_y (p.y)); + draw_session->move_to (font->em_fscalef_x (p.x), font->em_fscalef_y (p.y)); } else { @@ -1204,7 +1197,7 @@ struct glyf optional_point_t mid = first_offcurve.lerp (p, .5f); first_oncurve = mid; last_offcurve = p; - draw_helper->move_to (font->em_scalef_x (mid.x), font->em_scalef_y (mid.y)); + draw_session->move_to (font->em_fscalef_x (mid.x), font->em_fscalef_y (mid.y)); } else first_offcurve = p; @@ -1216,22 +1209,22 @@ struct glyf { if (is_on_curve) { - draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y), - font->em_scalef_x (p.x), font->em_scalef_y (p.y)); + draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y), + font->em_fscalef_x (p.x), font->em_fscalef_y (p.y)); last_offcurve = optional_point_t (); } else { optional_point_t mid = last_offcurve.lerp (p, .5f); - draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y), - font->em_scalef_x (mid.x), font->em_scalef_y (mid.y)); + draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y), + font->em_fscalef_x (mid.x), font->em_fscalef_y (mid.y)); last_offcurve = p; } } else { if (is_on_curve) - draw_helper->line_to (font->em_scalef_x (p.x), font->em_scalef_y (p.y)); + draw_session->line_to (font->em_fscalef_x (p.x), font->em_fscalef_y (p.y)); else last_offcurve = p; } @@ -1242,24 +1235,30 @@ struct glyf if (first_offcurve.has_data && last_offcurve.has_data) { optional_point_t mid = last_offcurve.lerp (first_offcurve, .5f); - draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y), - font->em_scalef_x (mid.x), font->em_scalef_y (mid.y)); + draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y), + font->em_fscalef_x (mid.x), font->em_fscalef_y (mid.y)); last_offcurve = optional_point_t (); /* now check the rest */ } if (first_offcurve.has_data && first_oncurve.has_data) - draw_helper->quadratic_to (font->em_scalef_x (first_offcurve.x), font->em_scalef_y (first_offcurve.y), - font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y)); + draw_session->quadratic_to (font->em_fscalef_x (first_offcurve.x), font->em_fscalef_y (first_offcurve.y), + font->em_fscalef_x (first_oncurve.x), font->em_fscalef_y (first_oncurve.y)); else if (last_offcurve.has_data && first_oncurve.has_data) - draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y), - font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y)); + draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y), + font->em_fscalef_x (first_oncurve.x), font->em_fscalef_y (first_oncurve.y)); else if (first_oncurve.has_data) - draw_helper->line_to (font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y)); + draw_session->line_to (font->em_fscalef_x (first_oncurve.x), font->em_fscalef_y (first_oncurve.y)); + else if (first_offcurve.has_data) + { + float x = font->em_fscalef_x (first_offcurve.x), y = font->em_fscalef_x (first_offcurve.y); + draw_session->move_to (x, y); + draw_session->quadratic_to (x, y, x, y); + } /* Getting ready for the next contour */ first_oncurve = first_offcurve = last_offcurve = optional_point_t (); - draw_helper->end_path (); + draw_session->close_path (); } } void points_end () {} @@ -1269,9 +1268,8 @@ struct glyf }; bool - get_path (hb_font_t *font, hb_codepoint_t gid, draw_helper_t &draw_helper) const - { return get_points (font, gid, path_builder_t (font, draw_helper)); } -#endif + get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const + { return get_points (font, gid, path_builder_t (font, draw_session)); } #ifndef HB_NO_VAR const gvar_accelerator_t *gvar; diff --git a/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh b/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh index 36bffa70a5..d5e1fc91d2 100644 --- a/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh @@ -28,6 +28,7 @@ #define HB_OT_HMTX_TABLE_HH #include "hb-open-type.hh" +#include "hb-ot-maxp-table.hh" #include "hb-ot-hhea-table.hh" #include "hb-ot-var-hvar-table.hh" #include "hb-ot-metrics.hh" @@ -98,12 +99,12 @@ struct hmtxvmtx hb_requires (hb_is_iterator (Iterator))> void serialize (hb_serialize_context_t *c, Iterator it, - unsigned num_advances) + unsigned num_long_metrics) { unsigned idx = 0; for (auto _ : it) { - if (idx < num_advances) + if (idx < num_long_metrics) { LongMetric lm; lm.advance = _.first; @@ -128,7 +129,19 @@ struct hmtxvmtx if (unlikely (!table_prime)) return_trace (false); accelerator_t _mtx (c->plan->source); - unsigned num_advances = _mtx.num_advances_for_subset (c->plan); + unsigned num_long_metrics; + { + /* Determine num_long_metrics to encode. */ + auto& plan = c->plan; + num_long_metrics = plan->num_output_glyphs (); + hb_codepoint_t old_gid = 0; + unsigned int last_advance = plan->old_gid_for_new_gid (num_long_metrics - 1, &old_gid) ? _mtx.get_advance (old_gid) : 0; + while (num_long_metrics > 1 && + last_advance == (plan->old_gid_for_new_gid (num_long_metrics - 2, &old_gid) ? _mtx.get_advance (old_gid) : 0)) + { + num_long_metrics--; + } + } auto it = + hb_range (c->plan->num_output_glyphs ()) @@ -141,13 +154,13 @@ struct hmtxvmtx }) ; - table_prime->serialize (c->serializer, it, num_advances); + table_prime->serialize (c->serializer, it, num_long_metrics); if (unlikely (c->serializer->in_error ())) return_trace (false); // Amend header num hmetrics - if (unlikely (!subset_update_header (c->plan, num_advances))) + if (unlikely (!subset_update_header (c->plan, num_long_metrics))) return_trace (false); return_trace (true); @@ -157,38 +170,48 @@ struct hmtxvmtx { friend struct hmtxvmtx; - accelerator_t (hb_face_t *face, - unsigned int default_advance_ = 0) + accelerator_t (hb_face_t *face) { - default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face); + table = hb_sanitize_context_t ().reference_table<hmtxvmtx> (face, T::tableTag); + var_table = hb_sanitize_context_t ().reference_table<HVARVVAR> (face, T::variationsTag); - num_advances = T::is_horizontal ? - face->table.hhea->numberOfLongMetrics : + 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 */ + + unsigned int len = table.get_length (); + if (len & 1) + len--; + + num_long_metrics = T::is_horizontal ? + face->table.hhea->numberOfLongMetrics : #ifndef HB_NO_VERTICAL - face->table.vhea->numberOfLongMetrics + face->table.vhea->numberOfLongMetrics #else - 0 + 0 #endif - ; + ; + if (unlikely (num_long_metrics * 4 > len)) + num_long_metrics = len / 4; + len -= num_long_metrics * 4; - table = hb_sanitize_context_t ().reference_table<hmtxvmtx> (face, T::tableTag); + num_bearings = face->table.maxp->get_num_glyphs (); - /* Cap num_metrics() and num_advances() based on table length. */ - unsigned int len = table.get_length (); - if (unlikely (num_advances * 4 > len)) - num_advances = len / 4; - num_metrics = num_advances + (len - 4 * num_advances) / 2; + if (unlikely (num_bearings < num_long_metrics)) + num_bearings = num_long_metrics; + if (unlikely ((num_bearings - num_long_metrics) * 2 > len)) + num_bearings = num_long_metrics + len / 2; + len -= (num_bearings - num_long_metrics) * 2; - /* We MUST set num_metrics to zero if num_advances is zero. + /* We MUST set num_bearings to zero if num_long_metrics is zero. * Our get_advance() depends on that. */ - if (unlikely (!num_advances)) - { - num_metrics = num_advances = 0; - table.destroy (); - table = hb_blob_get_empty (); - } + if (unlikely (!num_long_metrics)) + num_bearings = num_long_metrics = 0; - var_table = hb_sanitize_context_t ().reference_table<HVARVVAR> (face, T::variationsTag); + num_advances = num_bearings + len / 2; + num_glyphs = face->get_num_glyphs (); + if (num_glyphs < num_advances) + num_glyphs = num_advances; } ~accelerator_t () { @@ -196,16 +219,18 @@ 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_advances) + if (glyph < num_long_metrics) return table->longMetricZ[glyph].sb; - if (unlikely (glyph >= num_metrics)) + if (unlikely (glyph >= num_bearings)) return 0; - const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_advances]; - return bearings[glyph - num_advances]; + const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_long_metrics]; + return bearings[glyph - num_long_metrics]; } int get_side_bearing (hb_font_t *font, hb_codepoint_t glyph) const @@ -213,7 +238,7 @@ struct hmtxvmtx int side_bearing = get_side_bearing (glyph); #ifndef HB_NO_VAR - if (unlikely (glyph >= num_metrics) || !font->num_coords) + if (unlikely (glyph >= num_bearings) || !font->num_coords) return side_bearing; if (var_table.get_length ()) @@ -227,18 +252,35 @@ struct hmtxvmtx unsigned int get_advance (hb_codepoint_t glyph) const { - if (unlikely (glyph >= num_metrics)) - { - /* If num_metrics is zero, it means we don't have the metrics table - * for this direction: return default advance. Otherwise, it means that the - * glyph index is out of bound: return zero. */ - if (num_metrics) - return 0; - else - return default_advance; - } + /* OpenType case. */ + if (glyph < num_bearings) + return table->longMetricZ[hb_min (glyph, (uint32_t) num_long_metrics - 1)].advance; + + /* If num_advances is zero, it means we don't have the metrics table + * for this direction: return default advance. Otherwise, there's a + * well-defined answer. */ + if (unlikely (!num_advances)) + return default_advance; - return table->longMetricZ[hb_min (glyph, (uint32_t) num_advances - 1)].advance; +#ifdef HB_NO_BORING_EXPANSION + return 0; +#endif + + if (unlikely (glyph >= num_glyphs)) + return 0; + + /* num_bearings <= glyph < num_glyphs; + * num_bearings <= num_advances */ + + /* TODO Optimize */ + + if (num_bearings == num_advances) + return get_advance (num_bearings - 1); + + const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_long_metrics]; + const UFWORD *advances = (const UFWORD *) &bearings[num_bearings - num_long_metrics]; + + return advances[hb_min (glyph - num_bearings, num_advances - num_bearings - 1)]; } unsigned int get_advance (hb_codepoint_t glyph, @@ -247,7 +289,7 @@ struct hmtxvmtx unsigned int advance = get_advance (glyph); #ifndef HB_NO_VAR - if (unlikely (glyph >= num_metrics) || !font->num_coords) + if (unlikely (glyph >= num_bearings) || !font->num_coords) return advance; if (var_table.get_length ()) @@ -259,35 +301,13 @@ struct hmtxvmtx #endif } - unsigned int num_advances_for_subset (const hb_subset_plan_t *plan) const - { - unsigned int num_advances = plan->num_output_glyphs (); - unsigned int last_advance = _advance_for_new_gid (plan, - num_advances - 1); - while (num_advances > 1 && - last_advance == _advance_for_new_gid (plan, - num_advances - 2)) - { - num_advances--; - } - - return num_advances; - } - - private: - unsigned int _advance_for_new_gid (const hb_subset_plan_t *plan, - hb_codepoint_t new_gid) const - { - hb_codepoint_t old_gid; - if (!plan->old_gid_for_new_gid (new_gid, &old_gid)) - return 0; - - return get_advance (old_gid); - } - protected: - unsigned int num_metrics; - unsigned int num_advances; + // 0 <= num_long_metrics <= num_bearings <= num_advances <= num_glyphs + unsigned num_long_metrics; + unsigned num_bearings; + unsigned num_advances; + unsigned num_glyphs; + unsigned int default_advance; private: @@ -319,6 +339,8 @@ struct hmtxvmtx * the end. This allows a monospaced * font to vary the side bearing * values for each glyph. */ +/*UnsizedArrayOf<UFWORD>advancesX;*/ + /* TODO Document. */ public: DEFINE_SIZE_ARRAY (0, longMetricZ); }; diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh index eb4c3b46e2..1b9dfcd3f5 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh @@ -41,7 +41,10 @@ namespace OT { struct BaseCoordFormat1 { - hb_position_t get_coord () const { return coordinate; } + hb_position_t get_coord (hb_font_t *font, hb_direction_t direction) const + { + return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (coordinate) : font->em_scale_x (coordinate); + } bool sanitize (hb_sanitize_context_t *c) const { @@ -58,10 +61,10 @@ struct BaseCoordFormat1 struct BaseCoordFormat2 { - hb_position_t get_coord () const + hb_position_t get_coord (hb_font_t *font, hb_direction_t direction) const { /* TODO */ - return coordinate; + return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (coordinate) : font->em_scale_x (coordinate); } bool sanitize (hb_sanitize_context_t *c) const @@ -87,9 +90,10 @@ struct BaseCoordFormat3 hb_direction_t direction) const { const Device &device = this+deviceTable; - return coordinate + (HB_DIRECTION_IS_VERTICAL (direction) ? - device.get_y_delta (font, var_store) : - device.get_x_delta (font, var_store)); + + return HB_DIRECTION_IS_HORIZONTAL (direction) + ? font->em_scale_y (coordinate) + device.get_y_delta (font, var_store) + : font->em_scale_x (coordinate) + device.get_x_delta (font, var_store); } @@ -120,8 +124,8 @@ struct BaseCoord hb_direction_t direction) const { switch (u.format) { - case 1: return u.format1.get_coord (); - case 2: return u.format2.get_coord (); + case 1: return u.format1.get_coord (font, direction); + case 2: return u.format2.get_coord (font, direction); case 3: return u.format3.get_coord (font, var_store, direction); default:return 0; } diff --git a/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 a599eea6e9..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 @@ -361,6 +363,13 @@ hb_ot_layout_get_attach_points (hb_face_t *face, * Fetches a list of the caret positions defined for a ligature glyph in the GDEF * table of the font. The list returned will begin at the offset provided. * + * Note that a ligature that is formed from n characters will have n-1 + * caret positions. The first character is not represented in the array, + * since its caret position is the glyph position. + * + * The positions returned by this function are 'unshaped', and will have to + * be fixed up for kerning that may be applied to the ligature glyph. + * * Return value: Total number of ligature caret positions for @glyph. * **/ @@ -382,7 +391,7 @@ hb_ot_layout_get_ligature_carets (hb_font_t *font, */ bool -OT::GSUB::is_blocklisted (hb_blob_t *blob HB_UNUSED, +GSUB::is_blocklisted (hb_blob_t *blob HB_UNUSED, hb_face_t *face) const { #ifdef HB_NO_OT_LAYOUT_BLOCKLIST @@ -999,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_), @@ -1026,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); } } @@ -1522,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; @@ -1801,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; }; @@ -1922,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), @@ -1960,13 +1970,84 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c, #ifndef HB_NO_BASE /** + * hb_ot_layout_get_horizontal_baseline_tag_for_script: + * @script: a script tag. + * + * Fetches the dominant horizontal baseline tag used by @script. + * + * Return value: dominant baseline tag for the @script. + * + * Since: 4.0.0 + **/ +hb_ot_layout_baseline_tag_t +hb_ot_layout_get_horizontal_baseline_tag_for_script (hb_script_t script) +{ + /* Keep in sync with hb_ot_layout_get_baseline_with_fallback */ + switch ((int) script) + { + /* Unicode-1.1 additions */ + case HB_SCRIPT_BENGALI: + case HB_SCRIPT_DEVANAGARI: + case HB_SCRIPT_GUJARATI: + case HB_SCRIPT_GURMUKHI: + /* Unicode-2.0 additions */ + case HB_SCRIPT_TIBETAN: + /* Unicode-4.0 additions */ + case HB_SCRIPT_LIMBU: + /* Unicode-4.1 additions */ + case HB_SCRIPT_SYLOTI_NAGRI: + /* Unicode-5.0 additions */ + case HB_SCRIPT_PHAGS_PA: + /* Unicode-5.2 additions */ + case HB_SCRIPT_MEETEI_MAYEK: + /* Unicode-6.1 additions */ + case HB_SCRIPT_SHARADA: + case HB_SCRIPT_TAKRI: + /* Unicode-7.0 additions */ + case HB_SCRIPT_MODI: + case HB_SCRIPT_SIDDHAM: + case HB_SCRIPT_TIRHUTA: + /* Unicode-9.0 additions */ + case HB_SCRIPT_MARCHEN: + case HB_SCRIPT_NEWA: + /* Unicode-10.0 additions */ + case HB_SCRIPT_SOYOMBO: + case HB_SCRIPT_ZANABAZAR_SQUARE: + /* Unicode-11.0 additions */ + case HB_SCRIPT_DOGRA: + case HB_SCRIPT_GUNJALA_GONDI: + /* Unicode-12.0 additions */ + case HB_SCRIPT_NANDINAGARI: + return HB_OT_LAYOUT_BASELINE_TAG_HANGING; + + /* Unicode-1.1 additions */ + case HB_SCRIPT_HANGUL: + case HB_SCRIPT_HAN: + case HB_SCRIPT_HIRAGANA: + case HB_SCRIPT_KATAKANA: + /* Unicode-3.0 additions */ + case HB_SCRIPT_BOPOMOFO: + /* Unicode-9.0 additions */ + case HB_SCRIPT_TANGUT: + /* Unicode-10.0 additions */ + case HB_SCRIPT_NUSHU: + /* Unicode-13.0 additions */ + case HB_SCRIPT_KHITAN_SMALL_SCRIPT: + return HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT; + + default: + return HB_OT_LAYOUT_BASELINE_TAG_ROMAN; + } +} + +/** * hb_ot_layout_get_baseline: * @font: a font * @baseline_tag: a baseline tag * @direction: text direction. * @script_tag: script tag. * @language_tag: language tag, currently unused. - * @coord: (out): baseline value if found. + * @coord: (out) (nullable): baseline value if found. * * Fetches a baseline value from the face. * @@ -1982,13 +2063,231 @@ hb_ot_layout_get_baseline (hb_font_t *font, hb_tag_t language_tag, hb_position_t *coord /* OUT. May be NULL. */) { - bool result = font->face->table.BASE->get_baseline (font, baseline_tag, direction, script_tag, language_tag, coord); + return font->face->table.BASE->get_baseline (font, baseline_tag, direction, script_tag, language_tag, coord); +} + +/** + * hb_ot_layout_get_baseline_with_fallback: + * @font: a font + * @baseline_tag: a baseline tag + * @direction: text direction. + * @script_tag: script tag. + * @language_tag: language tag, currently unused. + * @coord: (out): baseline value if found. + * + * Fetches a baseline value from the face, and synthesizes + * it if the font does not have it. + * + * Since: 4.0.0 + **/ +void +hb_ot_layout_get_baseline_with_fallback (hb_font_t *font, + hb_ot_layout_baseline_tag_t baseline_tag, + hb_direction_t direction, + hb_tag_t script_tag, + hb_tag_t language_tag, + hb_position_t *coord /* OUT */) +{ + if (hb_ot_layout_get_baseline (font, + baseline_tag, + direction, + script_tag, + language_tag, + coord)) + return; + + /* Synthesize missing baselines. + * See https://www.w3.org/TR/css-inline-3/#baseline-synthesis-fonts + */ + switch (baseline_tag) + { + case HB_OT_LAYOUT_BASELINE_TAG_ROMAN: + *coord = 0; // FIXME origin ? + break; + + case HB_OT_LAYOUT_BASELINE_TAG_MATH: + { + hb_codepoint_t glyph; + hb_glyph_extents_t extents; + if (HB_DIRECTION_IS_HORIZONTAL (direction) && + (hb_font_get_nominal_glyph (font, 0x2212u, &glyph) || + hb_font_get_nominal_glyph (font, '-', &glyph)) && + hb_font_get_glyph_extents (font, glyph, &extents)) + { + *coord = extents.y_bearing + extents.height / 2; + } + else + { + hb_position_t x_height = font->y_scale / 2; +#ifndef HB_NO_METRICS + hb_ot_metrics_get_position_with_fallback (font, HB_OT_METRICS_TAG_X_HEIGHT, &x_height); +#endif + *coord = x_height / 2; + } + } + break; - if (result && coord) - *coord = HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (*coord) : font->em_scale_x (*coord); + case HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT: + case HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT: + { + hb_position_t embox_top, embox_bottom; + + hb_ot_layout_get_baseline_with_fallback (font, + HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT, + direction, + script_tag, + language_tag, + &embox_top); + hb_ot_layout_get_baseline_with_fallback (font, + HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT, + direction, + script_tag, + language_tag, + &embox_bottom); + + if (baseline_tag == HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT) + *coord = embox_top + (embox_bottom - embox_top) / 10; + else + *coord = embox_bottom + (embox_top - embox_bottom) / 10; + } + break; + + case HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT: + if (hb_ot_layout_get_baseline (font, + HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT, + direction, + script_tag, + language_tag, + coord)) + *coord += HB_DIRECTION_IS_HORIZONTAL (direction) ? font->y_scale : font->x_scale; + else + { + hb_font_extents_t font_extents; + hb_font_get_extents_for_direction (font, direction, &font_extents); + *coord = font_extents.ascender; + } + break; + + case HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT: + if (hb_ot_layout_get_baseline (font, + HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT, + direction, + script_tag, + language_tag, + coord)) + *coord -= HB_DIRECTION_IS_HORIZONTAL (direction) ? font->y_scale : font->x_scale; + else + { + hb_font_extents_t font_extents; + hb_font_get_extents_for_direction (font, direction, &font_extents); + *coord = font_extents.descender; + } + break; + + case HB_OT_LAYOUT_BASELINE_TAG_HANGING: + if (HB_DIRECTION_IS_HORIZONTAL (direction)) + { + hb_codepoint_t ch; + hb_codepoint_t glyph; + hb_glyph_extents_t extents; - return result; + /* Keep in sync with hb_ot_layout_get_horizontal_baseline_for_script */ + switch ((int) script_tag) + { + /* Unicode-1.1 additions */ + case HB_SCRIPT_BENGALI: ch = 0x0995u; break; + case HB_SCRIPT_DEVANAGARI: ch = 0x0915u; break; + case HB_SCRIPT_GUJARATI: ch = 0x0a95u; break; + case HB_SCRIPT_GURMUKHI: ch = 0x0a15u; break; + /* Unicode-2.0 additions */ + case HB_SCRIPT_TIBETAN: ch = 0x0f40u; break; + /* Unicode-4.0 additions */ + case HB_SCRIPT_LIMBU: ch = 0x1901u; break; + /* Unicode-4.1 additions */ + case HB_SCRIPT_SYLOTI_NAGRI: ch = 0xa807u; break; + /* Unicode-5.0 additions */ + case HB_SCRIPT_PHAGS_PA: ch = 0xa840u; break; + /* Unicode-5.2 additions */ + case HB_SCRIPT_MEETEI_MAYEK: ch = 0xabc0u; break; + /* Unicode-6.1 additions */ + case HB_SCRIPT_SHARADA: ch = 0x11191u; break; + case HB_SCRIPT_TAKRI: ch = 0x1168cu; break; + /* Unicode-7.0 additions */ + case HB_SCRIPT_MODI: ch = 0x1160eu;break; + case HB_SCRIPT_SIDDHAM: ch = 0x11590u; break; + case HB_SCRIPT_TIRHUTA: ch = 0x1148fu; break; + /* Unicode-9.0 additions */ + case HB_SCRIPT_MARCHEN: ch = 0x11c72u; break; + case HB_SCRIPT_NEWA: ch = 0x1140eu; break; + /* Unicode-10.0 additions */ + case HB_SCRIPT_SOYOMBO: ch = 0x11a5cu; break; + case HB_SCRIPT_ZANABAZAR_SQUARE: ch = 0x11a0bu; break; + /* Unicode-11.0 additions */ + case HB_SCRIPT_DOGRA: ch = 0x1180au; break; + case HB_SCRIPT_GUNJALA_GONDI: ch = 0x11d6cu; break; + /* Unicode-12.0 additions */ + case HB_SCRIPT_NANDINAGARI: ch = 0x119b0u; break; + default: ch = 0; break; + } + + if (ch && + hb_font_get_nominal_glyph (font, ch, &glyph) && + hb_font_get_glyph_extents (font, glyph, &extents)) + *coord = extents.y_bearing; + else + *coord = font->y_scale * 6 / 10; // FIXME makes assumptions about origin + } + else + *coord = font->x_scale * 6 / 10; // FIXME makes assumptions about origin + break; + + case HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_CENTRAL: + { + hb_position_t top, bottom; + hb_ot_layout_get_baseline_with_fallback (font, + HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT, + direction, + script_tag, + language_tag, + &top); + hb_ot_layout_get_baseline_with_fallback (font, + HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT, + direction, + script_tag, + language_tag, + &bottom); + *coord = (top + bottom) / 2; + + } + break; + + case HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_CENTRAL: + { + hb_position_t top, bottom; + hb_ot_layout_get_baseline_with_fallback (font, + HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT, + direction, + script_tag, + language_tag, + &top); + hb_ot_layout_get_baseline_with_fallback (font, + HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT, + direction, + script_tag, + language_tag, + &bottom); + *coord = (top + bottom) / 2; + + } + break; + + case _HB_OT_LAYOUT_BASELINE_TAG_MAX_VALUE: + default: + *coord = 0; + break; + } } + #endif diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.h b/thirdparty/harfbuzz/src/hb-ot-layout.h index d47ba0fc92..4edddd9e0d 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout.h +++ b/thirdparty/harfbuzz/src/hb-ot-layout.h @@ -332,31 +332,6 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face, hb_set_t *glyphs_after, /* OUT. May be NULL */ hb_set_t *glyphs_output /* OUT. May be NULL */); -#ifdef HB_NOT_IMPLEMENTED -typedef struct -{ - const hb_codepoint_t *before, - unsigned int before_length, - const hb_codepoint_t *input, - unsigned int input_length, - const hb_codepoint_t *after, - unsigned int after_length, -} hb_ot_layout_glyph_sequence_t; - -typedef hb_bool_t -(*hb_ot_layout_glyph_sequence_func_t) (hb_font_t *font, - hb_tag_t table_tag, - unsigned int lookup_index, - const hb_ot_layout_glyph_sequence_t *sequence, - void *user_data); - -HB_EXTERN void -Xhb_ot_layout_lookup_enumerate_sequences (hb_face_t *face, - hb_tag_t table_tag, - unsigned int lookup_index, - hb_ot_layout_glyph_sequence_func_t callback, - void *user_data); -#endif /* Variations support */ @@ -411,19 +386,6 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face, hb_set_t *glyphs); -#ifdef HB_NOT_IMPLEMENTED -/* Note: You better have GDEF when using this API, or marks won't do much. */ -HB_EXTERN hb_bool_t -Xhb_ot_layout_lookup_substitute (hb_font_t *font, - unsigned int lookup_index, - const hb_ot_layout_glyph_sequence_t *sequence, - unsigned int out_size, - hb_codepoint_t *glyphs_out, /* OUT */ - unsigned int *clusters_out, /* OUT */ - unsigned int *out_length /* OUT */); -#endif - - /* * GPOS */ @@ -431,15 +393,6 @@ Xhb_ot_layout_lookup_substitute (hb_font_t *font, HB_EXTERN hb_bool_t hb_ot_layout_has_positioning (hb_face_t *face); -#ifdef HB_NOT_IMPLEMENTED -/* Note: You better have GDEF when using this API, or marks won't do much. */ -HB_EXTERN hb_bool_t -Xhb_ot_layout_lookup_position (hb_font_t *font, - unsigned int lookup_index, - const hb_ot_layout_glyph_sequence_t *sequence, - hb_glyph_position_t *positions /* IN / OUT */); -#endif - /* Optical 'size' feature info. Returns true if found. * https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */ HB_EXTERN hb_bool_t @@ -487,9 +440,11 @@ hb_ot_layout_feature_get_characters (hb_face_t *face, * if the direction is horizontal or vertical, respectively. * @HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT: Ideographic character face top or right edge, * if the direction is horizontal or vertical, respectively. + * @HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_CENTRAL: The center of the ideographic character face. Since: 4.0.0 * @HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT: Ideographic em-box bottom or left edge, * if the direction is horizontal or vertical, respectively. * @HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT: Ideographic em-box top or right edge baseline, + * @HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_CENTRAL: The center of the ideographic em-box. Since: 4.0.0 * if the direction is horizontal or vertical, respectively. * @HB_OT_LAYOUT_BASELINE_TAG_MATH: The baseline about which mathematical characters are centered. * In vertical writing mode when mathematical characters rotated 90 degrees clockwise, are centered. @@ -503,14 +458,19 @@ typedef enum { HB_OT_LAYOUT_BASELINE_TAG_HANGING = HB_TAG ('h','a','n','g'), HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT = HB_TAG ('i','c','f','b'), HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT = HB_TAG ('i','c','f','t'), + HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_CENTRAL = HB_TAG ('I','c','f','c'), HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT = HB_TAG ('i','d','e','o'), HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT = HB_TAG ('i','d','t','p'), + HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_CENTRAL = HB_TAG ('I','d','c','e'), HB_OT_LAYOUT_BASELINE_TAG_MATH = HB_TAG ('m','a','t','h'), /*< private >*/ _HB_OT_LAYOUT_BASELINE_TAG_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/ } hb_ot_layout_baseline_tag_t; +HB_EXTERN hb_ot_layout_baseline_tag_t +hb_ot_layout_get_horizontal_baseline_tag_for_script (hb_script_t script); + HB_EXTERN hb_bool_t hb_ot_layout_get_baseline (hb_font_t *font, hb_ot_layout_baseline_tag_t baseline_tag, @@ -519,6 +479,14 @@ hb_ot_layout_get_baseline (hb_font_t *font, hb_tag_t language_tag, hb_position_t *coord /* OUT. May be NULL. */); +HB_EXTERN void +hb_ot_layout_get_baseline_with_fallback (hb_font_t *font, + hb_ot_layout_baseline_tag_t baseline_tag, + hb_direction_t direction, + hb_tag_t script_tag, + hb_tag_t language_tag, + hb_position_t *coord /* OUT */); + HB_END_DECLS #endif /* HB_OT_LAYOUT_H */ diff --git a/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-math-table.hh b/thirdparty/harfbuzz/src/hb-ot-math-table.hh index 8d0b4317c3..d834d94371 100644 --- a/thirdparty/harfbuzz/src/hb-ot-math-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-math-table.hh @@ -369,6 +369,37 @@ struct MathKern return kernValue[i].get_x_value (font, this); } + unsigned int get_entries (unsigned int start_offset, + unsigned int *entries_count, /* IN/OUT */ + hb_ot_math_kern_entry_t *kern_entries, /* OUT */ + hb_font_t *font) const + { + const MathValueRecord* correctionHeight = mathValueRecordsZ.arrayZ; + const MathValueRecord* kernValue = mathValueRecordsZ.arrayZ + heightCount; + const unsigned int entriesCount = heightCount + 1; + + if (entries_count) + { + unsigned int start = hb_min (start_offset, entriesCount); + unsigned int end = hb_min (start + *entries_count, entriesCount); + *entries_count = end - start; + + for (unsigned int i = 0; i < *entries_count; i++) { + unsigned int j = start + i; + + hb_position_t max_height; + if (j == heightCount) { + max_height = INT32_MAX; + } else { + max_height = correctionHeight[j].get_y_value (font, this); + } + + kern_entries[i] = {max_height, kernValue[j].get_x_value (font, this)}; + } + } + return entriesCount; + } + protected: HBUINT16 heightCount; UnsizedArrayOf<MathValueRecord> @@ -423,6 +454,24 @@ struct MathKernInfoRecord return (base+mathKern[idx]).get_value (correction_height, font); } + unsigned int get_kernings (hb_ot_math_kern_t kern, + unsigned int start_offset, + unsigned int *entries_count, /* IN/OUT */ + hb_ot_math_kern_entry_t *kern_entries, /* OUT */ + hb_font_t *font, + const void *base) const + { + unsigned int idx = kern; + if (unlikely (idx >= ARRAY_LENGTH (mathKern)) || !mathKern[idx]) { + if (entries_count) *entries_count = 0; + return 0; + } + return (base+mathKern[idx]).get_entries (start_offset, + entries_count, + kern_entries, + font); + } + protected: /* Offset to MathKern table for each corner - * from the beginning of MathKernInfo table. May be NULL. */ @@ -473,6 +522,22 @@ struct MathKernInfo return mathKernInfoRecords[index].get_kerning (kern, correction_height, font, this); } + unsigned int get_kernings (hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + unsigned int start_offset, + unsigned int *entries_count, /* IN/OUT */ + hb_ot_math_kern_entry_t *kern_entries, /* OUT */ + hb_font_t *font) const + { + unsigned int index = (this+mathKernCoverage).get_coverage (glyph); + return mathKernInfoRecords[index].get_kernings (kern, + start_offset, + entries_count, + kern_entries, + font, + this); + } + protected: Offset16To<Coverage> mathKernCoverage; @@ -545,6 +610,19 @@ struct MathGlyphInfo hb_font_t *font) const { return (this+mathKernInfo).get_kerning (glyph, kern, correction_height, font); } + hb_position_t get_kernings (hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + unsigned int start_offset, + unsigned int *entries_count, /* IN/OUT */ + hb_ot_math_kern_entry_t *kern_entries, /* OUT */ + hb_font_t *font) const + { return (this+mathKernInfo).get_kernings (glyph, + kern, + start_offset, + entries_count, + kern_entries, + font); } + protected: /* Offset to MathItalicsCorrectionInfo table - * from the beginning of MathGlyphInfo table. */ diff --git a/thirdparty/harfbuzz/src/hb-ot-math.cc b/thirdparty/harfbuzz/src/hb-ot-math.cc index 5781d25f2a..f44ac35849 100644 --- a/thirdparty/harfbuzz/src/hb-ot-math.cc +++ b/thirdparty/harfbuzz/src/hb-ot-math.cc @@ -185,6 +185,51 @@ hb_ot_math_get_glyph_kerning (hb_font_t *font, } /** + * hb_ot_math_get_glyph_kernings: + * @font: #hb_font_t to work upon + * @glyph: The glyph index from which to retrieve the kernings + * @kern: The #hb_ot_math_kern_t from which to retrieve the kernings + * @start_offset: offset of the first kern entry to retrieve + * @entries_count: (inout) (optional): Input = the maximum number of kern entries to return; + * Output = the actual number of kern entries returned + * @kern_entries: (out caller-allocates) (array length=entries_count): array of kern entries returned + * + * Fetches the raw MathKern (cut-in) data for the specified font, glyph index, + * and @kern. The corresponding list of kern values and correction heights is + * returned as a list of #hb_ot_math_kern_entry_t structs. + * + * See also #hb_ot_math_get_glyph_kerning, which handles selecting the + * appropriate kern value for a given correction height. + * + * <note>For a glyph with @n defined kern values (where @n > 0), there are only + * @n−1 defined correction heights, as each correction height defines a boundary + * past which the next kern value should be selected. Therefore, only the + * #hb_ot_math_kern_entry_t.kern_value of the uppermost #hb_ot_math_kern_entry_t + * actually comes from the font; its corresponding + * #hb_ot_math_kern_entry_t.max_correction_height is always set to + * <code>INT32_MAX</code>.</note> + * + * Return value: the total number of kern values available or zero + * + * Since: 3.4.0 + **/ +unsigned int +hb_ot_math_get_glyph_kernings (hb_font_t *font, + hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + unsigned int start_offset, + unsigned int *entries_count, /* IN/OUT */ + hb_ot_math_kern_entry_t *kern_entries /* OUT */) +{ + return font->face->table.MATH->get_glyph_info().get_kernings (glyph, + kern, + start_offset, + entries_count, + kern_entries, + font); +} + +/** * hb_ot_math_get_glyph_variants: * @font: #hb_font_t to work upon * @glyph: The index of the glyph to stretch diff --git a/thirdparty/harfbuzz/src/hb-ot-math.h b/thirdparty/harfbuzz/src/hb-ot-math.h index d3ffa19d85..1378a0639a 100644 --- a/thirdparty/harfbuzz/src/hb-ot-math.h +++ b/thirdparty/harfbuzz/src/hb-ot-math.h @@ -50,14 +50,18 @@ HB_BEGIN_DECLS #define HB_OT_TAG_MATH HB_TAG('M','A','T','H') /** - * HB_OT_MATH_SCRIPT: + * HB_OT_TAG_MATH_SCRIPT: * - * OpenType script tag for math shaping, for use with - * Use with hb_buffer_set_script(). + * OpenType script tag, `math`, for features specific to math shaping. * - * Since: 1.3.3 + * <note>#HB_OT_TAG_MATH_SCRIPT is not a valid #hb_script_t and should only be + * used with functions that accept raw OpenType script tags, such as + * #hb_ot_layout_collect_features. In other cases, #HB_SCRIPT_MATH should be + * used instead.</note> + * + * Since: 3.4.0 */ -#define HB_OT_MATH_SCRIPT HB_TAG('m','a','t','h') +#define HB_OT_TAG_MATH_SCRIPT HB_TAG('m','a','t','h') /* Types */ @@ -205,6 +209,20 @@ typedef enum { } hb_ot_math_kern_t; /** + * hb_ot_math_kern_entry_t: + * @max_correction_height: The maximum height at which this entry should be used + * @kern_value: The kern value of the entry + * + * Data type to hold math kerning (cut-in) information for a glyph. + * + * Since: 3.4.0 + */ +typedef struct { + hb_position_t max_correction_height; + hb_position_t kern_value; +} hb_ot_math_kern_entry_t; + +/** * hb_ot_math_glyph_variant_t: * @glyph: The glyph index of the variant * @advance: The advance width of the variant @@ -281,6 +299,14 @@ hb_ot_math_get_glyph_kerning (hb_font_t *font, hb_position_t correction_height); HB_EXTERN unsigned int +hb_ot_math_get_glyph_kernings (hb_font_t *font, + hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + unsigned int start_offset, + unsigned int *entries_count, /* IN/OUT */ + hb_ot_math_kern_entry_t *kern_entries /* OUT */); + +HB_EXTERN unsigned int hb_ot_math_get_glyph_variants (hb_font_t *font, hb_codepoint_t glyph, hb_direction_t direction, diff --git a/thirdparty/harfbuzz/src/hb-ot-metrics.cc b/thirdparty/harfbuzz/src/hb-ot-metrics.cc index 103808cf91..f9c4b96fff 100644 --- a/thirdparty/harfbuzz/src/hb-ot-metrics.cc +++ b/thirdparty/harfbuzz/src/hb-ot-metrics.cc @@ -238,6 +238,145 @@ hb_ot_metrics_get_position (hb_font_t *font, } } +/** + * hb_ot_metrics_get_position_with_fallback: + * @font: an #hb_font_t object. + * @metrics_tag: tag of metrics value you like to fetch. + * @position: (out) (optional): result of metrics value from the font. + * + * Fetches metrics value corresponding to @metrics_tag from @font, + * and synthesizes a value if it the value is missing in the font. + * + * Since: 4.0.0 + **/ +void +hb_ot_metrics_get_position_with_fallback (hb_font_t *font, + hb_ot_metrics_tag_t metrics_tag, + hb_position_t *position /* OUT */) +{ + hb_font_extents_t font_extents; + hb_codepoint_t glyph; + hb_glyph_extents_t extents; + + if (hb_ot_metrics_get_position (font, metrics_tag, position)) + { + if ((metrics_tag != HB_OT_METRICS_TAG_STRIKEOUT_SIZE && + metrics_tag != HB_OT_METRICS_TAG_UNDERLINE_SIZE) || + *position != 0) + return; + } + + switch (metrics_tag) + { + case HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER: + case HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_ASCENT: + hb_font_get_extents_for_direction (font, HB_DIRECTION_LTR, &font_extents); + *position = font_extents.ascender; + break; + + case HB_OT_METRICS_TAG_VERTICAL_ASCENDER: + hb_font_get_extents_for_direction (font, HB_DIRECTION_TTB, &font_extents); + *position = font_extents.ascender; + break; + + case HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER: + case HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_DESCENT: + hb_font_get_extents_for_direction (font, HB_DIRECTION_LTR, &font_extents); + *position = font_extents.descender; + break; + + case HB_OT_METRICS_TAG_VERTICAL_DESCENDER: + hb_font_get_extents_for_direction (font, HB_DIRECTION_TTB, &font_extents); + *position = font_extents.ascender; + break; + + case HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP: + hb_font_get_extents_for_direction (font, HB_DIRECTION_LTR, &font_extents); + *position = font_extents.line_gap; + break; + + case HB_OT_METRICS_TAG_VERTICAL_LINE_GAP: + hb_font_get_extents_for_direction (font, HB_DIRECTION_TTB, &font_extents); + *position = font_extents.line_gap; + break; + + case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE: + case HB_OT_METRICS_TAG_VERTICAL_CARET_RISE: + *position = 1; + break; + + case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RUN: + case HB_OT_METRICS_TAG_VERTICAL_CARET_RUN: + *position = 0; + break; + + case HB_OT_METRICS_TAG_HORIZONTAL_CARET_OFFSET: + case HB_OT_METRICS_TAG_VERTICAL_CARET_OFFSET: + *position = 0; + break; + + case HB_OT_METRICS_TAG_X_HEIGHT: + if (hb_font_get_nominal_glyph (font, 'x', &glyph) && + hb_font_get_glyph_extents (font, glyph, &extents)) + *position = extents.y_bearing; + else + *position = font->y_scale / 2; + break; + + case HB_OT_METRICS_TAG_CAP_HEIGHT: + if (hb_font_get_nominal_glyph (font, 'O', &glyph) && + hb_font_get_glyph_extents (font, glyph, &extents)) + *position = extents.height + 2 * extents.y_bearing; + else + *position = font->y_scale * 2 / 3; + break; + + case HB_OT_METRICS_TAG_STRIKEOUT_SIZE: + case HB_OT_METRICS_TAG_UNDERLINE_SIZE: + *position = font->y_scale / 18; + break; + + case HB_OT_METRICS_TAG_STRIKEOUT_OFFSET: + { + hb_position_t ascender; + hb_ot_metrics_get_position_with_fallback (font, + HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, + &ascender); + *position = ascender / 2; + } + break; + + case HB_OT_METRICS_TAG_UNDERLINE_OFFSET: + *position = - font->y_scale / 18; + break; + + case HB_OT_METRICS_TAG_SUBSCRIPT_EM_X_SIZE: + case HB_OT_METRICS_TAG_SUPERSCRIPT_EM_X_SIZE: + *position = font->x_scale * 10 / 12; + break; + + case HB_OT_METRICS_TAG_SUBSCRIPT_EM_Y_SIZE: + case HB_OT_METRICS_TAG_SUPERSCRIPT_EM_Y_SIZE: + *position = font->y_scale * 10 / 12; + break; + + case HB_OT_METRICS_TAG_SUBSCRIPT_EM_X_OFFSET: + case HB_OT_METRICS_TAG_SUPERSCRIPT_EM_X_OFFSET: + *position = 0; + break; + + case HB_OT_METRICS_TAG_SUBSCRIPT_EM_Y_OFFSET: + case HB_OT_METRICS_TAG_SUPERSCRIPT_EM_Y_OFFSET: + *position = font->y_scale / 5; + break; + + case _HB_OT_METRICS_TAG_MAX_VALUE: + default: + *position = 0; + break; + } +} + #ifndef HB_NO_VAR /** * hb_ot_metrics_get_variation: diff --git a/thirdparty/harfbuzz/src/hb-ot-metrics.h b/thirdparty/harfbuzz/src/hb-ot-metrics.h index 5841fc8b0f..30de500088 100644 --- a/thirdparty/harfbuzz/src/hb-ot-metrics.h +++ b/thirdparty/harfbuzz/src/hb-ot-metrics.h @@ -110,6 +110,11 @@ hb_ot_metrics_get_position (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag, hb_position_t *position /* OUT. May be NULL. */); +HB_EXTERN void +hb_ot_metrics_get_position_with_fallback (hb_font_t *font, + hb_ot_metrics_tag_t metrics_tag, + hb_position_t *position /* OUT */); + HB_EXTERN float hb_ot_metrics_get_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag); diff --git a/thirdparty/harfbuzz/src/hb-ot-name.cc b/thirdparty/harfbuzz/src/hb-ot-name.cc index eff46ef227..c35ac5b3dc 100644 --- a/thirdparty/harfbuzz/src/hb-ot-name.cc +++ b/thirdparty/harfbuzz/src/hb-ot-name.cc @@ -52,7 +52,7 @@ * array is owned by the @face and should not be modified. It can be * used as long as @face is alive. * - * Returns: (out) (transfer none) (array length=num_entries): Array of available name entries. + * Returns: (transfer none) (array length=num_entries): Array of available name entries. * Since: 2.1.0 **/ const hb_ot_name_entry_t * diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc index 2298aa92f2..224f8b842e 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc @@ -635,6 +635,11 @@ modifier_combining_marks[] = 0x06E3u, /* ARABIC SMALL LOW SEEN */ 0x06E7u, /* ARABIC SMALL HIGH YEH */ 0x06E8u, /* ARABIC SMALL HIGH NOON */ + 0x08CAu, /* ARABIC SMALL HIGH FARSI YEH */ + 0x08CBu, /* ARABIC SMALL HIGH YEH BARREE WITH TWO DOTS BELOW */ + 0x08CDu, /* ARABIC SMALL HIGH ZAH */ + 0x08CEu, /* ARABIC LARGE ROUND DOT ABOVE */ + 0x08CFu, /* ARABIC LARGE ROUND DOT BELOW */ 0x08D3u, /* ARABIC SMALL LOW WAW */ 0x08F3u, /* ARABIC SMALL HIGH WAW */ }; diff --git a/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 c3920b2cc6..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 @@ -92,234 +92,449 @@ enum use_syllable_type_t { #define use_syllable_machine_ex_VMPst 39u #define use_syllable_machine_ex_VPre 22u #define use_syllable_machine_ex_VPst 35u +#define use_syllable_machine_ex_WJ 16u #define use_syllable_machine_ex_ZWNJ 14u -#line 99 "hb-ot-shape-complex-use-machine.hh" +#line 100 "hb-ot-shape-complex-use-machine.hh" static const unsigned char _use_syllable_machine_trans_keys[] = { - 0u, 51u, 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, 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, 2, 1, 38, 38, 1, 27, 26, + 52, 38, 38, 48, 26, 24, 23, 22, + 2, 1, 25, 25, 25, 1, 25, 27, + 26, 26, 26, 37, 37, 37, 37, 38, + 1, 38, 2, 1, 38, 38, 48, 26, 24, 23, 22, 2, 1, 25, 25, 25, - 1, 25, 26, 26, 26, 27, 27, 27, - 38, 48, 1, 1, 38, 38, 1, 27, - 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, 56, 58, 97, 136, 138, 166, - 193, 218, 242, 265, 268, 270, 296, 322, - 348, 350, 376, 403, 430, 457, 485, 513, - 541, 580, 629, 631, 633, 672, 711, 713, - 741, 768, 793, 817, 840, 843, 845, 871, - 897, 923, 925, 951, 978, 1005, 1032, 1060, - 1088, 1116, 1155, 1204, 1206, 1208, 1257, 1296, - 1299, 1301, 1307, 1311, 1316 + 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, 0, 35, 34, - 35, 34, 37, 38, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 39, 40, 41, - 42, 43, 44, 45, 39, 46, 1, 47, - 48, 49, 50, 36, 51, 52, 53, 36, - 36, 36, 36, 54, 55, 56, 57, 38, - 36, 37, 38, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 39, 40, 41, 42, - 43, 44, 45, 39, 46, 47, 47, 48, - 49, 50, 36, 51, 52, 53, 36, 36, - 36, 36, 54, 55, 56, 57, 38, 36, - 37, 58, 39, 40, 41, 42, 43, 36, - 36, 36, 36, 36, 36, 48, 49, 50, - 36, 51, 52, 53, 36, 36, 36, 36, - 40, 55, 56, 57, 59, 36, 40, 41, - 42, 43, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 51, 52, 53, 36, - 36, 36, 36, 36, 55, 56, 57, 59, - 36, 41, 42, 43, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 55, 56, - 57, 36, 42, 43, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 55, 56, - 57, 36, 43, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 55, 56, 57, - 36, 55, 56, 36, 56, 36, 41, 42, - 43, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 51, 52, 53, 36, 36, - 36, 36, 36, 55, 56, 57, 59, 36, - 41, 42, 43, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 52, 53, - 36, 36, 36, 36, 36, 55, 56, 57, - 59, 36, 41, 42, 43, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, - 36, 53, 36, 36, 36, 36, 36, 55, - 56, 57, 59, 36, 61, 60, 41, 42, - 43, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 55, 56, 57, 59, 36, - 40, 41, 42, 43, 36, 36, 36, 36, - 36, 36, 48, 49, 50, 36, 51, 52, - 53, 36, 36, 36, 36, 40, 55, 56, - 57, 59, 36, 40, 41, 42, 43, 36, - 36, 36, 36, 36, 36, 36, 49, 50, - 36, 51, 52, 53, 36, 36, 36, 36, - 40, 55, 56, 57, 59, 36, 40, 41, - 42, 43, 36, 36, 36, 36, 36, 36, - 36, 36, 50, 36, 51, 52, 53, 36, - 36, 36, 36, 40, 55, 56, 57, 59, - 36, 39, 40, 41, 42, 43, 36, 45, - 39, 36, 36, 36, 48, 49, 50, 36, - 51, 52, 53, 36, 36, 36, 36, 40, - 55, 56, 57, 59, 36, 39, 40, 41, - 42, 43, 36, 36, 39, 36, 36, 36, - 48, 49, 50, 36, 51, 52, 53, 36, - 36, 36, 36, 40, 55, 56, 57, 59, - 36, 39, 40, 41, 42, 43, 44, 45, - 39, 36, 36, 36, 48, 49, 50, 36, - 51, 52, 53, 36, 36, 36, 36, 40, - 55, 56, 57, 59, 36, 37, 38, 36, - 36, 36, 36, 36, 36, 36, 36, 36, - 39, 40, 41, 42, 43, 44, 45, 39, - 46, 36, 47, 48, 49, 50, 36, 51, - 52, 53, 36, 36, 36, 36, 54, 55, - 56, 57, 38, 36, 37, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 40, 41, 42, 43, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, - 51, 52, 53, 58, 58, 58, 58, 58, - 55, 56, 57, 59, 58, 63, 62, 3, - 64, 37, 38, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 39, 40, 41, 42, - 43, 44, 45, 39, 46, 1, 47, 48, - 49, 50, 36, 51, 52, 53, 36, 0, - 35, 36, 54, 55, 56, 57, 38, 36, - 5, 6, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 9, 10, 11, 12, 13, - 14, 15, 9, 16, 18, 18, 19, 20, - 21, 65, 22, 23, 24, 65, 65, 65, - 65, 28, 29, 30, 31, 6, 65, 5, - 65, 9, 10, 11, 12, 13, 65, 65, - 65, 65, 65, 65, 19, 20, 21, 65, - 22, 23, 24, 65, 65, 65, 65, 10, - 29, 30, 31, 66, 65, 10, 11, 12, - 13, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 22, 23, 24, 65, 65, - 65, 65, 65, 29, 30, 31, 66, 65, - 11, 12, 13, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 29, 30, 31, - 65, 12, 13, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 29, 30, 31, - 65, 13, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 29, 30, 31, 65, - 29, 30, 65, 30, 65, 11, 12, 13, - 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 22, 23, 24, 65, 65, 65, - 65, 65, 29, 30, 31, 66, 65, 11, - 12, 13, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 23, 24, 65, - 65, 65, 65, 65, 29, 30, 31, 66, - 65, 11, 12, 13, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, - 24, 65, 65, 65, 65, 65, 29, 30, - 31, 66, 65, 67, 65, 11, 12, 13, - 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 29, 30, 31, 66, 65, 10, - 11, 12, 13, 65, 65, 65, 65, 65, - 65, 19, 20, 21, 65, 22, 23, 24, - 65, 65, 65, 65, 10, 29, 30, 31, - 66, 65, 10, 11, 12, 13, 65, 65, - 65, 65, 65, 65, 65, 20, 21, 65, - 22, 23, 24, 65, 65, 65, 65, 10, - 29, 30, 31, 66, 65, 10, 11, 12, - 13, 65, 65, 65, 65, 65, 65, 65, - 65, 21, 65, 22, 23, 24, 65, 65, - 65, 65, 10, 29, 30, 31, 66, 65, - 9, 10, 11, 12, 13, 65, 15, 9, - 65, 65, 65, 19, 20, 21, 65, 22, - 23, 24, 65, 65, 65, 65, 10, 29, - 30, 31, 66, 65, 9, 10, 11, 12, - 13, 65, 65, 9, 65, 65, 65, 19, - 20, 21, 65, 22, 23, 24, 65, 65, - 65, 65, 10, 29, 30, 31, 66, 65, - 9, 10, 11, 12, 13, 14, 15, 9, - 65, 65, 65, 19, 20, 21, 65, 22, - 23, 24, 65, 65, 65, 65, 10, 29, - 30, 31, 66, 65, 5, 6, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 9, - 10, 11, 12, 13, 14, 15, 9, 16, - 65, 18, 19, 20, 21, 65, 22, 23, - 24, 65, 65, 65, 65, 28, 29, 30, - 31, 6, 65, 5, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, - 65, 10, 11, 12, 13, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 22, - 23, 24, 65, 65, 65, 65, 65, 29, - 30, 31, 66, 65, 68, 65, 7, 65, - 1, 65, 65, 65, 1, 65, 65, 65, - 65, 65, 5, 6, 7, 65, 65, 65, - 65, 65, 65, 65, 65, 9, 10, 11, - 12, 13, 14, 15, 9, 16, 17, 18, - 19, 20, 21, 65, 22, 23, 24, 65, - 25, 26, 65, 28, 29, 30, 31, 6, - 65, 5, 6, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 9, 10, 11, 12, - 13, 14, 15, 9, 16, 17, 18, 19, - 20, 21, 65, 22, 23, 24, 65, 65, - 65, 65, 28, 29, 30, 31, 6, 65, - 25, 26, 65, 26, 65, 1, 69, 69, - 69, 1, 69, 71, 70, 32, 70, 32, - 71, 70, 71, 70, 32, 70, 33, 70, - 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, 3, 0, 26, 28, 29, 30, 51, - 53, 31, 32, 33, 34, 35, 46, 47, - 48, 54, 49, 43, 44, 45, 38, 39, - 40, 55, 56, 57, 50, 36, 37, 0, - 58, 60, 0, 2, 0, 4, 5, 6, - 7, 8, 9, 10, 21, 22, 23, 24, - 18, 19, 20, 13, 14, 15, 25, 11, - 12, 0, 0, 16, 0, 17, 0, 27, - 0, 0, 41, 42, 52, 0, 0, 59 + 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, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 7, 8, 0, 9, 0, 10, 0, - 11, 12, 0, 0, 0, 13, 14, 0 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 9, 10, 0, + 11, 0, 12, 13, 0, 14, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8, 0, 0, 10, 0, 0, 15, + 0, 0, 0, 16, 17, 0 }; static const char _use_syllable_machine_to_state_actions[] = { @@ -330,7 +545,13 @@ 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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[] = { @@ -341,18 +562,30 @@ 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 37, 37, 59, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 37, - 61, 37, 37, 37, 37, 37, 37, 37, - 37, 59, 63, 65, 37, 66, 66, 66, - 66, 66, 66, 66, 66, 66, 66, 66, - 66, 66, 66, 66, 66, 66, 66, 66, - 66, 66, 66, 66, 66, 66, 66, 66, - 66, 70, 71, 71, 71 + 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; @@ -366,7 +599,7 @@ static const int use_syllable_machine_en_main = 0; -#line 179 "hb-ot-shape-complex-use-machine.rl" +#line 181 "hb-ot-shape-complex-use-machine.rl" #define found_syllable(syllable_type) \ @@ -385,7 +618,9 @@ struct machine_index_t : typename Iter::item_t> { machine_index_t (const Iter& it) : it (it) {} - machine_index_t (const machine_index_t& o) : it (o.it) {} + machine_index_t (const machine_index_t& o) : hb_iter_with_fallback_t<machine_index_t<Iter>, + typename Iter::item_t> (), + it (o.it), is_null (o.is_null) {} static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator; static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator; @@ -397,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 { @@ -420,7 +669,7 @@ HB_FUNCOBJ (machine_index); static bool not_ccs_default_ignorable (const hb_glyph_info_t &i) -{ return !(i.use_category() == USE(CGJ) && _hb_glyph_info_is_default_ignorable (&i)); } +{ return i.use_category() != USE(CGJ); } static inline void find_syllables_use (hb_buffer_t *buffer) @@ -449,7 +698,7 @@ find_syllables_use (hb_buffer_t *buffer) unsigned int act HB_UNUSED; int cs; -#line 453 "hb-ot-shape-complex-use-machine.hh" +#line 702 "hb-ot-shape-complex-use-machine.hh" { cs = use_syllable_machine_start; ts = 0; @@ -457,12 +706,12 @@ find_syllables_use (hb_buffer_t *buffer) act = 0; } -#line 263 "hb-ot-shape-complex-use-machine.rl" +#line 281 "hb-ot-shape-complex-use-machine.rl" unsigned int syllable_serial = 1; -#line 466 "hb-ot-shape-complex-use-machine.hh" +#line 715 "hb-ot-shape-complex-use-machine.hh" { int _slen; int _trans; @@ -476,7 +725,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 480 "hb-ot-shape-complex-use-machine.hh" +#line 729 "hb-ot-shape-complex-use-machine.hh" } _keys = _use_syllable_machine_trans_keys + (cs<<1); @@ -494,55 +743,79 @@ _eof_trans: goto _again; switch ( _use_syllable_machine_trans_actions[_trans] ) { - case 7: -#line 169 "hb-ot-shape-complex-use-machine.rl" + case 9: +#line 171 "hb-ot-shape-complex-use-machine.rl" {te = p+1;{ found_syllable (use_standard_cluster); }} break; - case 4: + case 6: #line 174 "hb-ot-shape-complex-use-machine.rl" + {te = p+1;{ found_syllable (use_symbol_cluster); }} + break; + case 4: +#line 176 "hb-ot-shape-complex-use-machine.rl" {te = p+1;{ found_syllable (use_broken_cluster); }} break; case 3: -#line 175 "hb-ot-shape-complex-use-machine.rl" +#line 177 "hb-ot-shape-complex-use-machine.rl" {te = p+1;{ found_syllable (use_non_cluster); }} break; - case 8: -#line 167 "hb-ot-shape-complex-use-machine.rl" - {te = p;p--;{ found_syllable (use_virama_terminated_cluster); }} - break; - case 9: -#line 168 "hb-ot-shape-complex-use-machine.rl" + case 11: +#line 170 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (use_sakot_terminated_cluster); }} break; - case 6: -#line 169 "hb-ot-shape-complex-use-machine.rl" + case 7: +#line 171 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (use_standard_cluster); }} break; - case 11: -#line 170 "hb-ot-shape-complex-use-machine.rl" + case 14: +#line 172 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (use_number_joiner_terminated_cluster); }} break; - case 10: -#line 171 "hb-ot-shape-complex-use-machine.rl" + case 13: +#line 173 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (use_numeral_cluster); }} break; case 5: -#line 172 "hb-ot-shape-complex-use-machine.rl" +#line 174 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (use_symbol_cluster); }} break; - case 14: -#line 173 "hb-ot-shape-complex-use-machine.rl" + case 17: +#line 175 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (use_hieroglyph_cluster); }} break; - case 12: -#line 174 "hb-ot-shape-complex-use-machine.rl" + case 15: +#line 176 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (use_broken_cluster); }} break; - case 13: -#line 175 "hb-ot-shape-complex-use-machine.rl" + case 16: +#line 177 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (use_non_cluster); }} break; -#line 546 "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: @@ -551,7 +824,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 555 "hb-ot-shape-complex-use-machine.hh" +#line 828 "hb-ot-shape-complex-use-machine.hh" } if ( ++p != pe ) @@ -567,7 +840,7 @@ _again: } -#line 268 "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 7a3a995c8c..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 */ @@ -62,6 +62,7 @@ #define SE USE(SE) /* HIEROGLYPH_SEGMENT_END */ #define SUB USE(SUB) /* CONS_SUB */ #define Sk USE(Sk) /* SAKOT */ +#define WJ USE(WJ) /* Word_Joiner */ #define ZWNJ USE(ZWNJ) /* ZWNJ */ #define CMAbv USE(CMAbv) #define CMBlw USE(CMBlw) @@ -102,7 +103,7 @@ static const uint8_t use_table[] = { /* Latin-1 Supplement */ - /* 00A0 */ GB, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 00A0 */ GB, O, O, O, O, O, O, O, O, O, O, O, O, WJ, O, O, /* 00B0 */ O, O, FMPst, FMPst, O, O, O, O, O, O, O, O, O, O, O, O, /* 00C0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, /* 00D0 */ O, O, O, O, O, O, O, GB, @@ -127,7 +128,7 @@ static const uint8_t use_table[] = { O, O, B, B, B, B, B, B, /* 07D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 07E0 */ B, B, B, B, B, B, B, B, B, B, B, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, - /* 07F0 */ VMAbv, VMAbv, VMAbv, VMAbv, O, O, O, O, O, O, B, O, O, VMAbv, O, O, + /* 07F0 */ VMAbv, VMAbv, VMAbv, VMAbv, O, O, O, O, O, O, B, WJ, WJ, VMAbv, O, O, #define use_offset_0x0840u 152 @@ -135,7 +136,7 @@ static const uint8_t use_table[] = { /* Mandaic */ /* 0840 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 0850 */ B, B, B, B, B, B, B, B, B, CMBlw, CMBlw, CMBlw, O, O, O, O, + /* 0850 */ B, B, B, B, B, B, B, B, B, CMBlw, CMBlw, CMBlw, WJ, WJ, O, WJ, #define use_offset_0x0900u 184 @@ -153,102 +154,102 @@ static const uint8_t use_table[] = { /* Bengali */ - /* 0980 */ GB, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, O, B, - /* 0990 */ B, O, O, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 09A0 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, - /* 09B0 */ B, O, B, O, O, O, B, B, B, B, O, O, CMBlw, B, VPst, VPre, - /* 09C0 */ VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, O, O, VPre, VPre, H, O, O, - /* 09D0 */ O, O, O, O, O, O, O, VPst, O, O, O, O, B, B, O, B, - /* 09E0 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, - /* 09F0 */ B, B, O, O, O, O, O, O, O, O, O, O, B, O, FMAbv, O, + /* 0980 */ GB, VMAbv, VMPst, VMPst, WJ, B, B, B, B, B, B, B, B, WJ, WJ, B, + /* 0990 */ B, WJ, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 09A0 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B, + /* 09B0 */ B, WJ, B, WJ, WJ, WJ, B, B, B, B, WJ, WJ, CMBlw, B, VPst, VPre, + /* 09C0 */ VPst, VBlw, VBlw, VBlw, VBlw, WJ, WJ, VPre, VPre, WJ, WJ, VPre, VPre, H, O, WJ, + /* 09D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, VPst, WJ, WJ, WJ, WJ, B, B, WJ, B, + /* 09E0 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B, + /* 09F0 */ B, B, O, O, O, O, O, O, O, O, O, O, B, O, FMAbv, WJ, /* Gurmukhi */ - /* 0A00 */ O, VMAbv, VMAbv, VMPst, O, B, B, B, B, B, B, O, O, O, O, B, - /* 0A10 */ B, O, O, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 0A20 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, - /* 0A30 */ B, O, B, B, O, B, B, O, B, B, O, O, CMBlw, O, VPst, VPre, - /* 0A40 */ VPst, VBlw, VBlw, O, O, O, O, VAbv, VAbv, O, O, VAbv, VAbv, H, O, O, - /* 0A50 */ O, VMBlw, O, O, O, O, O, O, O, B, B, B, B, O, B, O, - /* 0A60 */ O, O, O, O, O, O, B, B, B, B, B, B, B, B, B, B, - /* 0A70 */ VMAbv, CMAbv, GB, GB, O, MBlw, O, O, O, O, O, O, O, O, O, O, + /* 0A00 */ WJ, VMAbv, VMAbv, VMPst, WJ, B, B, B, B, B, B, WJ, WJ, WJ, WJ, B, + /* 0A10 */ B, WJ, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 0A20 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B, + /* 0A30 */ B, WJ, B, B, WJ, B, B, WJ, B, B, WJ, WJ, CMBlw, WJ, VPst, VPre, + /* 0A40 */ VPst, VBlw, VBlw, WJ, WJ, WJ, WJ, VAbv, VAbv, WJ, WJ, VAbv, VAbv, H, WJ, WJ, + /* 0A50 */ WJ, VMBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, B, B, B, B, WJ, B, WJ, + /* 0A60 */ WJ, WJ, WJ, WJ, WJ, WJ, B, B, B, B, B, B, B, B, B, B, + /* 0A70 */ VMAbv, CMAbv, GB, GB, O, MBlw, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* Gujarati */ - /* 0A80 */ O, VMAbv, VMAbv, VMPst, O, B, B, B, B, B, B, B, B, B, O, B, - /* 0A90 */ B, B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 0AA0 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, - /* 0AB0 */ B, O, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VPre, - /* 0AC0 */ VPst, VBlw, VBlw, VBlw, VBlw, VAbv, O, VAbv, VAbv, VAbv, O, VPst, VPst, H, O, O, - /* 0AD0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* 0AE0 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, - /* 0AF0 */ O, O, O, O, O, O, O, O, O, B, VMAbv, VMAbv, VMAbv, CMAbv, CMAbv, CMAbv, + /* 0A80 */ WJ, VMAbv, VMAbv, VMPst, WJ, B, B, B, B, B, B, B, B, B, WJ, B, + /* 0A90 */ B, B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 0AA0 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B, + /* 0AB0 */ B, WJ, B, B, WJ, B, B, B, B, B, WJ, WJ, CMBlw, B, VPst, VPre, + /* 0AC0 */ VPst, VBlw, VBlw, VBlw, VBlw, VAbv, WJ, VAbv, VAbv, VAbv, WJ, VPst, VPst, H, WJ, WJ, + /* 0AD0 */ O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* 0AE0 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B, + /* 0AF0 */ O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, B, VMAbv, VMAbv, VMAbv, CMAbv, CMAbv, CMAbv, /* Oriya */ - /* 0B00 */ O, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, O, B, - /* 0B10 */ B, O, O, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 0B20 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, - /* 0B30 */ B, O, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VAbv, - /* 0B40 */ VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, O, O, VPre, VPre, H, O, O, - /* 0B50 */ O, O, O, O, O, VAbv, VAbv, VAbv, O, O, O, O, B, B, O, B, - /* 0B60 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, - /* 0B70 */ O, B, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 0B00 */ WJ, VMAbv, VMPst, VMPst, WJ, B, B, B, B, B, B, B, B, WJ, WJ, B, + /* 0B10 */ B, WJ, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 0B20 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B, + /* 0B30 */ B, WJ, B, B, WJ, B, B, B, B, B, WJ, WJ, CMBlw, B, VPst, VAbv, + /* 0B40 */ VPst, VBlw, VBlw, VBlw, VBlw, WJ, WJ, VPre, VPre, WJ, WJ, VPre, VPre, H, WJ, WJ, + /* 0B50 */ WJ, WJ, WJ, WJ, WJ, VAbv, VAbv, VAbv, WJ, WJ, WJ, WJ, B, B, WJ, B, + /* 0B60 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B, + /* 0B70 */ O, B, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* Tamil */ - /* 0B80 */ O, O, VMAbv, O, O, B, B, B, B, B, B, O, O, O, B, B, - /* 0B90 */ B, O, B, B, B, B, O, O, O, B, B, O, B, O, B, B, - /* 0BA0 */ O, O, O, B, B, O, O, O, B, B, B, O, O, O, B, B, - /* 0BB0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, VPst, VPst, - /* 0BC0 */ VAbv, VPst, VPst, O, O, O, VPre, VPre, VPre, O, VPre, VPre, VPre, H, O, O, - /* 0BD0 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, O, O, - /* 0BE0 */ O, O, O, O, O, O, B, B, B, B, B, B, B, B, B, B, - /* 0BF0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 0B80 */ WJ, WJ, VMAbv, O, WJ, B, B, B, B, B, B, WJ, WJ, WJ, B, B, + /* 0B90 */ B, WJ, B, B, B, B, WJ, WJ, WJ, B, B, WJ, B, WJ, B, B, + /* 0BA0 */ WJ, WJ, WJ, B, B, WJ, WJ, WJ, B, B, B, WJ, WJ, WJ, B, B, + /* 0BB0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, VPst, VPst, + /* 0BC0 */ VAbv, VPst, VPst, WJ, WJ, WJ, VPre, VPre, VPre, WJ, VPre, VPre, VPre, H, WJ, WJ, + /* 0BD0 */ O, WJ, WJ, WJ, WJ, WJ, WJ, VPst, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* 0BE0 */ WJ, WJ, WJ, WJ, WJ, WJ, B, B, B, B, B, B, B, B, B, B, + /* 0BF0 */ O, O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, /* Telugu */ - /* 0C00 */ VMAbv, VMPst, VMPst, VMPst, VMAbv, B, B, B, B, B, B, B, B, O, B, B, - /* 0C10 */ B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 0C20 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, - /* 0C30 */ B, B, B, B, B, B, B, B, B, B, O, O, CMBlw, B, VAbv, VAbv, - /* 0C40 */ VAbv, VPst, VPst, VPst, VPst, O, VAbv, VAbv, VAbv, O, VAbv, VAbv, VAbv, H, O, O, - /* 0C50 */ O, O, O, O, O, VAbv, VBlw, O, B, B, B, O, O, O, O, O, - /* 0C60 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, - /* 0C70 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 0C00 */ VMAbv, VMPst, VMPst, VMPst, VMAbv, B, B, B, B, B, B, B, B, WJ, B, B, + /* 0C10 */ B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 0C20 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B, + /* 0C30 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, CMBlw, B, VAbv, VAbv, + /* 0C40 */ VAbv, VPst, VPst, VPst, VPst, WJ, VAbv, VAbv, VAbv, WJ, VAbv, VAbv, VAbv, H, WJ, WJ, + /* 0C50 */ WJ, WJ, WJ, WJ, WJ, VAbv, VBlw, WJ, B, B, B, WJ, WJ, O, WJ, WJ, + /* 0C60 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B, + /* 0C70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, O, O, O, O, O, /* Kannada */ - /* 0C80 */ B, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, B, B, - /* 0C90 */ B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 0CA0 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, - /* 0CB0 */ B, B, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VAbv, - /* 0CC0 */ VAbv, VPst, VPst, VPst, VPst, O, VAbv, VAbv, VAbv, O, VAbv, VAbv, VAbv, H, O, O, - /* 0CD0 */ O, O, O, O, O, VPst, VPst, O, O, O, O, O, O, O, B, O, - /* 0CE0 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, - /* 0CF0 */ O, CS, CS, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 0C80 */ B, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, WJ, B, B, + /* 0C90 */ B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 0CA0 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B, + /* 0CB0 */ B, B, B, B, WJ, B, B, B, B, B, WJ, WJ, CMBlw, B, VPst, VAbv, + /* 0CC0 */ VAbv, VPst, VPst, VPst, VPst, WJ, VAbv, VAbv, VAbv, WJ, VAbv, VAbv, VAbv, H, WJ, WJ, + /* 0CD0 */ WJ, WJ, WJ, WJ, WJ, VPst, VPst, WJ, WJ, WJ, WJ, WJ, WJ, O, B, WJ, + /* 0CE0 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B, + /* 0CF0 */ WJ, CS, CS, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* Malayalam */ - /* 0D00 */ VMAbv, VMAbv, VMPst, VMPst, B, B, B, B, B, B, B, B, B, O, B, B, - /* 0D10 */ B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 0D00 */ VMAbv, VMAbv, VMPst, VMPst, B, B, B, B, B, B, B, B, B, WJ, B, B, + /* 0D10 */ B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 0D20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 0D30 */ B, B, B, B, B, B, B, B, B, B, B, VAbv, VAbv, B, VPst, VPst, - /* 0D40 */ VPst, VPst, VPst, VBlw, VBlw, O, VPre, VPre, VPre, O, VPre, VPre, VPre, H, R, O, - /* 0D50 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, O, B, - /* 0D60 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, + /* 0D40 */ VPst, VPst, VPst, VBlw, VBlw, WJ, VPre, VPre, VPre, WJ, VPre, VPre, VPre, H, R, O, + /* 0D50 */ WJ, WJ, WJ, WJ, O, O, O, VPst, O, O, O, O, O, O, O, B, + /* 0D60 */ B, B, VBlw, VBlw, WJ, WJ, B, B, B, B, B, B, B, B, B, B, /* 0D70 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, /* Sinhala */ - /* 0D80 */ O, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, B, B, B, - /* 0D90 */ B, B, B, B, B, B, B, O, O, O, B, B, B, B, B, B, + /* 0D80 */ WJ, VMAbv, VMPst, VMPst, WJ, B, B, B, B, B, B, B, B, B, B, B, + /* 0D90 */ B, B, B, B, B, B, B, WJ, WJ, WJ, B, B, B, B, B, B, /* 0DA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 0DB0 */ B, B, O, B, B, B, B, B, B, B, B, B, O, B, O, O, - /* 0DC0 */ B, B, B, B, B, B, B, O, O, O, H, O, O, O, O, VPst, - /* 0DD0 */ VPst, VPst, VAbv, VAbv, VBlw, O, VBlw, O, VPst, VPre, VPre, VPre, VPre, VPre, VPre, VPst, - /* 0DE0 */ O, O, O, O, O, O, B, B, B, B, B, B, B, B, B, B, - /* 0DF0 */ O, O, VPst, VPst, O, O, O, O, + /* 0DB0 */ B, B, WJ, B, B, B, B, B, B, B, B, B, WJ, B, WJ, WJ, + /* 0DC0 */ B, B, B, B, B, B, B, WJ, WJ, WJ, H, WJ, WJ, WJ, WJ, VPst, + /* 0DD0 */ VPst, VPst, VAbv, VAbv, VBlw, WJ, VBlw, WJ, VPst, VPre, VPre, VPre, VPre, VPre, VPre, VPst, + /* 0DE0 */ WJ, WJ, WJ, WJ, WJ, WJ, B, B, B, B, B, B, B, B, B, B, + /* 0DF0 */ WJ, WJ, VPst, VPst, O, WJ, WJ, WJ, #define use_offset_0x0f00u 1456 @@ -259,14 +260,14 @@ static const uint8_t use_table[] = { /* 0F10 */ O, O, O, O, O, O, O, O, VBlw, VBlw, O, O, O, O, O, O, /* 0F20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 0F30 */ B, B, B, B, O, FBlw, O, FBlw, O, CMAbv, O, O, O, O, VPst, VPre, - /* 0F40 */ B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, B, + /* 0F40 */ B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B, B, /* 0F50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 0F60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, - /* 0F70 */ O, CMBlw, VBlw, VAbv, VAbv, VBlw, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VMAbv, O, + /* 0F60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, + /* 0F70 */ WJ, CMBlw, VBlw, VAbv, VAbv, VBlw, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VMAbv, O, /* 0F80 */ VBlw, VAbv, VMAbv, VMAbv, VBlw, O, VMAbv, VMAbv, B, B, B, B, B, SUB, SUB, SUB, - /* 0F90 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, O, SUB, SUB, SUB, SUB, SUB, SUB, SUB, + /* 0F90 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, WJ, SUB, SUB, SUB, SUB, SUB, SUB, SUB, /* 0FA0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, - /* 0FB0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, O, O, O, + /* 0FB0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, WJ, O, O, /* 0FC0 */ O, O, O, O, O, O, FBlw, O, #define use_offset_0x1000u 1656 @@ -277,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, @@ -291,22 +292,22 @@ static const uint8_t use_table[] = { /* Tagalog */ /* 1700 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1710 */ B, B, VAbv, VBlw, VBlw, VPst, O, O, O, O, O, O, O, O, O, B, + /* 1710 */ B, B, VAbv, VBlw, VBlw, VPst, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, B, /* Hanunoo */ /* 1720 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1730 */ B, B, VAbv, VBlw, VPst, O, O, O, O, O, O, O, O, O, O, O, + /* 1730 */ B, B, VAbv, VBlw, VPst, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* Buhid */ /* 1740 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1750 */ B, B, VAbv, VBlw, O, O, O, O, O, O, O, O, O, O, O, O, + /* 1750 */ B, B, VAbv, VBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* Tagbanwa */ - /* 1760 */ B, B, B, B, B, B, B, B, B, B, B, B, B, O, B, B, - /* 1770 */ B, O, VAbv, VBlw, O, O, O, O, O, O, O, O, O, O, O, O, + /* 1760 */ B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, B, B, + /* 1770 */ B, WJ, VAbv, VBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* Khmer */ @@ -315,23 +316,23 @@ 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, O, O, - /* 17E0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, - /* 17F0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 17D0 */ FMAbv, VAbv, IS, FMAbv, O, O, O, O, O, O, O, O, B, FMAbv, WJ, WJ, + /* 17E0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, + /* 17F0 */ O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, /* Mongolian */ - /* 1800 */ B, O, O, O, O, O, O, B, O, O, B, CGJ, CGJ, CGJ, O, CGJ, - /* 1810 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 1800 */ B, O, O, O, O, O, O, B, O, O, B, CGJ, CGJ, CGJ, WJ, CGJ, + /* 1810 */ O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, /* 1820 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1830 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1840 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1850 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1860 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1870 */ B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, O, + /* 1870 */ B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* 1880 */ GB, GB, GB, GB, GB, CMAbv, CMAbv, B, B, B, B, B, B, B, B, B, /* 1890 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18A0 */ B, B, B, B, B, B, B, B, B, CMBlw, B, O, O, O, O, O, + /* 18A0 */ B, B, B, B, B, B, B, B, B, CMBlw, B, WJ, WJ, WJ, WJ, WJ, #define use_offset_0x1900u 2248 @@ -339,43 +340,43 @@ static const uint8_t use_table[] = { /* Limbu */ /* 1900 */ GB, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, O, - /* 1920 */ VAbv, VAbv, VBlw, VPst, VPst, VAbv, VAbv, VAbv, VAbv, SUB, SUB, SUB, O, O, O, O, - /* 1930 */ FPst, FPst, VMBlw, FPst, FPst, FPst, FPst, FPst, FPst, FBlw, VMAbv, FMBlw, O, O, O, O, - /* 1940 */ O, O, O, O, O, O, B, B, B, B, B, B, B, B, B, B, + /* 1910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, + /* 1920 */ VAbv, VAbv, VBlw, VPst, VPst, VAbv, VAbv, VAbv, VAbv, SUB, SUB, SUB, WJ, WJ, WJ, WJ, + /* 1930 */ FPst, FPst, VMBlw, FPst, FPst, FPst, FPst, FPst, FPst, FBlw, VMAbv, FMBlw, WJ, WJ, WJ, WJ, + /* 1940 */ O, WJ, WJ, WJ, O, O, B, B, B, B, B, B, B, B, B, B, /* Tai Le */ /* 1950 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1960 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, O, O, - /* 1970 */ B, B, B, B, B, O, O, O, O, O, O, O, O, O, O, O, + /* 1960 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, + /* 1970 */ B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* New Tai Lue */ /* 1980 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1990 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 19A0 */ B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, + /* 19A0 */ B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, /* 19B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 19C0 */ B, B, B, B, B, B, B, B, VMPst, VMPst, O, O, O, O, O, O, - /* 19D0 */ B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, + /* 19C0 */ B, B, B, B, B, B, B, B, VMPst, VMPst, WJ, WJ, WJ, WJ, WJ, WJ, + /* 19D0 */ B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, O, O, /* 19E0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, /* 19F0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, /* Buginese */ /* 1A00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1A10 */ B, B, B, B, B, B, B, VAbv, VAbv, VPre, VPst, VAbv, O, O, O, O, + /* 1A10 */ B, B, B, B, B, B, B, VAbv, VAbv, VPre, VPst, VAbv, WJ, WJ, O, O, /* Tai Tham */ /* 1A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1A30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1A40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1A50 */ B, B, B, B, B, MPre, MBlw, SUB, FAbv, FAbv, MAbv, SUB, SUB, SUB, SUB, O, + /* 1A50 */ B, B, B, B, B, MPre, MBlw, SUB, FAbv, FAbv, MAbv, SUB, SUB, SUB, SUB, WJ, /* 1A60 */ Sk, VPst, VAbv, VPst, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VAbv, VBlw, VPst, VPre, VPre, - /* 1A70 */ VPre, VPre, VPre, VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VAbv, VMAbv, VMAbv, O, O, VMBlw, - /* 1A80 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, - /* 1A90 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, + /* 1A70 */ VPre, VPre, VPre, VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VAbv, VMAbv, VMAbv, WJ, WJ, VMBlw, + /* 1A80 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, + /* 1A90 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, #define use_offset_0x1b00u 2664 @@ -386,16 +387,16 @@ static const uint8_t use_table[] = { /* 1B10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1B20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1B30 */ B, B, B, B, CMAbv, VPst, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VPre, VPre, - /* 1B40 */ VPre, VPre, VAbv, VAbv, H, B, B, B, B, B, B, B, B, O, O, O, - /* 1B50 */ B, B, B, B, B, B, B, B, B, B, O, GB, GB, O, O, GB, - /* 1B60 */ O, O, GB, O, O, O, O, O, GB, O, O, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv, - /* 1B70 */ SMAbv, SMAbv, SMAbv, SMAbv, O, O, O, O, O, O, O, O, O, O, O, O, + /* 1B40 */ VPre, VPre, VAbv, VAbv, H, B, B, B, B, B, B, B, B, WJ, WJ, WJ, + /* 1B50 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, + /* 1B60 */ O, O, O, O, O, O, O, O, O, O, O, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv, + /* 1B70 */ SMAbv, SMAbv, SMAbv, SMAbv, O, O, O, O, O, O, O, O, O, O, O, WJ, /* Sundanese */ /* 1B80 */ VMAbv, FAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1B90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1BA0 */ B, SUB, SUB, SUB, VAbv, VBlw, VPre, VPst, VAbv, VAbv, VPst, H, SUB, SUB, B, B, + /* 1BA0 */ B, SUB, SUB, SUB, VAbv, VBlw, VPre, VPst, VAbv, VAbv, VPst, IS, SUB, SUB, B, B, /* 1BB0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* Batak */ @@ -403,15 +404,15 @@ static const uint8_t use_table[] = { /* 1BC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1BD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1BE0 */ B, B, B, B, B, B, CMAbv, VPst, VAbv, VAbv, VPst, VPst, VPst, VAbv, VPst, VAbv, - /* 1BF0 */ FAbv, FAbv, CMBlw, CMBlw, O, O, O, O, O, O, O, O, O, O, O, O, + /* 1BF0 */ FAbv, FAbv, CMBlw, CMBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, /* Lepcha */ /* 1C00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1C10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1C20 */ B, B, B, B, SUB, SUB, VPst, VPre, VPre, VPre, VPst, VPst, VBlw, FAbv, FAbv, FAbv, - /* 1C30 */ FAbv, FAbv, FAbv, FAbv, VMPre, VMPre, FMAbv, CMBlw, O, O, O, O, O, O, O, O, - /* 1C40 */ B, B, B, B, B, B, B, B, B, B, O, O, O, B, B, B, + /* 1C30 */ FAbv, FAbv, FAbv, FAbv, VMPre, VMPre, FMAbv, CMBlw, WJ, WJ, WJ, O, O, O, O, O, + /* 1C40 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, B, B, B, #define use_offset_0x1cd0u 3000 @@ -420,7 +421,7 @@ static const uint8_t use_table[] = { /* 1CD0 */ VMAbv, VMAbv, VMAbv, O, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMAbv, VMAbv, VMBlw, VMBlw, VMBlw, VMBlw, /* 1CE0 */ VMAbv, VMPst, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, O, O, O, O, VMBlw, O, O, - /* 1CF0 */ O, O, O, O, VMAbv, CS, CS, VMPst, VMAbv, VMAbv, GB, O, O, O, O, O, + /* 1CF0 */ O, O, O, O, VMAbv, CS, CS, VMPst, VMAbv, VMAbv, GB, WJ, WJ, WJ, WJ, WJ, #define use_offset_0x1df8u 3048 @@ -432,31 +433,33 @@ static const uint8_t use_table[] = { /* General Punctuation */ - O, O, O, O, ZWNJ, CGJ, O, O, - /* 2010 */ GB, GB, GB, GB, GB, O, O, O, - -#define use_offset_0x2070u 3072 - + O, O, O, WJ, ZWNJ, CGJ, WJ, WJ, + /* 2010 */ GB, GB, GB, GB, GB, O, O, O, O, O, O, O, O, O, O, O, + /* 2020 */ O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, O, + /* 2030 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 2040 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 2050 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 2060 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* Superscripts and Subscripts */ - /* 2070 */ O, O, O, O, FMPst, O, O, O, O, O, O, O, O, O, O, O, + /* 2070 */ O, O, WJ, WJ, FMPst, O, O, O, O, O, O, O, O, O, O, O, /* 2080 */ O, O, FMPst, FMPst, FMPst, O, O, O, -#define use_offset_0x20f0u 3096 +#define use_offset_0x20f0u 3184 /* Combining Diacritical Marks for Symbols */ - /* 20F0 */ VMAbv, O, O, O, O, O, O, O, + /* 20F0 */ VMAbv, WJ, WJ, WJ, WJ, WJ, WJ, WJ, -#define use_offset_0x25c8u 3104 +#define use_offset_0x25c8u 3192 /* Geometric Shapes */ O, O, O, O, B, O, O, O, -#define use_offset_0x2d30u 3112 +#define use_offset_0x2d30u 3200 /* Tifinagh */ @@ -464,25 +467,25 @@ static const uint8_t use_table[] = { /* 2D30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 2D40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 2D50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 2D60 */ B, B, B, B, B, B, B, B, O, O, O, O, O, O, O, B, - /* 2D70 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, H, + /* 2D60 */ B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, B, + /* 2D70 */ O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, H, -#define use_offset_0xa800u 3192 +#define use_offset_0xa800u 3280 /* Syloti Nagri */ /* A800 */ B, B, VAbv, B, B, B, H, B, B, B, B, VMAbv, B, B, B, B, /* A810 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* A820 */ B, B, B, VPst, VPst, VBlw, VAbv, VPst, O, O, O, O, VBlw, O, O, O, - /* A830 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* A820 */ B, B, B, VPst, VPst, VBlw, VAbv, VPst, O, O, O, O, VBlw, WJ, WJ, WJ, + /* A830 */ O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, /* Phags-pa */ /* A840 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* A850 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* A860 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* A870 */ B, B, B, B, O, O, O, O, O, O, O, O, O, O, O, O, + /* A870 */ B, B, B, B, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* Saurashtra */ @@ -490,8 +493,8 @@ static const uint8_t use_table[] = { /* A890 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* A8A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* A8B0 */ B, B, B, B, MPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, - /* A8C0 */ VPst, VPst, VPst, VPst, H, VMAbv, O, O, O, O, O, O, O, O, O, O, - /* A8D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, + /* A8C0 */ VPst, VPst, VPst, VPst, H, VMAbv, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, + /* A8D0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, /* Devanagari Extended */ @@ -508,9 +511,9 @@ static const uint8_t use_table[] = { /* A930 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* A940 */ B, B, B, B, B, B, B, VBlw, VBlw, VBlw, VAbv, VBlw, VBlw, VBlw, VBlw, FAbv, - /* A950 */ FAbv, FAbv, FPst, VPst, O, O, O, O, O, O, O, O, O, O, O, O, + /* A950 */ FAbv, FAbv, FPst, VPst, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, /* A960 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* A970 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* A970 */ O, O, O, O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, /* Javanese */ @@ -518,22 +521,22 @@ static const uint8_t use_table[] = { /* A990 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* A9A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* A9B0 */ B, B, B, CMAbv, VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VPre, VAbv, MBlw, MPst, MBlw, - /* A9C0 */ H, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* A9D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, + /* A9C0 */ H, O, O, O, O, O, O, O, O, O, O, O, O, O, WJ, O, + /* A9D0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, O, O, /* Myanmar Extended-B */ /* A9E0 */ B, B, B, B, B, VAbv, O, B, B, B, B, B, B, B, B, B, - /* A9F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, O, + /* A9F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, /* Cham */ /* AA00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* AA10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* AA20 */ B, B, B, B, B, B, B, B, B, VMAbv, VAbv, VAbv, VAbv, VBlw, VAbv, VPre, - /* AA30 */ VPre, VAbv, VBlw, MPst, MPre, MAbv, MBlw, O, O, O, O, O, O, O, O, O, - /* AA40 */ B, B, B, FAbv, B, B, B, B, B, B, B, B, FAbv, FPst, O, O, - /* AA50 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, + /* AA30 */ VPre, VAbv, VBlw, MPst, MPre, MAbv, MBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* AA40 */ B, B, B, FAbv, B, B, B, B, B, B, B, B, FAbv, FPst, WJ, WJ, + /* AA50 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, O, O, O, O, /* Myanmar Extended-A */ @@ -546,115 +549,128 @@ static const uint8_t use_table[] = { /* AA90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* AAA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* AAB0 */ VAbv, B, VAbv, VAbv, VBlw, B, B, VAbv, VAbv, B, B, B, B, B, VAbv, VMAbv, - /* AAC0 */ B, VMAbv, B, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* AAD0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* AAC0 */ B, VMAbv, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* AAD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, O, /* Meetei Mayek Extensions */ /* AAE0 */ B, B, B, B, B, B, B, B, B, B, B, VPre, VBlw, VAbv, VPre, VPst, - /* AAF0 */ O, O, O, O, O, VMPst, H, O, + /* AAF0 */ O, O, O, O, O, VMPst, IS, WJ, -#define use_offset_0xabc0u 3952 +#define use_offset_0xabc0u 4040 /* Meetei Mayek */ /* ABC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* ABD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* ABE0 */ B, B, B, VPst, VPst, VAbv, VPst, VPst, VBlw, VPst, VPst, O, VMPst, VBlw, O, O, - /* ABF0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, + /* ABE0 */ B, B, B, VPst, VPst, VAbv, VPst, VPst, VBlw, VPst, VPst, O, VMPst, VBlw, WJ, WJ, + /* ABF0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, -#define use_offset_0xfe00u 4016 +#define use_offset_0xfe00u 4104 /* Variation Selectors */ /* FE00 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, -#define use_offset_0x10570u 4032 +#define use_offset_0xfef8u 4120 + + + /* Arabic Presentation Forms-B */ + O, O, O, O, O, WJ, WJ, WJ, + +#define use_offset_0xfff0u 4128 + + + /* Specials */ + + /* FFF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, O, WJ, WJ, + +#define use_offset_0x10570u 4144 /* Vithkuqi */ - /* 10570 */ B, B, B, B, B, B, B, B, B, B, B, O, B, B, B, B, - /* 10580 */ B, B, B, B, B, B, B, B, B, B, B, O, B, B, B, B, - /* 10590 */ B, B, B, O, B, B, O, B, B, B, B, B, B, B, B, B, - /* 105A0 */ B, B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 105B0 */ B, B, O, B, B, B, B, B, B, B, O, B, B, O, O, O, + /* 10570 */ B, B, B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, + /* 10580 */ B, B, B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, + /* 10590 */ B, B, B, WJ, B, B, WJ, B, B, B, B, B, B, B, B, B, + /* 105A0 */ B, B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 105B0 */ B, B, WJ, B, B, B, B, B, B, B, WJ, B, B, WJ, WJ, WJ, -#define use_offset_0x10a00u 4112 +#define use_offset_0x10a00u 4224 /* Kharoshthi */ - /* 10A00 */ B, VBlw, VBlw, VBlw, O, VAbv, VBlw, O, O, O, O, O, VPst, VMBlw, VMBlw, VMAbv, - /* 10A10 */ B, B, B, B, O, B, B, B, O, B, B, B, B, B, B, B, + /* 10A00 */ B, VBlw, VBlw, VBlw, WJ, VAbv, VBlw, WJ, WJ, WJ, WJ, WJ, VPst, VMBlw, VMBlw, VMAbv, + /* 10A10 */ B, B, B, B, WJ, B, B, B, WJ, B, B, B, B, B, B, B, /* 10A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 10A30 */ B, B, B, B, B, B, O, O, CMAbv, CMBlw, CMBlw, O, O, O, O, H, - /* 10A40 */ B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, O, + /* 10A30 */ B, B, B, B, B, B, WJ, WJ, CMAbv, CMBlw, CMBlw, WJ, WJ, WJ, WJ, IS, + /* 10A40 */ B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, -#define use_offset_0x10ac0u 4192 +#define use_offset_0x10ac0u 4304 /* Manichaean */ /* 10AC0 */ B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, B, /* 10AD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 10AE0 */ B, B, B, B, B, CMBlw, CMBlw, O, O, O, O, B, B, B, B, B, + /* 10AE0 */ B, B, B, B, B, CMBlw, CMBlw, WJ, WJ, WJ, WJ, B, B, B, B, B, -#define use_offset_0x10b80u 4240 +#define use_offset_0x10b80u 4352 /* Psalter Pahlavi */ /* 10B80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 10B90 */ B, B, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* 10BA0 */ O, O, O, O, O, O, O, O, O, B, B, B, B, B, B, O, + /* 10B90 */ B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, WJ, WJ, WJ, + /* 10BA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, B, B, B, B, B, B, O, -#define use_offset_0x10d00u 4288 +#define use_offset_0x10d00u 4400 /* Hanifi Rohingya */ /* 10D00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 10D10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 10D20 */ B, B, B, B, VMAbv, VMAbv, VMAbv, CMAbv, O, O, O, O, O, O, O, O, - /* 10D30 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, + /* 10D20 */ B, B, B, B, VMAbv, VMAbv, VMAbv, CMAbv, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* 10D30 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, -#define use_offset_0x10e80u 4352 +#define use_offset_0x10e80u 4464 /* Yezidi */ /* 10E80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 10E90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 10EA0 */ B, B, B, B, B, B, B, B, B, B, O, VAbv, VAbv, O, O, O, - /* 10EB0 */ B, B, O, O, O, O, O, O, + /* 10EA0 */ B, B, B, B, B, B, B, B, B, B, WJ, VAbv, VAbv, O, WJ, WJ, + /* 10EB0 */ B, B, WJ, WJ, WJ, WJ, WJ, WJ, -#define use_offset_0x10f30u 4408 +#define use_offset_0x10f30u 4520 /* Sogdian */ /* 10F30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 10F40 */ B, B, B, B, B, B, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, - /* 10F50 */ VMBlw, B, B, B, B, O, O, O, O, O, O, O, O, O, O, O, - /* 10F60 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 10F50 */ VMBlw, B, B, B, B, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, + /* 10F60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* Old Uyghur */ /* 10F70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 10F80 */ B, B, CMBlw, CMBlw, CMBlw, CMBlw, O, O, O, O, O, O, O, O, O, O, - /* 10F90 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* 10FA0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 10F80 */ B, B, CMBlw, CMBlw, CMBlw, CMBlw, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, + /* 10F90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* 10FA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* Chorasmian */ /* 10FB0 */ B, O, B, B, B, B, B, O, B, B, B, B, B, B, B, B, - /* 10FC0 */ O, B, B, B, B, O, O, O, O, B, B, B, O, O, O, O, - /* 10FD0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 10FC0 */ O, B, B, B, B, O, O, O, O, B, B, B, WJ, WJ, WJ, WJ, + /* 10FD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* 10FE0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* 10FF0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 10FF0 */ O, O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* Brahmi */ @@ -662,10 +678,10 @@ static const uint8_t use_table[] = { /* 11010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11020 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11030 */ B, B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, - /* 11040 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, H, O, O, O, O, O, O, O, O, O, - /* 11050 */ O, O, N, N, N, N, N, N, N, N, N, N, N, N, N, N, + /* 11040 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, H, O, O, O, O, O, O, O, WJ, WJ, + /* 11050 */ WJ, WJ, N, N, N, N, N, N, N, N, N, N, N, N, N, N, /* 11060 */ N, N, N, N, N, N, B, B, B, B, B, B, B, B, B, B, - /* 11070 */ VAbv, B, B, VAbv, VAbv, B, O, O, O, O, O, O, O, O, O, HN, + /* 11070 */ VAbv, B, B, VAbv, VAbv, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, HN, /* Kaithi */ @@ -673,9 +689,9 @@ static const uint8_t use_table[] = { /* 11090 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 110A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 110B0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VPst, VPst, H, CMBlw, O, O, O, O, O, - /* 110C0 */ O, O, VBlw, O, O, O, O, O, + /* 110C0 */ O, O, VBlw, WJ, WJ, WJ, WJ, WJ, -#define use_offset_0x11100u 4816 +#define use_offset_0x11100u 4928 /* Chakma */ @@ -683,14 +699,14 @@ static const uint8_t use_table[] = { /* 11100 */ VMAbv, VMAbv, VMAbv, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11110 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11120 */ B, B, B, B, B, B, B, VBlw, VBlw, VBlw, VAbv, VAbv, VPre, VBlw, VAbv, VAbv, - /* 11130 */ VBlw, VAbv, VAbv, H, CMAbv, O, B, B, B, B, B, B, B, B, B, B, - /* 11140 */ O, O, O, O, B, VPst, VPst, B, O, O, O, O, O, O, O, O, + /* 11130 */ VBlw, VAbv, VAbv, IS, CMAbv, WJ, B, B, B, B, B, B, B, B, B, B, + /* 11140 */ O, O, O, O, B, VPst, VPst, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* Mahajani */ /* 11150 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11160 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11170 */ B, B, B, CMBlw, O, O, O, O, O, O, O, O, O, O, O, O, + /* 11170 */ B, B, B, CMBlw, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* Sharada */ @@ -698,50 +714,50 @@ static const uint8_t use_table[] = { /* 11190 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 111A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 111B0 */ B, B, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, - /* 111C0 */ H, B, R, R, O, O, O, O, GB, FMBlw, CMBlw, VAbv, VBlw, O, VPre, VMAbv, + /* 111C0 */ H, B, R, R, O, O, O, O, O, FMBlw, CMBlw, VAbv, VBlw, O, VPre, VMAbv, /* 111D0 */ B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, /* Sinhala Archaic Numbers */ - /* 111E0 */ O, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 111F0 */ B, B, B, B, B, O, O, O, O, O, O, O, O, O, O, O, + /* 111E0 */ WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 111F0 */ B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* Khojki */ /* 11200 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11210 */ B, B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 11210 */ B, B, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11220 */ B, B, B, B, B, B, B, B, B, B, B, B, VPst, VPst, VPst, VBlw, - /* 11230 */ VAbv, VAbv, VAbv, VAbv, VMAbv, H, CMAbv, CMAbv, O, O, O, O, O, O, VMAbv, O, + /* 11230 */ VAbv, VAbv, VAbv, VAbv, VMAbv, H, CMAbv, CMAbv, O, O, O, O, O, O, VMAbv, WJ, -#define use_offset_0x11280u 5136 +#define use_offset_0x11280u 5248 /* Multani */ - /* 11280 */ B, B, B, B, B, B, B, O, B, O, B, B, B, B, O, B, - /* 11290 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, O, B, - /* 112A0 */ B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, O, + /* 11280 */ B, B, B, B, B, B, B, WJ, B, WJ, B, B, B, B, WJ, B, + /* 11290 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, B, + /* 112A0 */ B, B, B, B, B, B, B, B, B, O, WJ, WJ, WJ, WJ, WJ, WJ, /* Khudawadi */ /* 112B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 112C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 112D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VMAbv, - /* 112E0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, CMBlw, VBlw, O, O, O, O, O, - /* 112F0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, + /* 112E0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, CMBlw, VBlw, WJ, WJ, WJ, WJ, WJ, + /* 112F0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, /* Grantha */ - /* 11300 */ VMAbv, VMAbv, VMAbv, VMAbv, O, B, B, B, B, B, B, B, B, O, O, B, - /* 11310 */ B, O, O, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11320 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, - /* 11330 */ B, O, B, B, O, B, B, B, B, B, O, CMBlw, CMBlw, B, VPst, VPst, - /* 11340 */ VAbv, VPst, VPst, VPst, VPst, O, O, VPre, VPre, O, O, VPre, VPre, HVM, O, O, - /* 11350 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, B, B, - /* 11360 */ B, B, VPst, VPst, O, O, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O, - /* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O, + /* 11300 */ VMAbv, VMAbv, VMAbv, VMAbv, WJ, B, B, B, B, B, B, B, B, WJ, WJ, B, + /* 11310 */ B, WJ, WJ, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 11320 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B, + /* 11330 */ B, WJ, B, B, WJ, B, B, B, B, B, WJ, CMBlw, CMBlw, B, VPst, VPst, + /* 11340 */ VAbv, VPst, VPst, VPst, VPst, WJ, WJ, VPre, VPre, WJ, WJ, VPre, VPre, H, WJ, WJ, + /* 11350 */ O, WJ, WJ, WJ, WJ, WJ, WJ, VPst, WJ, WJ, WJ, WJ, WJ, O, B, B, + /* 11360 */ B, B, VPst, VPst, WJ, WJ, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, WJ, WJ, WJ, + /* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, WJ, WJ, WJ, -#define use_offset_0x11400u 5384 +#define use_offset_0x11400u 5496 /* Newa */ @@ -751,9 +767,9 @@ static const uint8_t use_table[] = { /* 11420 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11430 */ B, B, B, B, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, /* 11440 */ VPst, VPst, H, VMAbv, VMAbv, VMPst, CMBlw, B, O, O, O, O, O, O, O, O, - /* 11450 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, FMAbv, B, - /* 11460 */ CS, CS, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* 11470 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 11450 */ B, B, B, B, B, B, B, B, B, B, O, O, WJ, O, FMAbv, B, + /* 11460 */ CS, CS, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* 11470 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* Tirhuta */ @@ -761,10 +777,10 @@ static const uint8_t use_table[] = { /* 11490 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 114A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 114B0 */ VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VPre, VAbv, VPre, VPre, VPst, VPre, VMAbv, - /* 114C0 */ VMAbv, VMAbv, H, CMBlw, B, O, O, O, O, O, O, O, O, O, O, O, - /* 114D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, + /* 114C0 */ VMAbv, VMAbv, H, CMBlw, B, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* 114D0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, -#define use_offset_0x11580u 5608 +#define use_offset_0x11580u 5720 /* Siddham */ @@ -772,11 +788,11 @@ static const uint8_t use_table[] = { /* 11580 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11590 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 115A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VPst, - /* 115B0 */ VPre, VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, VPre, VPre, VMAbv, VMAbv, VMPst, H, + /* 115B0 */ VPre, VPst, VBlw, VBlw, VBlw, VBlw, WJ, WJ, VPre, VPre, VPre, VPre, VMAbv, VMAbv, VMPst, H, /* 115C0 */ CMBlw, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* 115D0 */ O, O, O, O, O, O, O, O, B, B, B, B, VBlw, VBlw, O, O, - /* 115E0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* 115F0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 115D0 */ O, O, O, O, O, O, O, O, B, B, B, B, VBlw, VBlw, WJ, WJ, + /* 115E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* 115F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* Modi */ @@ -784,31 +800,31 @@ static const uint8_t use_table[] = { /* 11610 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11620 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11630 */ VPst, VPst, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VPst, VPst, VMAbv, VMPst, H, - /* 11640 */ VAbv, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* 11650 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, - /* 11660 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* 11670 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 11640 */ VAbv, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* 11650 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, + /* 11660 */ O, O, O, O, O, O, O, O, O, O, O, O, O, WJ, WJ, WJ, + /* 11670 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* Takri */ /* 11680 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11690 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 116A0 */ B, B, B, B, B, B, B, B, B, B, B, VMAbv, VMPst, VAbv, VPre, VPst, - /* 116B0 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, H, CMBlw, B, O, O, O, O, O, O, O, - /* 116C0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, - /* 116D0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* 116E0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* 116F0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 116B0 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, H, CMBlw, B, O, WJ, WJ, WJ, WJ, WJ, WJ, + /* 116C0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, + /* 116D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* 116E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* 116F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* Ahom */ /* 11700 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11710 */ B, B, B, B, B, B, B, B, B, B, B, O, O, MBlw, MPre, MAbv, - /* 11720 */ VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VBlw, VAbv, VAbv, VAbv, O, O, O, O, + /* 11710 */ B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, MBlw, MPre, MAbv, + /* 11720 */ VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VBlw, VAbv, VAbv, VAbv, WJ, WJ, WJ, WJ, /* 11730 */ B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, - /* 11740 */ B, B, B, B, B, B, B, O, + /* 11740 */ B, B, B, B, B, B, B, WJ, -#define use_offset_0x11800u 6064 +#define use_offset_0x11800u 6176 /* Dogra */ @@ -816,31 +832,31 @@ static const uint8_t use_table[] = { /* 11800 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11810 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11820 */ B, B, B, B, B, B, B, B, B, B, B, B, VPst, VPre, VPst, VBlw, - /* 11830 */ VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VMAbv, VMPst, H, CMBlw, O, O, O, O, O, + /* 11830 */ VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VMAbv, VMPst, H, CMBlw, O, WJ, WJ, WJ, WJ, -#define use_offset_0x11900u 6128 +#define use_offset_0x11900u 6240 /* Dives Akuru */ - /* 11900 */ B, B, B, B, B, B, B, O, O, B, O, O, B, B, B, B, - /* 11910 */ B, B, B, B, O, B, B, O, B, B, B, B, B, B, B, B, + /* 11900 */ B, B, B, B, B, B, B, WJ, WJ, B, WJ, WJ, B, B, B, B, + /* 11910 */ B, B, B, B, WJ, B, B, WJ, B, B, B, B, B, B, B, B, /* 11920 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11930 */ VPst, VPst, VPst, VPst, VPst, VPre, O, VPre, VPre, O, O, VMAbv, VMAbv, VPst, H, R, - /* 11940 */ MPst, R, MPst, CMBlw, O, O, O, O, O, O, O, O, O, O, O, O, - /* 11950 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, + /* 11930 */ VPst, VPst, VPst, VPst, VPst, VPre, WJ, VPre, VPre, WJ, WJ, VMAbv, VMAbv, VPst, IS, R, + /* 11940 */ MPst, R, MPst, CMBlw, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* 11950 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, -#define use_offset_0x119a0u 6224 +#define use_offset_0x119a0u 6336 /* Nandinagari */ - /* 119A0 */ B, B, B, B, B, B, B, B, O, O, B, B, B, B, B, B, + /* 119A0 */ B, B, B, B, B, B, B, B, WJ, WJ, B, B, B, B, B, B, /* 119B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 119C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 119D0 */ B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, O, O, VAbv, VAbv, VPst, VPst, VMPst, VMPst, - /* 119E0 */ H, B, O, O, VPre, O, O, O, O, O, O, O, O, O, O, O, - /* 119F0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 119D0 */ B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, WJ, WJ, VAbv, VAbv, VPst, VPst, VMPst, VMPst, + /* 119E0 */ H, B, O, O, VPre, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* 119F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* Zanabazar Square */ @@ -848,7 +864,7 @@ static const uint8_t use_table[] = { /* 11A10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11A30 */ B, B, B, FMBlw, VBlw, VMAbv, VMAbv, VMAbv, VMAbv, VMPst, R, MBlw, MBlw, MBlw, MBlw, GB, - /* 11A40 */ O, O, O, O, O, GB, O, H, O, O, O, O, O, O, O, O, + /* 11A40 */ O, O, O, O, O, GB, O, IS, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* Soyombo */ @@ -856,50 +872,50 @@ static const uint8_t use_table[] = { /* 11A60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11A70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11A80 */ B, B, B, B, R, R, R, R, R, R, FBlw, FBlw, FBlw, FBlw, FBlw, FBlw, - /* 11A90 */ FBlw, FBlw, FBlw, FBlw, FBlw, FBlw, VMAbv, VMPst, CMAbv, H, O, O, O, B, O, O, + /* 11A90 */ FBlw, FBlw, FBlw, FBlw, FBlw, FBlw, VMAbv, VMPst, CMAbv, IS, O, O, O, B, O, O, -#define use_offset_0x11c00u 6480 +#define use_offset_0x11c00u 6592 /* Bhaiksuki */ - /* 11C00 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, + /* 11C00 */ B, B, B, B, B, B, B, B, B, WJ, B, B, B, B, B, B, /* 11C10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11C20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VPst, - /* 11C30 */ VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VBlw, O, VAbv, VAbv, VAbv, VAbv, VMAbv, VMAbv, VMPst, H, - /* 11C40 */ B, O, O, O, GB, GB, O, O, O, O, O, O, O, O, O, O, + /* 11C30 */ VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VBlw, WJ, VAbv, VAbv, VAbv, VAbv, VMAbv, VMAbv, VMPst, H, + /* 11C40 */ B, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* 11C50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11C60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, + /* 11C60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, /* Marchen */ /* 11C70 */ O, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11C80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11C90 */ O, O, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, - /* 11CA0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, O, SUB, SUB, SUB, SUB, SUB, SUB, SUB, - /* 11CB0 */ VBlw, VPre, VBlw, VAbv, VPst, VMAbv, VMAbv, O, + /* 11C90 */ WJ, WJ, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, + /* 11CA0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, WJ, SUB, SUB, SUB, SUB, SUB, SUB, SUB, + /* 11CB0 */ VBlw, VPre, VBlw, VAbv, VPst, VMAbv, VMAbv, WJ, -#define use_offset_0x11d00u 6664 +#define use_offset_0x11d00u 6776 /* Masaram Gondi */ - /* 11D00 */ B, B, B, B, B, B, B, O, B, B, O, B, B, B, B, B, + /* 11D00 */ B, B, B, B, B, B, B, WJ, B, B, WJ, B, B, B, B, B, /* 11D10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11D20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11D30 */ B, VAbv, VAbv, VAbv, VAbv, VAbv, VBlw, O, O, O, VAbv, O, VAbv, VAbv, O, VAbv, - /* 11D40 */ VMAbv, VMAbv, CMBlw, VAbv, VBlw, H, R, MBlw, O, O, O, O, O, O, O, O, - /* 11D50 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, + /* 11D30 */ B, VAbv, VAbv, VAbv, VAbv, VAbv, VBlw, WJ, WJ, WJ, VAbv, WJ, VAbv, VAbv, WJ, VAbv, + /* 11D40 */ VMAbv, VMAbv, CMBlw, VAbv, VBlw, IS, R, MBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* 11D50 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, /* Gunjala Gondi */ - /* 11D60 */ B, B, B, B, B, B, O, B, B, O, B, B, B, B, B, B, + /* 11D60 */ B, B, B, B, B, B, WJ, B, B, WJ, B, B, B, B, B, B, /* 11D70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 11D80 */ B, B, B, B, B, B, B, B, B, B, VPst, VPst, VPst, VPst, VPst, O, - /* 11D90 */ VAbv, VAbv, O, VPst, VPst, VMAbv, VMPst, H, O, O, O, O, O, O, O, O, - /* 11DA0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, + /* 11D80 */ B, B, B, B, B, B, B, B, B, B, VPst, VPst, VPst, VPst, VPst, WJ, + /* 11D90 */ VAbv, VAbv, WJ, VPst, VPst, VMAbv, VMPst, IS, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* 11DA0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, -#define use_offset_0x11ee0u 6840 +#define use_offset_0x11ee0u 6952 /* Makasar */ @@ -907,7 +923,7 @@ static const uint8_t use_table[] = { /* 11EE0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11EF0 */ B, B, GB, VAbv, VBlw, VPre, VPst, O, -#define use_offset_0x13000u 6864 +#define use_offset_0x13000u 6976 /* Egyptian Hieroglyphs */ @@ -978,21 +994,21 @@ static const uint8_t use_table[] = { /* 133F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 13400 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 13410 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 13420 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, O, + /* 13420 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, /* Egyptian Hieroglyph Format Controls */ - /* 13430 */ H, H, H, H, H, H, H, B, B, O, O, O, O, O, O, O, + /* 13430 */ H, H, H, H, H, H, H, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, -#define use_offset_0x16ac0u 7952 +#define use_offset_0x16ac0u 8064 /* Tangsa */ - /* 16AC0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, + /* 16AC0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, /* 16AD0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* 16AE0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, - /* 16AF0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 16AE0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, WJ, WJ, + /* 16AF0 */ O, O, O, O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* Pahawh Hmong */ @@ -1001,7 +1017,7 @@ static const uint8_t use_table[] = { /* 16B20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 16B30 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, -#define use_offset_0x16f00u 8072 +#define use_offset_0x16f00u 8184 /* Miao */ @@ -1010,21 +1026,21 @@ static const uint8_t use_table[] = { /* 16F10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 16F20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 16F30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 16F40 */ B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, CMBlw, + /* 16F40 */ B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, CMBlw, /* 16F50 */ O, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, /* 16F60 */ VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, /* 16F70 */ VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, - /* 16F80 */ VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, O, O, O, O, O, O, O, VMBlw, + /* 16F80 */ VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, WJ, WJ, WJ, WJ, WJ, WJ, WJ, VMBlw, /* 16F90 */ VMBlw, VMBlw, VMBlw, O, O, O, O, O, -#define use_offset_0x16fe0u 8224 +#define use_offset_0x16fe0u 8336 /* Ideographic Symbols and Punctuation */ - /* 16FE0 */ O, O, O, O, B, O, O, O, + /* 16FE0 */ O, O, O, O, B, WJ, WJ, WJ, -#define use_offset_0x18b00u 8232 +#define use_offset_0x18b00u 8344 /* Khitan Small Script */ @@ -1058,9 +1074,9 @@ static const uint8_t use_table[] = { /* 18CA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 18CB0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 18CC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 18CD0 */ B, B, B, B, B, B, O, O, + /* 18CD0 */ B, B, B, B, B, B, WJ, WJ, -#define use_offset_0x1bc00u 8704 +#define use_offset_0x1bc00u 8816 /* Duployan */ @@ -1071,39 +1087,46 @@ static const uint8_t use_table[] = { /* 1BC30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1BC40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1BC50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1BC60 */ B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, - /* 1BC70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, - /* 1BC80 */ B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, O, - /* 1BC90 */ B, B, B, B, B, B, B, B, B, B, O, O, O, CMBlw, CMBlw, O, + /* 1BC60 */ B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, + /* 1BC70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, + /* 1BC80 */ B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* 1BC90 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, O, CMBlw, CMBlw, O, + +#define use_offset_0x1d170u 8976 + -#define use_offset_0x1e100u 8864 + /* Musical Symbols */ + + /* 1D170 */ O, O, O, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, O, O, O, O, O, + +#define use_offset_0x1e100u 8992 /* Nyiakeng Puachue Hmong */ /* 1E100 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1E110 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1E120 */ B, B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, - /* 1E130 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, B, B, B, B, B, B, B, O, O, - /* 1E140 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, B, B, + /* 1E120 */ B, B, B, B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, + /* 1E130 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, B, B, B, B, B, B, B, WJ, WJ, + /* 1E140 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, B, B, -#define use_offset_0x1e290u 8944 +#define use_offset_0x1e290u 9072 /* Toto */ /* 1E290 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1E2A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, VMAbv, O, - /* 1E2B0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 1E2A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, VMAbv, WJ, + /* 1E2B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* Wancho */ /* 1E2C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1E2D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1E2E0 */ B, B, B, B, B, B, B, B, B, B, B, B, VMAbv, VMAbv, VMAbv, VMAbv, - /* 1E2F0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, + /* 1E2F0 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, O, -#define use_offset_0x1e900u 9056 +#define use_offset_0x1e900u 9184 /* Adlam */ @@ -1112,11 +1135,33 @@ static const uint8_t use_table[] = { /* 1E910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1E920 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1E930 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1E940 */ B, B, B, B, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, B, O, O, O, O, - /* 1E950 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, + /* 1E940 */ B, B, B, B, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, B, WJ, WJ, WJ, WJ, + /* 1E950 */ B, B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, O, O, + +#define use_offset_0xe0000u 9280 + + + /* Tags */ -#define use_offset_0xe0100u 9152 + /* E0000 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0010 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0020 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0030 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0040 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0050 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0060 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0070 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* No_Block */ + + /* E0080 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0090 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E00A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E00B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E00C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E00D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E00E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E00F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, /* Variation Selectors Supplement */ @@ -1136,11 +1181,240 @@ static const uint8_t use_table[] = { /* E01D0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, /* E01E0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, -}; /* Table items: 9392; occupancy: 79% */ + /* No_Block */ + + /* E01F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0200 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0210 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0220 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0230 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0240 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0250 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0260 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0270 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0280 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0290 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E02A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E02B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E02C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E02D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E02E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E02F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0300 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0310 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0320 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0330 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0340 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0350 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0360 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0370 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0380 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0390 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E03A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E03B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E03C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E03D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E03E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E03F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0400 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0410 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0420 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0430 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0440 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0450 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0460 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0470 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0480 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0490 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E04A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E04B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E04C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E04D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E04E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E04F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0500 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0510 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0520 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0530 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0540 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0550 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0560 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0570 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0580 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0590 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E05A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E05B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E05C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E05D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E05E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E05F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0600 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0610 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0620 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0630 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0640 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0650 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0660 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0670 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0680 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0690 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E06A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E06B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E06C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E06D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E06E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E06F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0700 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0710 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0720 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0730 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0740 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0750 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0760 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0770 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0780 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0790 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E07A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E07B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E07C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E07D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E07E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E07F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0800 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0810 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0820 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0830 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0840 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0850 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0860 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0870 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0880 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0890 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E08A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E08B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E08C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E08D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E08E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E08F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0900 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0910 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0920 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0930 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0940 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0950 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0960 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0970 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0980 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0990 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E09A0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E09B0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E09C0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E09D0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E09E0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E09F0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0A00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0A10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0A20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0A30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0A40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0A50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0A60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0A70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0A80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0A90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0AA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0AB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0AC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0AD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0AE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0AF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0B00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0B10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0B20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0B30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0B40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0B50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0B60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0B70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0B80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0B90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0BA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0BB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0BC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0BD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0BE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0BF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0C00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0C10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0C20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0C30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0C40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0C50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0C60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0C70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0C80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0C90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0CA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0CB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0CC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0CD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0CE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0CF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0D00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0D10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0D20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0D30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0D40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0D50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0D60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0D70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0D80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0D90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0DA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0DB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0DC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0DD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0DE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0DF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0E00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0E10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0E20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0E30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0E40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0E50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0E60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0E70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0E80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0E90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0EA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0EB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0EC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0ED0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0EE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0EF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0F00 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0F10 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0F20 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0F30 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0F40 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0F50 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0F60 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0F70 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0F80 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0F90 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0FA0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0FB0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0FC0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0FD0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0FE0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + /* E0FF0 */ WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, WJ, + +}; /* Table items: 13376; occupancy: 84% */ static inline uint8_t -hb_use_get_category (hb_codepoint_t u) +hb_use_get_category (hb_glyph_info_t info) { + hb_codepoint_t u = info.codepoint; switch (u >> 12) { case 0x0u: @@ -1164,8 +1438,7 @@ hb_use_get_category (hb_codepoint_t u) break; case 0x2u: - if (hb_in_range<hb_codepoint_t> (u, 0x2008u, 0x2017u)) return use_table[u - 0x2008u + use_offset_0x2008u]; - if (hb_in_range<hb_codepoint_t> (u, 0x2070u, 0x2087u)) return use_table[u - 0x2070u + use_offset_0x2070u]; + if (hb_in_range<hb_codepoint_t> (u, 0x2008u, 0x2087u)) return use_table[u - 0x2008u + use_offset_0x2008u]; if (hb_in_range<hb_codepoint_t> (u, 0x20F0u, 0x20F7u)) return use_table[u - 0x20F0u + use_offset_0x20f0u]; if (hb_in_range<hb_codepoint_t> (u, 0x25C8u, 0x25CFu)) return use_table[u - 0x25C8u + use_offset_0x25c8u]; if (hb_in_range<hb_codepoint_t> (u, 0x2D30u, 0x2D7Fu)) return use_table[u - 0x2D30u + use_offset_0x2d30u]; @@ -1178,9 +1451,12 @@ hb_use_get_category (hb_codepoint_t u) case 0xFu: if (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu)) return use_table[u - 0xFE00u + use_offset_0xfe00u]; + if (hb_in_range<hb_codepoint_t> (u, 0xFEF8u, 0xFEFFu)) return use_table[u - 0xFEF8u + use_offset_0xfef8u]; + if (hb_in_range<hb_codepoint_t> (u, 0xFFF0u, 0xFFFFu)) return use_table[u - 0xFFF0u + use_offset_0xfff0u]; break; case 0x10u: + if (hb_in_range<hb_codepoint_t> (u, 0xFFF0u, 0xFFFFu)) return use_table[u - 0xFFF0u + use_offset_0xfff0u]; if (hb_in_range<hb_codepoint_t> (u, 0x10570u, 0x105BFu)) return use_table[u - 0x10570u + use_offset_0x10570u]; if (hb_in_range<hb_codepoint_t> (u, 0x10A00u, 0x10A4Fu)) return use_table[u - 0x10A00u + use_offset_0x10a00u]; if (hb_in_range<hb_codepoint_t> (u, 0x10AC0u, 0x10AEFu)) return use_table[u - 0x10AC0u + use_offset_0x10ac0u]; @@ -1222,6 +1498,10 @@ hb_use_get_category (hb_codepoint_t u) if (hb_in_range<hb_codepoint_t> (u, 0x1BC00u, 0x1BC9Fu)) return use_table[u - 0x1BC00u + use_offset_0x1bc00u]; break; + case 0x1Du: + if (hb_in_range<hb_codepoint_t> (u, 0x1D170u, 0x1D17Fu)) return use_table[u - 0x1D170u + use_offset_0x1d170u]; + break; + case 0x1Eu: if (hb_in_range<hb_codepoint_t> (u, 0x1E100u, 0x1E14Fu)) return use_table[u - 0x1E100u + use_offset_0x1e100u]; if (hb_in_range<hb_codepoint_t> (u, 0x1E290u, 0x1E2FFu)) return use_table[u - 0x1E290u + use_offset_0x1e290u]; @@ -1229,13 +1509,19 @@ hb_use_get_category (hb_codepoint_t u) break; case 0xE0u: - if (hb_in_range<hb_codepoint_t> (u, 0xE0100u, 0xE01EFu)) return use_table[u - 0xE0100u + use_offset_0xe0100u]; + if (hb_in_range<hb_codepoint_t> (u, 0xE0000u, 0xE0FFFu)) return use_table[u - 0xE0000u + use_offset_0xe0000u]; + break; + + case 0xE1u: + if (hb_in_range<hb_codepoint_t> (u, 0xE0000u, 0xE0FFFu)) return use_table[u - 0xE0000u + use_offset_0xe0000u]; break; default: break; } - return USE(O); + if (_hb_glyph_info_get_general_category (&info) == HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED) + return WJ; + return O; } #undef B @@ -1245,7 +1531,7 @@ hb_use_get_category (hb_codepoint_t u) #undef GB #undef H #undef HN -#undef HVM +#undef IS #undef J #undef N #undef O @@ -1254,6 +1540,7 @@ hb_use_get_category (hb_codepoint_t u) #undef SE #undef SUB #undef Sk +#undef WJ #undef ZWNJ #undef CMAbv #undef CMBlw diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc index 70b637933d..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++) @@ -206,7 +205,7 @@ setup_masks_use (const hb_ot_shape_plan_t *plan, unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) - info[i].use_category() = hb_use_get_category (info[i].codepoint); + info[i].use_category() = hb_use_get_category (info[i]); } static void @@ -257,7 +256,6 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan, use_syllable_type_t syllable_type = (use_syllable_type_t) (info[start].syllable() & 0x0F); switch (syllable_type) { - case use_symbol_cluster: case use_hieroglyph_cluster: case use_non_cluster: /* These don't join. Nothing to do. */ @@ -269,6 +267,7 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan, case use_standard_cluster: case use_number_joiner_terminated_cluster: case use_numeral_cluster: + case use_symbol_cluster: case use_broken_cluster: bool join = last_form == JOINING_FORM_FINA || last_form == JOINING_FORM_ISOL; @@ -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); } @@ -363,6 +362,7 @@ reorder_syllable_use (hb_buffer_t *buffer, unsigned int start, unsigned int end) (FLAG (use_virama_terminated_cluster) | FLAG (use_sakot_terminated_cluster) | FLAG (use_standard_cluster) | + FLAG (use_symbol_cluster) | FLAG (use_broken_cluster) | 0)))) return; diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-fallback.cc b/thirdparty/harfbuzz/src/hb-ot-shape-fallback.cc index 671f30327f..b2eedb027b 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-fallback.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-fallback.cc @@ -497,14 +497,14 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan, #endif #ifndef HB_DISABLE_DEPRECATED - if (!buffer->message (font, "start fallback kern")) - return; - if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction) ? !font->has_glyph_h_kerning_func () : !font->has_glyph_v_kerning_func ()) return; + if (!buffer->message (font, "start fallback kern")) + return; + bool reverse = HB_DIRECTION_IS_BACKWARD (buffer->props.direction); if (reverse) 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-tag-table.hh b/thirdparty/harfbuzz/src/hb-ot-tag-table.hh index 61d2814e93..5261783277 100644 --- a/thirdparty/harfbuzz/src/hb-ot-tag-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-tag-table.hh @@ -7,7 +7,7 @@ * on files with these headers: * * <meta name="updated_at" content="2022-01-28 10:00 PM" /> - * File-Date: 2021-12-29 + * File-Date: 2022-03-02 */ #ifndef HB_OT_TAG_TABLE_HH @@ -54,6 +54,7 @@ static const LangTag ot_languages[] = { /*{"aio", HB_TAG('A','I','O',' ')},*/ /* Aiton */ {"aiw", HB_TAG('A','R','I',' ')}, /* Aari */ {"ajp", HB_TAG('A','R','A',' ')}, /* South Levantine Arabic -> Arabic */ + {"ajt", HB_TAG('A','R','A',' ')}, /* Judeo-Tunisian Arabic (retired code) -> Arabic */ {"ak", HB_TAG('A','K','A',' ')}, /* Akan [macrolanguage] */ {"akb", HB_TAG('A','K','B',' ')}, /* Batak Angkola */ {"akb", HB_TAG('B','T','K',' ')}, /* Batak Angkola -> Batak */ @@ -809,7 +810,7 @@ static const LangTag ot_languages[] = { {"lac", HB_TAG('M','Y','N',' ')}, /* Lacandon -> Mayan */ {"lad", HB_TAG('J','U','D',' ')}, /* Ladino */ {"lah", HB_TAG_NONE }, /* Lahnda [macrolanguage] != Lahuli */ - {"lak", HB_TAG_NONE }, /* Laka (Nigeria) != Lak */ + {"lak", HB_TAG_NONE }, /* Laka (Nigeria) (retired code) != Lak */ {"lam", HB_TAG_NONE }, /* Lamba != Lambani */ {"laz", HB_TAG_NONE }, /* Aribwatsa != Laz */ {"lb", HB_TAG('L','T','Z',' ')}, /* Luxembourgish */ @@ -1339,12 +1340,14 @@ static const LangTag ot_languages[] = { {"sla", HB_TAG_NONE }, /* Slavic [collection] != Slavey */ {"sm", HB_TAG('S','M','O',' ')}, /* Samoan */ {"sma", HB_TAG('S','S','M',' ')}, /* Southern Sami */ + {"smd", HB_TAG('M','B','N',' ')}, /* Sama (retired code) -> Mbundu */ {"smj", HB_TAG('L','S','M',' ')}, /* Lule Sami */ {"sml", HB_TAG_NONE }, /* Central Sama != Somali */ {"smn", HB_TAG('I','S','M',' ')}, /* Inari Sami */ {"sms", HB_TAG('S','K','S',' ')}, /* Skolt Sami */ {"smt", HB_TAG('Q','I','N',' ')}, /* Simte -> Chin */ {"sn", HB_TAG('S','N','A','0')}, /* Shona */ + {"snb", HB_TAG('I','B','A',' ')}, /* Sebuyau (retired code) -> Iban */ {"snh", HB_TAG_NONE }, /* Shinabo (retired code) != Sinhala (Sinhalese) */ /*{"snk", HB_TAG('S','N','K',' ')},*/ /* Soninke */ {"so", HB_TAG('S','M','L',' ')}, /* Somali */ diff --git a/thirdparty/harfbuzz/src/hb-ot-tag.cc b/thirdparty/harfbuzz/src/hb-ot-tag.cc index 1837063af8..f50be97ad3 100644 --- a/thirdparty/harfbuzz/src/hb-ot-tag.cc +++ b/thirdparty/harfbuzz/src/hb-ot-tag.cc @@ -41,6 +41,7 @@ hb_ot_old_tag_from_script (hb_script_t script) switch ((hb_tag_t) script) { case HB_SCRIPT_INVALID: return HB_OT_TAG_DEFAULT_SCRIPT; + case HB_SCRIPT_MATH: return HB_OT_TAG_MATH_SCRIPT; /* KATAKANA and HIRAGANA both map to 'kana' */ case HB_SCRIPT_HIRAGANA: return HB_TAG('k','a','n','a'); @@ -63,6 +64,8 @@ hb_ot_old_tag_to_script (hb_tag_t tag) { if (unlikely (tag == HB_OT_TAG_DEFAULT_SCRIPT)) return HB_SCRIPT_INVALID; + if (unlikely (tag == HB_OT_TAG_MATH_SCRIPT)) + return HB_SCRIPT_MATH; /* This side of the conversion is fully algorithmic. */ diff --git a/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-repacker.hh b/thirdparty/harfbuzz/src/hb-repacker.hh index b1726d8beb..2a9e75c45b 100644 --- a/thirdparty/harfbuzz/src/hb-repacker.hh +++ b/thirdparty/harfbuzz/src/hb-repacker.hh @@ -37,7 +37,6 @@ * For a detailed writeup on the overflow resolution algorithm see: * docs/repacker.md */ - struct graph_t { struct vertex_t @@ -140,7 +139,8 @@ struct graph_t * the 'packed' object stack used internally in the * serializer */ - graph_t (const hb_vector_t<hb_serialize_context_t::object_t *>& objects) + template<typename T> + graph_t (const T& objects) : parents_invalid (true), distance_invalid (true), positions_invalid (true), @@ -1098,8 +1098,9 @@ struct graph_t hb_vector_t<unsigned> num_roots_for_space_; }; -static bool _try_isolating_subgraphs (const hb_vector_t<graph_t::overflow_record_t>& overflows, - graph_t& sorted_graph) +static inline +bool _try_isolating_subgraphs (const hb_vector_t<graph_t::overflow_record_t>& overflows, + graph_t& sorted_graph) { unsigned space = 0; hb_set_t roots_to_isolate; @@ -1147,9 +1148,10 @@ static bool _try_isolating_subgraphs (const hb_vector_t<graph_t::overflow_record return true; } -static bool _process_overflows (const hb_vector_t<graph_t::overflow_record_t>& overflows, - hb_set_t& priority_bumped_parents, - graph_t& sorted_graph) +static inline +bool _process_overflows (const hb_vector_t<graph_t::overflow_record_t>& overflows, + hb_set_t& priority_bumped_parents, + graph_t& sorted_graph) { bool resolution_attempted = false; @@ -1207,8 +1209,9 @@ static bool _process_overflows (const hb_vector_t<graph_t::overflow_record_t>& o * For a detailed writeup describing how the algorithm operates see: * docs/repacker.md */ +template<typename T> inline hb_blob_t* -hb_resolve_overflows (const hb_vector_t<hb_serialize_context_t::object_t *>& packed, +hb_resolve_overflows (const T& packed, hb_tag_t table_tag, unsigned max_rounds = 20) { // Kahn sort is ~twice as fast as shortest distance sort and works for many fonts diff --git a/thirdparty/harfbuzz/src/hb-serialize.hh b/thirdparty/harfbuzz/src/hb-serialize.hh index 6615f033c5..40895a4548 100644 --- a/thirdparty/harfbuzz/src/hb-serialize.hh +++ b/thirdparty/harfbuzz/src/hb-serialize.hh @@ -36,6 +36,9 @@ #include "hb-map.hh" #include "hb-pool.hh" +#ifdef HB_EXPERIMENTAL_API +#include "hb-subset-repacker.h" +#endif /* * Serialize @@ -70,6 +73,24 @@ struct hb_serialize_context_t virtual_links.fini (); } + object_t () = default; + +#ifdef HB_EXPERIMENTAL_API + object_t (const hb_object_t &o) + { + head = o.head; + tail = o.tail; + next = nullptr; + real_links.alloc (o.num_real_links); + for (unsigned i = 0 ; i < o.num_real_links; i++) + real_links.push (o.real_links[i]); + + virtual_links.alloc (o.num_virtual_links); + for (unsigned i = 0; i < o.num_virtual_links; i++) + virtual_links.push (o.virtual_links[i]); + } +#endif + bool operator == (const object_t &o) const { // Virtual links aren't considered for equality since they don't affect the functionality @@ -95,6 +116,20 @@ struct hb_serialize_context_t unsigned position: 28; unsigned bias; objidx_t objidx; + + link_t () = default; + +#ifdef HB_EXPERIMENTAL_API + link_t (const hb_link_t &o) + { + width = o.width; + is_signed = 0; + whence = 0; + position = o.position; + bias = 0; + objidx = o.objidx; + } +#endif }; char *head; 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-shape.cc b/thirdparty/harfbuzz/src/hb-shape.cc index c1f619c81c..3407e1af42 100644 --- a/thirdparty/harfbuzz/src/hb-shape.cc +++ b/thirdparty/harfbuzz/src/hb-shape.cc @@ -126,6 +126,13 @@ hb_shape_full (hb_font_t *font, unsigned int num_features, const char * const *shaper_list) { + hb_buffer_t *text_buffer = nullptr; + if (buffer->flags & HB_BUFFER_FLAG_VERIFY) + { + text_buffer = hb_buffer_create (); + hb_buffer_append (text_buffer, buffer, 0, -1); + } + hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached2 (font->face, &buffer->props, features, num_features, font->coords, font->num_coords, @@ -133,6 +140,17 @@ hb_shape_full (hb_font_t *font, hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num_features); hb_shape_plan_destroy (shape_plan); + if (text_buffer) + { + if (res && !buffer->verify (text_buffer, + font, + features, + num_features, + shaper_list)) + res = false; + hb_buffer_destroy (text_buffer); + } + return res; } diff --git a/thirdparty/harfbuzz/src/hb-static.cc b/thirdparty/harfbuzz/src/hb-static.cc index ec4b241470..7cc51be611 100644 --- a/thirdparty/harfbuzz/src/hb-static.cc +++ b/thirdparty/harfbuzz/src/hb-static.cc @@ -33,6 +33,7 @@ #include "hb-aat-layout-feat-table.hh" #include "hb-ot-layout-common.hh" #include "hb-ot-cmap-table.hh" +#include "hb-ot-glyf-table.hh" #include "hb-ot-head-table.hh" #include "hb-ot-maxp-table.hh" @@ -55,17 +56,43 @@ const unsigned char _hb_Null_AAT_Lookup[2] = {0xFF, 0xFF}; /* hb_face_t */ +#ifndef HB_NO_BORING_EXPANSION +static inline unsigned +load_num_glyphs_from_loca (const hb_face_t *face) +{ + unsigned ret = 0; + + unsigned indexToLocFormat = face->table.head->indexToLocFormat; + + if (indexToLocFormat <= 1) + { + bool short_offset = 0 == indexToLocFormat; + hb_blob_t *loca_blob = face->table.loca.get_blob (); + ret = hb_max (1u, loca_blob->length / (short_offset ? 2 : 4)) - 1; + } + + return ret; +} +#endif + +static inline unsigned +load_num_glyphs_from_maxp (const hb_face_t *face) +{ + return face->table.maxp->get_num_glyphs (); +} + unsigned int hb_face_t::load_num_glyphs () const { - hb_sanitize_context_t c = hb_sanitize_context_t (); - c.set_num_glyphs (0); /* So we don't recurse ad infinitum. */ - hb_blob_t *maxp_blob = c.reference_table<OT::maxp> (this); - const OT::maxp *maxp_table = maxp_blob->as<OT::maxp> (); + unsigned ret = 0; + +#ifndef HB_NO_BORING_EXPANSION + ret = hb_max (ret, load_num_glyphs_from_loca (this)); +#endif + + ret = hb_max (ret, load_num_glyphs_from_maxp (this)); - unsigned int ret = maxp_table->get_num_glyphs (); num_glyphs.set_relaxed (ret); - hb_blob_destroy (maxp_blob); return ret; } diff --git a/thirdparty/harfbuzz/src/hb-style.cc b/thirdparty/harfbuzz/src/hb-style.cc index c0c5c4832c..c7d7d713c2 100644 --- a/thirdparty/harfbuzz/src/hb-style.cc +++ b/thirdparty/harfbuzz/src/hb-style.cc @@ -46,13 +46,13 @@ static inline float _hb_angle_to_ratio (float a) { - return tanf (a * float (M_PI / 180.)); + return tanf (a * float (-M_PI / 180.)); } static inline float _hb_ratio_to_angle (float r) { - return atanf (r) * float (180. / M_PI); + return atanf (r) * float (-180. / M_PI); } /** @@ -72,8 +72,7 @@ float hb_style_get_value (hb_font_t *font, hb_style_tag_t style_tag) { if (unlikely (style_tag == HB_STYLE_TAG_SLANT_RATIO)) - return _hb_angle_to_ratio (hb_style_get_value (font, HB_STYLE_TAG_SLANT_ANGLE)) - + font->slant; + return _hb_angle_to_ratio (hb_style_get_value (font, HB_STYLE_TAG_SLANT_ANGLE)); hb_face_t *face = font->face; diff --git a/thirdparty/harfbuzz/src/hb-style.h b/thirdparty/harfbuzz/src/hb-style.h index 30a6f2b878..d17d2daa5f 100644 --- a/thirdparty/harfbuzz/src/hb-style.h +++ b/thirdparty/harfbuzz/src/hb-style.h @@ -43,8 +43,10 @@ HB_BEGIN_DECLS * @HB_STYLE_TAG_SLANT_ANGLE: Used to vary between upright and slanted text. Values * must be greater than -90 and less than +90. Values can be interpreted as * the angle, in counter-clockwise degrees, of oblique slant from whatever the - * designer considers to be upright for that font design. + * designer considers to be upright for that font design. Typical right-leaning + * Italic fonts have a negative slant angle (typically around -12) * @HB_STYLE_TAG_SLANT_RATIO: same as @HB_STYLE_TAG_SLANT_ANGLE expression as ratio. + * Typical right-leaning Italic fonts have a positive slant ratio (typically around 0.2) * @HB_STYLE_TAG_WIDTH: Used to vary width of text from narrower to wider. * Non-zero. Values can be interpreted as a percentage of whatever the font * designer considers “normal width” for that font design. diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.cc b/thirdparty/harfbuzz/src/hb-subset-plan.cc index af4fcb8137..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 @@ -111,7 +113,7 @@ static void _collect_layout_indices (hb_face_t *face, retain_all_features = false; continue; } - + if (visited_features.has (tag)) continue; @@ -249,9 +251,9 @@ static void _colr_closure (hb_face_t *face, hb_set_t glyphset_colrv0; for (hb_codepoint_t gid : glyphs_colred->iter ()) colr.closure_glyphs (gid, &glyphset_colrv0); - + glyphs_colred->union_ (glyphset_colrv0); - + //closure for COLRv1 colr.closure_forV1 (glyphs_colred, &layer_indices, &palette_indices); } while (iteration_count++ <= HB_CLOSURE_MAX_STAGES && @@ -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, @@ -458,7 +460,7 @@ _nameid_closure (hb_face_t *face, } /** - * hb_subset_plan_create: + * hb_subset_plan_create_or_fail: * @face: font face to create the plan for. * @input: a #hb_subset_input_t input. * @@ -467,17 +469,18 @@ _nameid_closure (hb_face_t *face, * which tables and glyphs should be retained. * * Return value: (transfer full): New subset plan. Destroy with - * hb_subset_plan_destroy(). + * hb_subset_plan_destroy(). If there is a failure creating the plan + * nullptr will be returned. * - * Since: 1.7.5 + * Since: 4.0.0 **/ hb_subset_plan_t * -hb_subset_plan_create (hb_face_t *face, - const hb_subset_input_t *input) +hb_subset_plan_create_or_fail (hb_face_t *face, + const hb_subset_input_t *input) { hb_subset_plan_t *plan; if (unlikely (!(plan = hb_object_create<hb_subset_plan_t> ()))) - return const_cast<hb_subset_plan_t *> (&Null (hb_subset_plan_t)); + return nullptr; plan->successful = true; plan->flags = input->flags; @@ -514,8 +517,9 @@ hb_subset_plan_create (hb_face_t *face, plan->layout_variation_indices = hb_set_create (); plan->layout_variation_idx_map = hb_map_create (); - if (plan->in_error ()) { - return plan; + if (unlikely (plan->in_error ())) { + hb_subset_plan_destroy (plan); + return nullptr; } _populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, plan); @@ -532,6 +536,10 @@ hb_subset_plan_create (hb_face_t *face, plan->reverse_glyph_map, &plan->_num_output_glyphs); + if (unlikely (plan->in_error ())) { + hb_subset_plan_destroy (plan); + return nullptr; + } return plan; } @@ -542,7 +550,7 @@ hb_subset_plan_create (hb_face_t *face, * Decreases the reference count on @plan, and if it reaches zero, destroys * @plan, freeing all memory. * - * Since: 1.7.5 + * Since: 4.0.0 **/ void hb_subset_plan_destroy (hb_subset_plan_t *plan) @@ -596,3 +604,116 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan) hb_free (plan); } + +/** + * hb_subset_plan_old_to_new_glyph_mapping: + * @plan: a subsetting plan. + * + * Returns the mapping between glyphs in the original font to glyphs in the + * subset that will be produced by @plan + * + * Return value: (transfer none): + * A pointer to the #hb_map_t of the mapping. + * + * Since: 4.0.0 + **/ +const hb_map_t* +hb_subset_plan_old_to_new_glyph_mapping (const hb_subset_plan_t *plan) +{ + return plan->glyph_map; +} + +/** + * hb_subset_plan_new_to_old_glyph_mapping: + * @plan: a subsetting plan. + * + * Returns the mapping between glyphs in the subset that will be produced by + * @plan and the glyph in the original font. + * + * Return value: (transfer none): + * A pointer to the #hb_map_t of the mapping. + * + * Since: 4.0.0 + **/ +const hb_map_t* +hb_subset_plan_new_to_old_glyph_mapping (const hb_subset_plan_t *plan) +{ + return plan->reverse_glyph_map; +} + +/** + * hb_subset_plan_unicode_to_old_glyph_mapping: + * @plan: a subsetting plan. + * + * Returns the mapping between codepoints in the original font and the + * associated glyph id in the original font. + * + * Return value: (transfer none): + * A pointer to the #hb_map_t of the mapping. + * + * Since: 4.0.0 + **/ +const hb_map_t* +hb_subset_plan_unicode_to_old_glyph_mapping (const hb_subset_plan_t *plan) +{ + return plan->codepoint_to_glyph; +} + +/** + * hb_subset_plan_reference: (skip) + * @plan: a #hb_subset_plan_t object. + * + * Increases the reference count on @plan. + * + * Return value: @plan. + * + * Since: 4.0.0 + **/ +hb_subset_plan_t * +hb_subset_plan_reference (hb_subset_plan_t *plan) +{ + return hb_object_reference (plan); +} + +/** + * hb_subset_plan_set_user_data: (skip) + * @plan: a #hb_subset_plan_t object. + * @key: The user-data key to set + * @data: A pointer to the user data + * @destroy: (nullable): A callback to call when @data is not needed anymore + * @replace: Whether to replace an existing data with the same key + * + * Attaches a user-data key/data pair to the given subset plan object. + * + * Return value: %true if success, %false otherwise + * + * Since: 4.0.0 + **/ +hb_bool_t +hb_subset_plan_set_user_data (hb_subset_plan_t *plan, + hb_user_data_key_t *key, + void *data, + hb_destroy_func_t destroy, + hb_bool_t replace) +{ + return hb_object_set_user_data (plan, key, data, destroy, replace); +} + +/** + * hb_subset_plan_get_user_data: (skip) + * @plan: a #hb_subset_plan_t object. + * @key: The user-data key to query + * + * Fetches the user data associated with the specified key, + * attached to the specified subset plan object. + * + * Return value: (transfer none): A pointer to the user data + * + * Since: 4.0.0 + **/ +void * +hb_subset_plan_get_user_data (const hb_subset_plan_t *plan, + hb_user_data_key_t *key) +{ + return hb_object_get_user_data (plan, key); +} diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.hh b/thirdparty/harfbuzz/src/hb-subset-plan.hh index b9244e5cb2..ab2c4c302c 100644 --- a/thirdparty/harfbuzz/src/hb-subset-plan.hh +++ b/thirdparty/harfbuzz/src/hb-subset-plan.hh @@ -198,13 +198,4 @@ struct hb_subset_plan_t } }; -typedef struct hb_subset_plan_t hb_subset_plan_t; - -HB_INTERNAL hb_subset_plan_t * -hb_subset_plan_create (hb_face_t *face, - const hb_subset_input_t *input); - -HB_INTERNAL void -hb_subset_plan_destroy (hb_subset_plan_t *plan); - #endif /* HB_SUBSET_PLAN_HH */ diff --git a/thirdparty/harfbuzz/src/hb-subset-repacker.cc b/thirdparty/harfbuzz/src/hb-subset-repacker.cc new file mode 100644 index 0000000000..2447d296b8 --- /dev/null +++ b/thirdparty/harfbuzz/src/hb-subset-repacker.cc @@ -0,0 +1,49 @@ +/* + * Copyright © 2022 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + */ +#include "hb-repacker.hh" + +#ifdef HB_EXPERIMENTAL_API +/** + * hb_subset_repack_or_fail: + * @hb_objects: raw array of struct hb_object_t, which provides + * object graph info + * @num_hb_objs: number of hb_object_t in the hb_objects array. + * + * Given the input object graph info, repack a table to eliminate + * offset overflows. A nullptr is returned if the repacking attempt fails. + * + * Since: EXPERIMENTAL + **/ +hb_blob_t* hb_subset_repack_or_fail (hb_object_t* hb_objects, unsigned num_hb_objs) +{ + hb_vector_t<const hb_object_t *> packed; + packed.alloc (num_hb_objs + 1); + packed.push (nullptr); + for (unsigned i = 0 ; i < num_hb_objs ; i++) + packed.push (&(hb_objects[i])); + return hb_resolve_overflows (packed, HB_OT_TAG_GSUB); +} +#endif + diff --git a/thirdparty/harfbuzz/src/hb-subset-repacker.h b/thirdparty/harfbuzz/src/hb-subset-repacker.h new file mode 100644 index 0000000000..f9a2383698 --- /dev/null +++ b/thirdparty/harfbuzz/src/hb-subset-repacker.h @@ -0,0 +1,80 @@ +/* + * Copyright © 2022 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + */ + +#ifndef HB_SUBSET_REPACKER_H +#define HB_SUBSET_REPACKER_H + +#include "hb.h" + +HB_BEGIN_DECLS + +#ifdef HB_EXPERIMENTAL_API +/** + * struct hb_link_t + * width: offsetSize in bytes + * position: position of the offset field in bytes + * from beginning of subtable + * objidx: index of subtable + **/ +struct hb_link_t +{ + unsigned width; + unsigned position; + unsigned objidx; +}; + +typedef struct hb_link_t hb_link_t; + +/** + * struct hb_object_t + * head: start of object data + * tail: end of object data + * num_real_links: num of offset field in the object + * real_links: pointer to array of offset info + * num_virtual_links: num of objects that must be packed + * after current object in the final serialized order + * virtual_links: array of virtual link info + **/ +struct hb_object_t +{ + char *head; + char *tail; + unsigned num_real_links; + hb_link_t *real_links; + unsigned num_virtual_links; + hb_link_t *virtual_links; +}; + +typedef struct hb_object_t hb_object_t; + +HB_EXTERN hb_blob_t* +hb_subset_repack_or_fail (hb_object_t* hb_objects, + unsigned num_hb_objs); + +#endif + +HB_END_DECLS + +#endif /* HB_SUBSET_REPACKER_H */ diff --git a/thirdparty/harfbuzz/src/hb-subset.cc b/thirdparty/harfbuzz/src/hb-subset.cc index bb46e5b97f..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); @@ -343,9 +345,33 @@ hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input) { if (unlikely (!input || !source)) return hb_face_get_empty (); - hb_subset_plan_t *plan = hb_subset_plan_create (source, input); - if (unlikely (plan->in_error ())) { - hb_subset_plan_destroy (plan); + hb_subset_plan_t *plan = hb_subset_plan_create_or_fail (source, input); + if (unlikely (!plan)) { + return nullptr; + } + + hb_face_t * result = hb_subset_plan_execute_or_fail (plan); + hb_subset_plan_destroy (plan); + return result; +} + + +/** + * hb_subset_plan_execute_or_fail: + * @plan: a subsetting plan. + * + * Executes the provided subsetting @plan. + * + * Return value: + * on success returns a reference to generated font subset. If the subsetting operation fails + * returns nullptr. + * + * Since: 4.0.0 + **/ +hb_face_t * +hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan) +{ + if (unlikely (!plan || plan->in_error ())) { return nullptr; } @@ -353,7 +379,7 @@ hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input) bool success = true; hb_tag_t table_tags[32]; unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags); - while ((hb_face_get_table_tags (source, offset, &num_tables, table_tags), num_tables)) + while ((hb_face_get_table_tags (plan->source, offset, &num_tables, table_tags), num_tables)) { for (unsigned i = 0; i < num_tables; ++i) { @@ -367,8 +393,5 @@ hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input) } end: - hb_face_t *result = success ? hb_face_reference (plan->dest) : nullptr; - - hb_subset_plan_destroy (plan); - return result; + return success ? hb_face_reference (plan->dest) : nullptr; } diff --git a/thirdparty/harfbuzz/src/hb-subset.h b/thirdparty/harfbuzz/src/hb-subset.h index 1c65a4da1c..a2799d91e8 100644 --- a/thirdparty/harfbuzz/src/hb-subset.h +++ b/thirdparty/harfbuzz/src/hb-subset.h @@ -40,6 +40,15 @@ HB_BEGIN_DECLS typedef struct hb_subset_input_t hb_subset_input_t; /** + * hb_subset_plan_t: + * + * Contains information about how the subset operation will be executed. + * Such as mappings from the old glyph ids to the new ones in the subset. + */ + +typedef struct hb_subset_plan_t hb_subset_plan_t; + +/** * hb_subset_flags_t: * @HB_SUBSET_FLAGS_DEFAULT: all flags at their default value of false. * @HB_SUBSET_FLAGS_NO_HINTING: If set hinting instructions will be dropped in @@ -124,7 +133,7 @@ hb_subset_input_set_user_data (hb_subset_input_t *input, HB_EXTERN void * hb_subset_input_get_user_data (const hb_subset_input_t *input, - hb_user_data_key_t *key); + hb_user_data_key_t *key); HB_EXTERN hb_set_t * hb_subset_input_unicode_set (hb_subset_input_t *input); @@ -145,6 +154,41 @@ hb_subset_input_set_flags (hb_subset_input_t *input, HB_EXTERN hb_face_t * hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input); +HB_EXTERN hb_face_t * +hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan); + +HB_EXTERN hb_subset_plan_t * +hb_subset_plan_create_or_fail (hb_face_t *face, + const hb_subset_input_t *input); + +HB_EXTERN void +hb_subset_plan_destroy (hb_subset_plan_t *plan); + +HB_EXTERN const hb_map_t* +hb_subset_plan_old_to_new_glyph_mapping (const hb_subset_plan_t *plan); + +HB_EXTERN const hb_map_t* +hb_subset_plan_new_to_old_glyph_mapping (const hb_subset_plan_t *plan); + +HB_EXTERN const hb_map_t* +hb_subset_plan_unicode_to_old_glyph_mapping (const hb_subset_plan_t *plan); + + +HB_EXTERN hb_subset_plan_t * +hb_subset_plan_reference (hb_subset_plan_t *plan); + +HB_EXTERN hb_bool_t +hb_subset_plan_set_user_data (hb_subset_plan_t *plan, + hb_user_data_key_t *key, + void *data, + hb_destroy_func_t destroy, + hb_bool_t replace); + +HB_EXTERN void * +hb_subset_plan_get_user_data (const hb_subset_plan_t *plan, + hb_user_data_key_t *key); + + HB_END_DECLS #endif /* HB_SUBSET_H */ diff --git a/thirdparty/harfbuzz/src/hb-version.h b/thirdparty/harfbuzz/src/hb-version.h index 493a09f8cf..39fbde45c1 100644 --- a/thirdparty/harfbuzz/src/hb-version.h +++ b/thirdparty/harfbuzz/src/hb-version.h @@ -41,26 +41,26 @@ HB_BEGIN_DECLS * * The major component of the library version available at compile-time. */ -#define HB_VERSION_MAJOR 3 +#define HB_VERSION_MAJOR 4 /** * HB_VERSION_MINOR: * * The minor component of the library version available at compile-time. */ -#define HB_VERSION_MINOR 3 +#define HB_VERSION_MINOR 2 /** * HB_VERSION_MICRO: * * The micro component of the library version available at compile-time. */ -#define HB_VERSION_MICRO 2 +#define HB_VERSION_MICRO 0 /** * HB_VERSION_STRING: * * A string literal containing the library version available at compile-time. */ -#define HB_VERSION_STRING "3.3.2" +#define HB_VERSION_STRING "4.2.0" /** * HB_VERSION_ATLEAST: |