diff options
Diffstat (limited to 'src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh')
-rw-r--r-- | src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh | 1361 |
1 files changed, 775 insertions, 586 deletions
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh index 0b09c4e4a1..fc21cb056e 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh @@ -29,54 +29,49 @@ #ifndef HB_OT_LAYOUT_GSUB_TABLE_HH #define HB_OT_LAYOUT_GSUB_TABLE_HH -#include "hb-ot-layout-gsubgpos-private.hh" +#include "hb-ot-layout-gsubgpos.hh" namespace OT { +typedef hb_pair_t<hb_codepoint_t, hb_codepoint_t> hb_codepoint_pair_t; + +template<typename Iterator> +static inline void SingleSubst_serialize (hb_serialize_context_t *c, + Iterator it); + struct SingleSubstFormat1 { - inline void closure (hb_closure_context_t *c) const + bool intersects (const hb_set_t *glyphs) const + { return (this+coverage).intersects (glyphs); } + + void closure (hb_closure_context_t *c) const { - TRACE_CLOSURE (this); - Coverage::Iter iter; - for (iter.init (this+coverage); iter.more (); iter.next ()) - { - /* TODO Switch to range-based API to work around malicious fonts. - * https://github.com/harfbuzz/harfbuzz/issues/363 */ - hb_codepoint_t glyph_id = iter.get_glyph (); - if (c->glyphs->has (glyph_id)) - c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFFu); - } + unsigned d = deltaGlyphID; + + hb_iter (this+coverage) + | hb_filter (*c->glyphs) + | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; }) + | hb_sink (c->output) + ; } - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + void collect_glyphs (hb_collect_glyphs_context_t *c) const { - TRACE_COLLECT_GLYPHS (this); if (unlikely (!(this+coverage).add_coverage (c->input))) return; - Coverage::Iter iter; - for (iter.init (this+coverage); iter.more (); iter.next ()) - { - /* TODO Switch to range-based API to work around malicious fonts. - * https://github.com/harfbuzz/harfbuzz/issues/363 */ - hb_codepoint_t glyph_id = iter.get_glyph (); - c->output->add ((glyph_id + deltaGlyphID) & 0xFFFFu); - } + unsigned d = deltaGlyphID; + + hb_iter (this+coverage) + | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; }) + | hb_sink (c->output) + ; } - inline const Coverage &get_coverage (void) const - { - return this+coverage; - } + const Coverage &get_coverage () const { return this+coverage; } - inline bool would_apply (hb_would_apply_context_t *c) const - { - TRACE_WOULD_APPLY (this); - return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED); - } + bool would_apply (hb_would_apply_context_t *c) const + { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; } - inline bool apply (hb_apply_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); hb_codepoint_t glyph_id = c->buffer->cur().codepoint; @@ -91,115 +86,153 @@ struct SingleSubstFormat1 return_trace (true); } - inline bool serialize (hb_serialize_context_t *c, - Supplier<GlyphID> &glyphs, - unsigned int num_glyphs, - int delta) + 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 (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false); - deltaGlyphID.set (delta); /* TODO(serilaize) overflow? */ + if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs))) return_trace (false); + c->check_assign (deltaGlyphID, delta); return_trace (true); } - inline bool sanitize (hb_sanitize_context_t *c) const + 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: - UINT16 format; /* Format identifier--format = 1 */ + HBUINT16 format; /* Format identifier--format = 1 */ OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of Substitution table */ - INT16 deltaGlyphID; /* Add to original GlyphID to get - * substitute GlyphID */ + HBUINT16 deltaGlyphID; /* Add to original GlyphID to get + * substitute GlyphID, modulo 0x10000 */ public: DEFINE_SIZE_STATIC (6); }; struct SingleSubstFormat2 { - inline void closure (hb_closure_context_t *c) const + bool intersects (const hb_set_t *glyphs) const + { return (this+coverage).intersects (glyphs); } + + void closure (hb_closure_context_t *c) const { - TRACE_CLOSURE (this); - Coverage::Iter iter; - unsigned int count = substitute.len; - for (iter.init (this+coverage); iter.more (); iter.next ()) - { - if (unlikely (iter.get_coverage () >= count)) - break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ - if (c->glyphs->has (iter.get_glyph ())) - c->glyphs->add (substitute[iter.get_coverage ()]); - } + + hb_zip (this+coverage, substitute) + | hb_filter (*c->glyphs, hb_first) + | hb_map (hb_second) + | hb_sink (c->output) + ; } - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + void collect_glyphs (hb_collect_glyphs_context_t *c) const { - TRACE_COLLECT_GLYPHS (this); if (unlikely (!(this+coverage).add_coverage (c->input))) return; - Coverage::Iter iter; - unsigned int count = substitute.len; - for (iter.init (this+coverage); iter.more (); iter.next ()) - { - if (unlikely (iter.get_coverage () >= count)) - break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ - c->output->add (substitute[iter.get_coverage ()]); - } + + hb_zip (this+coverage, substitute) + | hb_map (hb_second) + | hb_sink (c->output) + ; } - inline const Coverage &get_coverage (void) const - { - return this+coverage; - } + const Coverage &get_coverage () const { return this+coverage; } - inline bool would_apply (hb_would_apply_context_t *c) const - { - TRACE_WOULD_APPLY (this); - return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED); - } + bool would_apply (hb_would_apply_context_t *c) const + { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; } - inline bool apply (hb_apply_context_t *c) const + 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); + 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); - glyph_id = substitute[index]; - c->replace_glyph (glyph_id); + c->replace_glyph (substitute[index]); return_trace (true); } - inline bool serialize (hb_serialize_context_t *c, - Supplier<GlyphID> &glyphs, - Supplier<GlyphID> &substitutes, - unsigned int num_glyphs) + 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, num_glyphs))) return_trace (false); - if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false); + if (unlikely (!substitute.serialize (c, substitutes))) return_trace (false); + if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs))) return_trace (false); return_trace (true); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); + const hb_map_t &glyph_map = *c->plan->glyph_map; + + auto it = + + hb_zip (this+coverage, substitute) + | hb_filter (glyphset, hb_first) + | hb_filter (glyphset, hb_second) + | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID &> p) -> hb_codepoint_pair_t + { return hb_pair (glyph_map[p.first], glyph_map[p.second]); }) + ; + + bool ret = bool (it); + SingleSubst_serialize (c->serializer, it); + return_trace (ret); + } + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (coverage.sanitize (c, this) && substitute.sanitize (c)); } protected: - UINT16 format; /* Format identifier--format = 2 */ + HBUINT16 format; /* Format identifier--format = 2 */ OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of Substitution table */ - ArrayOf<GlyphID> + ArrayOf<HBGlyphID> substitute; /* Array of substitute * GlyphIDs--ordered by Coverage Index */ public: @@ -208,71 +241,75 @@ struct SingleSubstFormat2 struct SingleSubst { - inline bool serialize (hb_serialize_context_t *c, - Supplier<GlyphID> &glyphs, - Supplier<GlyphID> &substitutes, - unsigned int num_glyphs) + + 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 int format = 2; - int delta = 0; - if (num_glyphs) { + unsigned format = 2; + unsigned delta = 0; + if (glyphs) + { format = 1; - /* TODO(serialize) check for wrap-around */ - delta = substitutes[0] - glyphs[0]; - for (unsigned int i = 1; i < num_glyphs; i++) - if (delta != substitutes[i] - glyphs[i]) { - format = 2; - break; - } + 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.set (format); + u.format = format; switch (u.format) { - case 1: return_trace (u.format1.serialize (c, glyphs, num_glyphs, delta)); - case 2: return_trace (u.format2.serialize (c, glyphs, substitutes, num_glyphs)); + 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> - inline typename context_t::return_t dispatch (context_t *c) const + 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)); - case 2: return_trace (c->dispatch (u.format2)); + case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...)); + case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...)); default:return_trace (c->default_return_value ()); } } protected: union { - UINT16 format; /* Format identifier */ + HBUINT16 format; /* Format identifier */ SingleSubstFormat1 format1; SingleSubstFormat2 format2; } u; }; +template<typename Iterator> +static inline void +SingleSubst_serialize (hb_serialize_context_t *c, + Iterator it) +{ c->start_embed<SingleSubst> ()->serialize (c, it); } struct Sequence { - inline void closure (hb_closure_context_t *c) const - { - TRACE_CLOSURE (this); - unsigned int count = substitute.len; - for (unsigned int i = 0; i < count; i++) - c->glyphs->add (substitute[i]); - } + bool intersects (const hb_set_t *glyphs) const + { return hb_all (substitute, glyphs); } - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const - { - TRACE_COLLECT_GLYPHS (this); - c->output->add_array (substitute.array, substitute.len); - } + void closure (hb_closure_context_t *c) const + { c->output->add_array (substitute.arrayZ, substitute.len); } - inline bool apply (hb_apply_context_t *c) const + 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; @@ -281,7 +318,7 @@ struct Sequence * as a "multiplied" substitution. */ if (unlikely (count == 1)) { - c->replace_glyph (substitute.array[0]); + c->replace_glyph (substitute.arrayZ[0]); return_trace (true); } /* Spec disallows this, but Uniscribe allows it. @@ -297,31 +334,47 @@ struct Sequence for (unsigned int i = 0; i < count; i++) { _hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i); - c->output_glyph_for_component (substitute.array[i], klass); + c->output_glyph_for_component (substitute.arrayZ[i], klass); } c->buffer->skip_glyph (); return_trace (true); } - inline bool serialize (hb_serialize_context_t *c, - Supplier<GlyphID> &glyphs, - unsigned int num_glyphs) + 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); - if (unlikely (!c->extend_min (*this))) return_trace (false); - if (unlikely (!substitute.serialize (c, glyphs, num_glyphs))) return_trace (false); - return_trace (true); + return_trace (substitute.serialize (c, subst)); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + const hb_set_t &glyphset = *c->plan->glyphset (); + 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: - ArrayOf<GlyphID> + ArrayOf<HBGlyphID> substitute; /* String of GlyphIDs to substitute */ public: DEFINE_SIZE_ARRAY (2, substitute); @@ -329,41 +382,35 @@ struct Sequence struct MultipleSubstFormat1 { - inline void closure (hb_closure_context_t *c) const + bool intersects (const hb_set_t *glyphs) const + { return (this+coverage).intersects (glyphs); } + + void closure (hb_closure_context_t *c) const { - TRACE_CLOSURE (this); - Coverage::Iter iter; - unsigned int count = sequence.len; - for (iter.init (this+coverage); iter.more (); iter.next ()) - { - if (unlikely (iter.get_coverage () >= count)) - break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ - if (c->glyphs->has (iter.get_glyph ())) - (this+sequence[iter.get_coverage ()]).closure (c); - } + + hb_zip (this+coverage, sequence) + | hb_filter (*c->glyphs, hb_first) + | hb_map (hb_second) + | hb_map (hb_add (this)) + | hb_apply ([c] (const Sequence &_) { _.closure (c); }) + ; } - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + void collect_glyphs (hb_collect_glyphs_context_t *c) const { - TRACE_COLLECT_GLYPHS (this); if (unlikely (!(this+coverage).add_coverage (c->input))) return; - unsigned int count = sequence.len; - for (unsigned int i = 0; i < count; i++) - (this+sequence[i]).collect_glyphs (c); + + hb_zip (this+coverage, sequence) + | hb_map (hb_second) + | hb_map (hb_add (this)) + | hb_apply ([c] (const Sequence &_) { _.collect_glyphs (c); }) + ; } - inline const Coverage &get_coverage (void) const - { - return this+coverage; - } + const Coverage &get_coverage () const { return this+coverage; } - inline bool would_apply (hb_would_apply_context_t *c) const - { - TRACE_WOULD_APPLY (this); - return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED); - } + bool would_apply (hb_would_apply_context_t *c) const + { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; } - inline bool apply (hb_apply_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); @@ -373,32 +420,56 @@ struct MultipleSubstFormat1 return_trace ((this+sequence[index]).apply (c)); } - inline bool serialize (hb_serialize_context_t *c, - Supplier<GlyphID> &glyphs, - Supplier<unsigned int> &substitute_len_list, - unsigned int num_glyphs, - Supplier<GlyphID> &substitute_glyphs_list) + bool serialize (hb_serialize_context_t *c, + hb_sorted_array_t<const HBGlyphID> glyphs, + hb_array_t<const unsigned int> substitute_len_list, + hb_array_t<const HBGlyphID> substitute_glyphs_list) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (*this))) return_trace (false); - if (unlikely (!sequence.serialize (c, num_glyphs))) return_trace (false); - for (unsigned int i = 0; i < num_glyphs; i++) - if (unlikely (!sequence[i].serialize (c, this).serialize (c, - substitute_glyphs_list, - substitute_len_list[i]))) return_trace (false); - substitute_len_list.advance (num_glyphs); - if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false); - return_trace (true); + 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 (c, this) + .serialize (c, substitute_glyphs_list.sub_array (0, substitute_len)))) + return_trace (false); + substitute_glyphs_list += substitute_len; + } + return_trace (coverage.serialize (c, this).serialize (c, glyphs)); + } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + const hb_set_t &glyphset = *c->plan->glyphset (); + 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, out), hb_second) + | hb_map (hb_first) + | hb_map (glyph_map) + | hb_sink (new_coverage) + ; + out->coverage.serialize (c->serializer, out) + .serialize (c->serializer, new_coverage.iter ()); + return_trace (bool (new_coverage)); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (coverage.sanitize (c, this) && sequence.sanitize (c, this)); } protected: - UINT16 format; /* Format identifier--format = 1 */ + HBUINT16 format; /* Format identifier--format = 1 */ OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of Substitution table */ @@ -411,144 +482,204 @@ struct MultipleSubstFormat1 struct MultipleSubst { - inline bool serialize (hb_serialize_context_t *c, - Supplier<GlyphID> &glyphs, - Supplier<unsigned int> &substitute_len_list, - unsigned int num_glyphs, - Supplier<GlyphID> &substitute_glyphs_list) + bool serialize (hb_serialize_context_t *c, + hb_sorted_array_t<const HBGlyphID> glyphs, + hb_array_t<const unsigned int> substitute_len_list, + hb_array_t<const HBGlyphID> substitute_glyphs_list) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (u.format))) return_trace (false); unsigned int format = 1; - u.format.set (format); + u.format = format; switch (u.format) { - case 1: return_trace (u.format1.serialize (c, glyphs, substitute_len_list, num_glyphs, substitute_glyphs_list)); + case 1: return_trace (u.format1.serialize (c, glyphs, substitute_len_list, substitute_glyphs_list)); default:return_trace (false); } } - template <typename context_t> - inline typename context_t::return_t dispatch (context_t *c) const + 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)); + case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...)); default:return_trace (c->default_return_value ()); } } protected: union { - UINT16 format; /* Format identifier */ + HBUINT16 format; /* Format identifier */ MultipleSubstFormat1 format1; } u; }; +struct AlternateSet +{ + bool intersects (const hb_set_t *glyphs) const + { return hb_any (alternates, glyphs); } -typedef ArrayOf<GlyphID> AlternateSet; /* Array of alternate GlyphIDs--in - * arbitrary order */ + void closure (hb_closure_context_t *c) const + { c->output->add_array (alternates.arrayZ, alternates.len); } -struct AlternateSubstFormat1 -{ - inline void closure (hb_closure_context_t *c) const - { - TRACE_CLOSURE (this); - Coverage::Iter iter; - unsigned int count = alternateSet.len; - for (iter.init (this+coverage); iter.more (); iter.next ()) - { - if (unlikely (iter.get_coverage () >= count)) - break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ - if (c->glyphs->has (iter.get_glyph ())) { - const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()]; - unsigned int count = alt_set.len; - for (unsigned int i = 0; i < count; i++) - c->glyphs->add (alt_set[i]); - } - } - } + void collect_glyphs (hb_collect_glyphs_context_t *c) const + { c->output->add_array (alternates.arrayZ, alternates.len); } - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { - TRACE_COLLECT_GLYPHS (this); - if (unlikely (!(this+coverage).add_coverage (c->input))) return; - Coverage::Iter iter; - unsigned int count = alternateSet.len; - for (iter.init (this+coverage); iter.more (); iter.next ()) - { - if (unlikely (iter.get_coverage () >= count)) - break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ - const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()]; - c->output->add_array (alt_set.array, alt_set.len); - } + 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) + 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); } - inline const Coverage &get_coverage (void) const + template <typename Iterator, + hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))> + bool serialize (hb_serialize_context_t *c, + Iterator alts) { - return this+coverage; + TRACE_SERIALIZE (this); + return_trace (alternates.serialize (c, alts)); } - inline bool would_apply (hb_would_apply_context_t *c) const + bool subset (hb_subset_context_t *c) const { - TRACE_WOULD_APPLY (this); - return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED); + TRACE_SUBSET (this); + const hb_set_t &glyphset = *c->plan->glyphset (); + 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); } - inline bool apply (hb_apply_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { - TRACE_APPLY (this); - hb_codepoint_t glyph_id = c->buffer->cur().codepoint; + TRACE_SANITIZE (this); + return_trace (alternates.sanitize (c)); + } - unsigned int index = (this+coverage).get_coverage (glyph_id); - if (likely (index == NOT_COVERED)) return_trace (false); + protected: + ArrayOf<HBGlyphID> + alternates; /* Array of alternate GlyphIDs--in + * arbitrary order */ + public: + DEFINE_SIZE_ARRAY (2, alternates); +}; - const AlternateSet &alt_set = this+alternateSet[index]; +struct AlternateSubstFormat1 +{ + bool intersects (const hb_set_t *glyphs) const + { return (this+coverage).intersects (glyphs); } - if (unlikely (!alt_set.len)) return_trace (false); + void closure (hb_closure_context_t *c) const + { + + hb_zip (this+coverage, alternateSet) + | hb_map (hb_second) + | hb_map (hb_add (this)) + | hb_apply ([c] (const AlternateSet &_) { _.closure (c); }) + ; + } - hb_mask_t glyph_mask = c->buffer->cur().mask; - hb_mask_t lookup_mask = c->lookup_mask; + void collect_glyphs (hb_collect_glyphs_context_t *c) const + { + if (unlikely (!(this+coverage).add_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); }) + ; + } - /* 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); + const Coverage &get_coverage () const { return this+coverage; } - if (unlikely (alt_index > alt_set.len || alt_index == 0)) return_trace (false); + bool would_apply (hb_would_apply_context_t *c) const + { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; } - glyph_id = alt_set[alt_index - 1]; + bool apply (hb_ot_apply_context_t *c) const + { + TRACE_APPLY (this); - c->replace_glyph (glyph_id); + unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); + if (likely (index == NOT_COVERED)) return_trace (false); - return_trace (true); + return_trace ((this+alternateSet[index]).apply (c)); } - inline bool serialize (hb_serialize_context_t *c, - Supplier<GlyphID> &glyphs, - Supplier<unsigned int> &alternate_len_list, - unsigned int num_glyphs, - Supplier<GlyphID> &alternate_glyphs_list) + bool serialize (hb_serialize_context_t *c, + hb_sorted_array_t<const HBGlyphID> glyphs, + hb_array_t<const unsigned int> alternate_len_list, + hb_array_t<const HBGlyphID> alternate_glyphs_list) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (*this))) return_trace (false); - if (unlikely (!alternateSet.serialize (c, num_glyphs))) return_trace (false); - for (unsigned int i = 0; i < num_glyphs; i++) - if (unlikely (!alternateSet[i].serialize (c, this).serialize (c, - alternate_glyphs_list, - alternate_len_list[i]))) return_trace (false); - alternate_len_list.advance (num_glyphs); - if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false); - return_trace (true); + 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 (c, this) + .serialize (c, alternate_glyphs_list.sub_array (0, alternate_len)))) + return_trace (false); + alternate_glyphs_list += alternate_len; + } + return_trace (coverage.serialize (c, this).serialize (c, glyphs)); + } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + const hb_set_t &glyphset = *c->plan->glyphset (); + 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, out), hb_second) + | hb_map (hb_first) + | hb_map (glyph_map) + | hb_sink (new_coverage) + ; + out->coverage.serialize (c->serializer, out) + .serialize (c->serializer, new_coverage.iter ()); + return_trace (bool (new_coverage)); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (coverage.sanitize (c, this) && alternateSet.sanitize (c, this)); } protected: - UINT16 format; /* Format identifier--format = 1 */ + HBUINT16 format; /* Format identifier--format = 1 */ OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of Substitution table */ @@ -561,36 +692,35 @@ struct AlternateSubstFormat1 struct AlternateSubst { - inline bool serialize (hb_serialize_context_t *c, - Supplier<GlyphID> &glyphs, - Supplier<unsigned int> &alternate_len_list, - unsigned int num_glyphs, - Supplier<GlyphID> &alternate_glyphs_list) + bool serialize (hb_serialize_context_t *c, + hb_sorted_array_t<const HBGlyphID> glyphs, + hb_array_t<const unsigned int> alternate_len_list, + hb_array_t<const HBGlyphID> alternate_glyphs_list) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (u.format))) return_trace (false); unsigned int format = 1; - u.format.set (format); + u.format = format; switch (u.format) { - case 1: return_trace (u.format1.serialize (c, glyphs, alternate_len_list, num_glyphs, alternate_glyphs_list)); + case 1: return_trace (u.format1.serialize (c, glyphs, alternate_len_list, alternate_glyphs_list)); default:return_trace (false); } } - template <typename context_t> - inline typename context_t::return_t dispatch (context_t *c) const + 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)); + case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...)); default:return_trace (c->default_return_value ()); } } protected: union { - UINT16 format; /* Format identifier */ + HBUINT16 format; /* Format identifier */ AlternateSubstFormat1 format1; } u; }; @@ -598,40 +728,37 @@ struct AlternateSubst struct Ligature { - inline void closure (hb_closure_context_t *c) const + bool intersects (const hb_set_t *glyphs) const + { return hb_all (component, glyphs); } + + void closure (hb_closure_context_t *c) const { - TRACE_CLOSURE (this); - unsigned int count = component.len; - for (unsigned int i = 1; i < count; i++) - if (!c->glyphs->has (component[i])) - return; - c->glyphs->add (ligGlyph); + if (!intersects (c->glyphs)) return; + c->output->add (ligGlyph); } - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + void collect_glyphs (hb_collect_glyphs_context_t *c) const { - TRACE_COLLECT_GLYPHS (this); - c->input->add_array (component.array, component.len ? component.len - 1 : 0); + c->input->add_array (component.arrayZ, component.get_length ()); c->output->add (ligGlyph); } - inline bool would_apply (hb_would_apply_context_t *c) const + bool would_apply (hb_would_apply_context_t *c) const { - TRACE_WOULD_APPLY (this); - if (c->len != component.len) - return_trace (false); + if (c->len != component.lenP1) + return false; for (unsigned int i = 1; i < c->len; i++) if (likely (c->glyphs[i] != component[i])) - return_trace (false); + return false; - return_trace (true); + return true; } - inline bool apply (hb_apply_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); - unsigned int count = component.len; + unsigned int count = component.lenP1; if (unlikely (!count)) return_trace (false); @@ -643,7 +770,6 @@ struct Ligature return_trace (true); } - bool is_mark_ligature = false; unsigned int total_component_count = 0; unsigned int match_length = 0; @@ -655,7 +781,6 @@ struct Ligature nullptr, &match_length, match_positions, - &is_mark_ligature, &total_component_count))) return_trace (false); @@ -664,34 +789,53 @@ struct Ligature match_positions, match_length, ligGlyph, - is_mark_ligature, total_component_count); return_trace (true); } - inline bool serialize (hb_serialize_context_t *c, - GlyphID ligature, - Supplier<GlyphID> &components, /* Starting from second */ - unsigned int num_components /* Including first component */) + 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, num_components))) return_trace (false); + if (unlikely (!component.serialize (c, components))) return_trace (false); return_trace (true); } + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_map_t &glyph_map = *c->plan->glyph_map; + + if (!intersects (&glyphset) || !glyphset.has (ligGlyph)) return_trace (false); + + auto it = + + hb_iter (component) + | hb_map (glyph_map) + ; + + auto *out = c->serializer->start_embed (*this); + return_trace (out->serialize (c->serializer, + glyph_map[ligGlyph], + it)); + } + public: - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (ligGlyph.sanitize (c) && component.sanitize (c)); } protected: - GlyphID ligGlyph; /* GlyphID of ligature to substitute */ - HeadlessArrayOf<GlyphID> + HBGlyphID ligGlyph; /* GlyphID of ligature to substitute */ + HeadlessArrayOf<HBGlyphID> component; /* Array of component GlyphIDs--start * with the second component--ordered * in writing direction */ @@ -701,36 +845,43 @@ struct Ligature struct LigatureSet { - inline void closure (hb_closure_context_t *c) const + bool intersects (const hb_set_t *glyphs) const { - TRACE_CLOSURE (this); - unsigned int num_ligs = ligature.len; - for (unsigned int i = 0; i < num_ligs; i++) - (this+ligature[i]).closure (c); + return + + hb_iter (ligature) + | hb_map (hb_add (this)) + | hb_map ([glyphs] (const Ligature &_) { return _.intersects (glyphs); }) + | hb_any + ; } - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + void closure (hb_closure_context_t *c) const { - TRACE_COLLECT_GLYPHS (this); - unsigned int num_ligs = ligature.len; - for (unsigned int i = 0; i < num_ligs; i++) - (this+ligature[i]).collect_glyphs (c); + + hb_iter (ligature) + | hb_map (hb_add (this)) + | hb_apply ([c] (const Ligature &_) { _.closure (c); }) + ; } - inline bool would_apply (hb_would_apply_context_t *c) const + void collect_glyphs (hb_collect_glyphs_context_t *c) const { - TRACE_WOULD_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.would_apply (c)) - return_trace (true); - } - return_trace (false); + + hb_iter (ligature) + | hb_map (hb_add (this)) + | hb_apply ([c] (const Ligature &_) { _.collect_glyphs (c); }) + ; } - inline bool apply (hb_apply_context_t *c) const + 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; @@ -743,26 +894,41 @@ struct LigatureSet return_trace (false); } - inline bool serialize (hb_serialize_context_t *c, - Supplier<GlyphID> &ligatures, - Supplier<unsigned int> &component_count_list, - unsigned int num_ligatures, - Supplier<GlyphID> &component_list /* Starting from second for each ligature */) + bool serialize (hb_serialize_context_t *c, + hb_array_t<const HBGlyphID> ligatures, + hb_array_t<const unsigned int> component_count_list, + hb_array_t<const HBGlyphID> &component_list /* Starting from second for each ligature */) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (*this))) return_trace (false); - if (unlikely (!ligature.serialize (c, num_ligatures))) return_trace (false); - for (unsigned int i = 0; i < num_ligatures; i++) - if (unlikely (!ligature[i].serialize (c, this).serialize (c, - ligatures[i], - component_list, - component_count_list[i]))) return_trace (false); - ligatures.advance (num_ligatures); - component_count_list.advance (num_ligatures); + 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 (c, this) + .serialize (c, + ligatures[i], + component_list.sub_array (0, component_count)))) + return_trace (false); + component_list += component_count; + } return_trace (true); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->start_embed (*this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + + + hb_iter (ligature) + | hb_filter (subset_offset_array (c, out->ligature, this, out)) + | hb_drain + ; + return_trace (bool (out->ligature)); + } + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (ligature.sanitize (c, this)); @@ -778,91 +944,116 @@ struct LigatureSet struct LigatureSubstFormat1 { - inline void closure (hb_closure_context_t *c) const + bool intersects (const hb_set_t *glyphs) const { - TRACE_CLOSURE (this); - Coverage::Iter iter; - unsigned int count = ligatureSet.len; - for (iter.init (this+coverage); iter.more (); iter.next ()) - { - if (unlikely (iter.get_coverage () >= count)) - break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ - if (c->glyphs->has (iter.get_glyph ())) - (this+ligatureSet[iter.get_coverage ()]).closure (c); - } + return + + hb_zip (this+coverage, ligatureSet) + | hb_filter (*glyphs, hb_first) + | hb_map (hb_second) + | hb_map ([this, glyphs] (const OffsetTo<LigatureSet> &_) + { return (this+_).intersects (glyphs); }) + | hb_any + ; } - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + void closure (hb_closure_context_t *c) const { - TRACE_COLLECT_GLYPHS (this); - if (unlikely (!(this+coverage).add_coverage (c->input))) return; - Coverage::Iter iter; - unsigned int count = ligatureSet.len; - for (iter.init (this+coverage); iter.more (); iter.next ()) - { - if (unlikely (iter.get_coverage () >= count)) - break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ - (this+ligatureSet[iter.get_coverage ()]).collect_glyphs (c); - } + + hb_zip (this+coverage, ligatureSet) + | hb_filter (*c->glyphs, hb_first) + | hb_map (hb_second) + | hb_map (hb_add (this)) + | hb_apply ([c] (const LigatureSet &_) { _.closure (c); }) + ; } - inline const Coverage &get_coverage (void) const + void collect_glyphs (hb_collect_glyphs_context_t *c) const { - return this+coverage; + if (unlikely (!(this+coverage).add_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); }) + ; } - inline bool would_apply (hb_would_apply_context_t *c) const + const Coverage &get_coverage () const { return this+coverage; } + + bool would_apply (hb_would_apply_context_t *c) const { - TRACE_WOULD_APPLY (this); unsigned int index = (this+coverage).get_coverage (c->glyphs[0]); - if (likely (index == NOT_COVERED)) return_trace (false); + if (likely (index == NOT_COVERED)) return false; const LigatureSet &lig_set = this+ligatureSet[index]; - return_trace (lig_set.would_apply (c)); + return lig_set.would_apply (c); } - inline bool apply (hb_apply_context_t *c) const + 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); + 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)); } - inline bool serialize (hb_serialize_context_t *c, - Supplier<GlyphID> &first_glyphs, - Supplier<unsigned int> &ligature_per_first_glyph_count_list, - unsigned int num_first_glyphs, - Supplier<GlyphID> &ligatures_list, - Supplier<unsigned int> &component_count_list, - Supplier<GlyphID> &component_list /* Starting from second for each ligature */) + bool serialize (hb_serialize_context_t *c, + hb_sorted_array_t<const HBGlyphID> first_glyphs, + hb_array_t<const unsigned int> ligature_per_first_glyph_count_list, + hb_array_t<const HBGlyphID> ligatures_list, + hb_array_t<const unsigned int> component_count_list, + hb_array_t<const HBGlyphID> component_list /* Starting from second for each ligature */) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (*this))) return_trace (false); - if (unlikely (!ligatureSet.serialize (c, num_first_glyphs))) return_trace (false); - for (unsigned int i = 0; i < num_first_glyphs; i++) - if (unlikely (!ligatureSet[i].serialize (c, this).serialize (c, - ligatures_list, - component_count_list, - ligature_per_first_glyph_count_list[i], - component_list))) return_trace (false); - ligature_per_first_glyph_count_list.advance (num_first_glyphs); - if (unlikely (!coverage.serialize (c, this).serialize (c, first_glyphs, num_first_glyphs))) return_trace (false); - return_trace (true); + 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 (c, this) + .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 (c, this).serialize (c, first_glyphs)); + } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_map_t &glyph_map = *c->plan->glyph_map; + + auto *out = c->serializer->start_embed (*this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + out->format = format; + + hb_sorted_vector_t<hb_codepoint_t> new_coverage; + + hb_zip (this+coverage, ligatureSet) + | hb_filter (glyphset, hb_first) + | hb_filter (subset_offset_array (c, out->ligatureSet, this, out), hb_second) + | hb_map (hb_first) + | hb_map (glyph_map) + | hb_sink (new_coverage) + ; + out->coverage.serialize (c->serializer, out) + .serialize (c->serializer, new_coverage.iter ()); + return_trace (bool (new_coverage)); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this)); } protected: - UINT16 format; /* Format identifier--format = 1 */ + HBUINT16 format; /* Format identifier--format = 1 */ OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of Substitution table */ @@ -875,23 +1066,21 @@ struct LigatureSubstFormat1 struct LigatureSubst { - inline bool serialize (hb_serialize_context_t *c, - Supplier<GlyphID> &first_glyphs, - Supplier<unsigned int> &ligature_per_first_glyph_count_list, - unsigned int num_first_glyphs, - Supplier<GlyphID> &ligatures_list, - Supplier<unsigned int> &component_count_list, - Supplier<GlyphID> &component_list /* Starting from second for each ligature */) + bool serialize (hb_serialize_context_t *c, + hb_sorted_array_t<const HBGlyphID> first_glyphs, + hb_array_t<const unsigned int> ligature_per_first_glyph_count_list, + hb_array_t<const HBGlyphID> ligatures_list, + hb_array_t<const unsigned int> component_count_list, + hb_array_t<const HBGlyphID> component_list /* Starting from second for each ligature */) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (u.format))) return_trace (false); unsigned int format = 1; - u.format.set (format); + u.format = format; switch (u.format) { case 1: return_trace (u.format1.serialize (c, first_glyphs, ligature_per_first_glyph_count_list, - num_first_glyphs, ligatures_list, component_count_list, component_list)); @@ -899,20 +1088,20 @@ struct LigatureSubst } } - template <typename context_t> - inline typename context_t::return_t dispatch (context_t *c) const + 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)); + case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...)); default:return_trace (c->default_return_value ()); } } protected: union { - UINT16 format; /* Format identifier */ + HBUINT16 format; /* Format identifier */ LigatureSubstFormat1 format1; } u; }; @@ -924,46 +1113,52 @@ struct ChainContextSubst : ChainContext {}; struct ExtensionSubst : Extension<ExtensionSubst> { - typedef struct SubstLookupSubTable LookupSubTable; + typedef struct SubstLookupSubTable SubTable; - inline bool is_reverse (void) const; + bool is_reverse () const; }; struct ReverseChainSingleSubstFormat1 { - inline void closure (hb_closure_context_t *c) const + bool intersects (const hb_set_t *glyphs) const { - TRACE_CLOSURE (this); - const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack); + if (!(this+coverage).intersects (glyphs)) + return false; + + const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack); unsigned int count; count = backtrack.len; for (unsigned int i = 0; i < count; i++) - if (!(this+backtrack[i]).intersects (c->glyphs)) - return; + if (!(this+backtrack[i]).intersects (glyphs)) + return false; count = lookahead.len; for (unsigned int i = 0; i < count; i++) - if (!(this+lookahead[i]).intersects (c->glyphs)) - return; + if (!(this+lookahead[i]).intersects (glyphs)) + return false; - const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead); - Coverage::Iter iter; - count = substitute.len; - for (iter.init (this+coverage); iter.more (); iter.next ()) - { - if (unlikely (iter.get_coverage () >= count)) - break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ - if (c->glyphs->has (iter.get_glyph ())) - c->glyphs->add (substitute[iter.get_coverage ()]); - } + return true; + } + + void closure (hb_closure_context_t *c) const + { + if (!intersects (c->glyphs)) return; + + const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack); + const ArrayOf<HBGlyphID> &substitute = StructAfter<ArrayOf<HBGlyphID>> (lookahead); + + + hb_zip (this+coverage, substitute) + | hb_filter (*c->glyphs, hb_first) + | hb_map (hb_second) + | hb_sink (c->output) + ; } - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const + void collect_glyphs (hb_collect_glyphs_context_t *c) const { - TRACE_COLLECT_GLYPHS (this); if (unlikely (!(this+coverage).add_coverage (c->input))) return; unsigned int count; @@ -972,28 +1167,22 @@ struct ReverseChainSingleSubstFormat1 for (unsigned int i = 0; i < count; i++) if (unlikely (!(this+backtrack[i]).add_coverage (c->before))) return; - const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack); + const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack); count = lookahead.len; for (unsigned int i = 0; i < count; i++) if (unlikely (!(this+lookahead[i]).add_coverage (c->after))) return; - const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead); + const ArrayOf<HBGlyphID> &substitute = StructAfter<ArrayOf<HBGlyphID>> (lookahead); count = substitute.len; - c->output->add_array (substitute.array, substitute.len); + c->output->add_array (substitute.arrayZ, substitute.len); } - inline const Coverage &get_coverage (void) const - { - return this+coverage; - } + const Coverage &get_coverage () const { return this+coverage; } - inline bool would_apply (hb_would_apply_context_t *c) const - { - TRACE_WOULD_APPLY (this); - return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED); - } + bool would_apply (hb_would_apply_context_t *c) const + { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; } - inline bool apply (hb_apply_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); if (unlikely (c->nesting_level_left != HB_MAX_NESTING_LEVEL)) @@ -1002,16 +1191,16 @@ struct ReverseChainSingleSubstFormat1 unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); if (likely (index == NOT_COVERED)) return_trace (false); - const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack); - const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead); + const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack); + const ArrayOf<HBGlyphID> &substitute = StructAfter<ArrayOf<HBGlyphID>> (lookahead); unsigned int start_index = 0, end_index = 0; if (match_backtrack (c, - backtrack.len, (UINT16 *) backtrack.array, + backtrack.len, (HBUINT16 *) backtrack.arrayZ, match_coverage, this, &start_index) && - match_lookahead (c, - lookahead.len, (UINT16 *) lookahead.array, + match_lookahead (c, + lookahead.len, (HBUINT16 *) lookahead.arrayZ, match_coverage, this, 1, &end_index)) { @@ -1026,32 +1215,39 @@ struct ReverseChainSingleSubstFormat1 return_trace (false); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + // TODO(subset) + return_trace (false); + } + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this))) return_trace (false); - const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack); + const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack); if (!lookahead.sanitize (c, this)) return_trace (false); - const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead); + const ArrayOf<HBGlyphID> &substitute = StructAfter<ArrayOf<HBGlyphID>> (lookahead); return_trace (substitute.sanitize (c)); } protected: - UINT16 format; /* Format identifier--format = 1 */ + HBUINT16 format; /* Format identifier--format = 1 */ OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of table */ OffsetArrayOf<Coverage> backtrack; /* Array of coverage tables - * in backtracking sequence, in glyph + * in backtracking sequence, in glyph * sequence order */ OffsetArrayOf<Coverage> lookaheadX; /* Array of coverage tables * in lookahead sequence, in glyph * sequence order */ - ArrayOf<GlyphID> + ArrayOf<HBGlyphID> substituteX; /* Array of substitute * GlyphIDs--ordered by Coverage Index */ public: @@ -1060,20 +1256,20 @@ struct ReverseChainSingleSubstFormat1 struct ReverseChainSingleSubst { - template <typename context_t> - inline typename context_t::return_t dispatch (context_t *c) const + 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)); + case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...)); default:return_trace (c->default_return_value ()); } } protected: union { - UINT16 format; /* Format identifier */ + HBUINT16 format; /* Format identifier */ ReverseChainSingleSubstFormat1 format1; } u; }; @@ -1086,6 +1282,7 @@ struct ReverseChainSingleSubst struct SubstLookupSubTable { + friend struct Lookup; friend struct SubstLookup; enum Type { @@ -1099,27 +1296,25 @@ struct SubstLookupSubTable ReverseChainSingle = 8 }; - template <typename context_t> - inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const + 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); - if (unlikely (!c->may_dispatch (this, &u.sub_format))) return_trace (c->no_dispatch_return_value ()); switch (lookup_type) { - case Single: return_trace (u.single.dispatch (c)); - case Multiple: return_trace (u.multiple.dispatch (c)); - case Alternate: return_trace (u.alternate.dispatch (c)); - case Ligature: return_trace (u.ligature.dispatch (c)); - case Context: return_trace (u.context.dispatch (c)); - case ChainContext: return_trace (u.chainContext.dispatch (c)); - case Extension: return_trace (u.extension.dispatch (c)); - case ReverseChainSingle: return_trace (u.reverseChainContextSingle.dispatch (c)); + case Single: return_trace (u.single.dispatch (c, hb_forward<Ts> (ds)...)); + case Multiple: return_trace (u.multiple.dispatch (c, hb_forward<Ts> (ds)...)); + case Alternate: return_trace (u.alternate.dispatch (c, hb_forward<Ts> (ds)...)); + case Ligature: return_trace (u.ligature.dispatch (c, hb_forward<Ts> (ds)...)); + case Context: return_trace (u.context.dispatch (c, hb_forward<Ts> (ds)...)); + case ChainContext: return_trace (u.chainContext.dispatch (c, hb_forward<Ts> (ds)...)); + case Extension: return_trace (u.extension.dispatch (c, hb_forward<Ts> (ds)...)); + case ReverseChainSingle: return_trace (u.reverseChainContextSingle.dispatch (c, hb_forward<Ts> (ds)...)); default: return_trace (c->default_return_value ()); } } protected: union { - UINT16 sub_format; SingleSubst single; MultipleSubst multiple; AlternateSubst alternate; @@ -1130,224 +1325,217 @@ struct SubstLookupSubTable ReverseChainSingleSubst reverseChainContextSingle; } u; public: - DEFINE_SIZE_UNION (2, sub_format); + DEFINE_SIZE_MIN (0); }; struct SubstLookup : Lookup { - inline const SubstLookupSubTable& get_subtable (unsigned int i) const - { return Lookup::get_subtable<SubstLookupSubTable> (i); } + typedef SubstLookupSubTable SubTable; - inline static bool lookup_type_is_reverse (unsigned int lookup_type) - { return lookup_type == SubstLookupSubTable::ReverseChainSingle; } + const SubTable& get_subtable (unsigned int i) const + { return Lookup::get_subtable<SubTable> (i); } - inline bool is_reverse (void) const + HB_INTERNAL static 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 == SubstLookupSubTable::Extension)) + if (unlikely (type == SubTable::Extension)) return CastR<ExtensionSubst> (get_subtable(0)).is_reverse (); return lookup_type_is_reverse (type); } - inline bool apply (hb_apply_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); return_trace (dispatch (c)); } - inline hb_closure_context_t::return_t closure (hb_closure_context_t *c) const + bool intersects (const hb_set_t *glyphs) const { - TRACE_CLOSURE (this); - c->set_recurse_func (dispatch_recurse_func<hb_closure_context_t>); - return_trace (dispatch (c)); + hb_intersects_context_t c (glyphs); + return dispatch (&c); } - inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const + 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_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const { - TRACE_COLLECT_GLYPHS (this); c->set_recurse_func (dispatch_recurse_func<hb_collect_glyphs_context_t>); - return_trace (dispatch (c)); + return dispatch (c); } template <typename set_t> - inline void add_coverage (set_t *glyphs) const + void add_coverage (set_t *glyphs) const { hb_add_coverage_context_t<set_t> c (glyphs); dispatch (&c); } - inline bool would_apply (hb_would_apply_context_t *c, - const hb_ot_layout_lookup_accelerator_t *accel) const + bool would_apply (hb_would_apply_context_t *c, + const hb_ot_layout_lookup_accelerator_t *accel) const { - TRACE_WOULD_APPLY (this); - if (unlikely (!c->len)) return_trace (false); - if (!accel->may_have (c->glyphs[0])) return_trace (false); - return_trace (dispatch (c)); + if (unlikely (!c->len)) return false; + if (!accel->may_have (c->glyphs[0])) return false; + return dispatch (c); } - static bool apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index); + HB_INTERNAL static bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index); - inline SubstLookupSubTable& serialize_subtable (hb_serialize_context_t *c, - unsigned int i) - { return get_subtables<SubstLookupSubTable> ()[i].serialize (c, this); } + SubTable& serialize_subtable (hb_serialize_context_t *c, + unsigned int i) + { return get_subtables<SubTable> ()[i].serialize (c, this); } - inline bool serialize_single (hb_serialize_context_t *c, - uint32_t lookup_props, - Supplier<GlyphID> &glyphs, - Supplier<GlyphID> &substitutes, - unsigned int num_glyphs) + bool serialize_single (hb_serialize_context_t *c, + uint32_t lookup_props, + hb_sorted_array_t<const HBGlyphID> glyphs, + hb_array_t<const HBGlyphID> substitutes) { TRACE_SERIALIZE (this); - if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Single, lookup_props, 1))) return_trace (false); - return_trace (serialize_subtable (c, 0).u.single.serialize (c, glyphs, substitutes, num_glyphs)); + if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false); + return_trace (serialize_subtable (c, 0).u.single. + serialize (c, hb_zip (glyphs, substitutes))); } - inline bool serialize_multiple (hb_serialize_context_t *c, - uint32_t lookup_props, - Supplier<GlyphID> &glyphs, - Supplier<unsigned int> &substitute_len_list, - unsigned int num_glyphs, - Supplier<GlyphID> &substitute_glyphs_list) + bool serialize_multiple (hb_serialize_context_t *c, + uint32_t lookup_props, + hb_sorted_array_t<const HBGlyphID> glyphs, + hb_array_t<const unsigned int> substitute_len_list, + hb_array_t<const HBGlyphID> substitute_glyphs_list) { TRACE_SERIALIZE (this); - if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Multiple, lookup_props, 1))) return_trace (false); - return_trace (serialize_subtable (c, 0).u.multiple.serialize (c, - glyphs, - substitute_len_list, - num_glyphs, - substitute_glyphs_list)); + if (unlikely (!Lookup::serialize (c, SubTable::Multiple, lookup_props, 1))) return_trace (false); + return_trace (serialize_subtable (c, 0).u.multiple. + serialize (c, + glyphs, + substitute_len_list, + substitute_glyphs_list)); } - inline bool serialize_alternate (hb_serialize_context_t *c, - uint32_t lookup_props, - Supplier<GlyphID> &glyphs, - Supplier<unsigned int> &alternate_len_list, - unsigned int num_glyphs, - Supplier<GlyphID> &alternate_glyphs_list) + bool serialize_alternate (hb_serialize_context_t *c, + uint32_t lookup_props, + hb_sorted_array_t<const HBGlyphID> glyphs, + hb_array_t<const unsigned int> alternate_len_list, + hb_array_t<const HBGlyphID> alternate_glyphs_list) { TRACE_SERIALIZE (this); - if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Alternate, lookup_props, 1))) return_trace (false); - return_trace (serialize_subtable (c, 0).u.alternate.serialize (c, - glyphs, - alternate_len_list, - num_glyphs, - alternate_glyphs_list)); - } - - inline bool serialize_ligature (hb_serialize_context_t *c, - uint32_t lookup_props, - Supplier<GlyphID> &first_glyphs, - Supplier<unsigned int> &ligature_per_first_glyph_count_list, - unsigned int num_first_glyphs, - Supplier<GlyphID> &ligatures_list, - Supplier<unsigned int> &component_count_list, - Supplier<GlyphID> &component_list /* Starting from second for each ligature */) + if (unlikely (!Lookup::serialize (c, SubTable::Alternate, lookup_props, 1))) return_trace (false); + return_trace (serialize_subtable (c, 0).u.alternate. + serialize (c, + glyphs, + alternate_len_list, + alternate_glyphs_list)); + } + + bool serialize_ligature (hb_serialize_context_t *c, + uint32_t lookup_props, + hb_sorted_array_t<const HBGlyphID> first_glyphs, + hb_array_t<const unsigned int> ligature_per_first_glyph_count_list, + hb_array_t<const HBGlyphID> ligatures_list, + hb_array_t<const unsigned int> component_count_list, + hb_array_t<const HBGlyphID> component_list /* Starting from second for each ligature */) { TRACE_SERIALIZE (this); - if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Ligature, lookup_props, 1))) return_trace (false); - return_trace (serialize_subtable (c, 0).u.ligature.serialize (c, - first_glyphs, - ligature_per_first_glyph_count_list, - num_first_glyphs, - ligatures_list, - component_count_list, - component_list)); + if (unlikely (!Lookup::serialize (c, SubTable::Ligature, lookup_props, 1))) return_trace (false); + return_trace (serialize_subtable (c, 0).u.ligature. + serialize (c, + first_glyphs, + ligature_per_first_glyph_count_list, + ligatures_list, + component_count_list, + component_list)); } template <typename context_t> - static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index); - - template <typename context_t> - inline typename context_t::return_t dispatch (context_t *c) const - { return Lookup::dispatch<SubstLookupSubTable> (c); } + HB_INTERNAL static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index); - inline bool sanitize (hb_sanitize_context_t *c) const + HB_INTERNAL static hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned int lookup_index) { - TRACE_SANITIZE (this); - if (unlikely (!Lookup::sanitize (c))) return_trace (false); - if (unlikely (!dispatch (c))) return_trace (false); + if (!c->should_visit_lookup (lookup_index)) + return hb_empty_t (); - if (unlikely (get_type () == SubstLookupSubTable::Extension)) - { - /* The spec says all subtables of an Extension lookup should - * have the same type, which shall not be the Extension type - * itself. This is specially important if one has a reverse type! */ - unsigned int type = get_subtable (0).u.extension.get_type (); - if (unlikely (type == SubstLookupSubTable::Extension)) - return_trace (false); - unsigned int count = get_subtable_count (); - for (unsigned int i = 1; i < count; i++) - if (get_subtable (i).u.extension.get_type () != type) - return_trace (false); - } - return_trace (true); + hb_closure_context_t::return_t ret = dispatch_recurse_func (c, lookup_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; } -}; -typedef OffsetListOf<SubstLookup> SubstLookupList; + template <typename context_t, typename ...Ts> + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const + { return Lookup::dispatch<SubTable> (c, hb_forward<Ts> (ds)...); } + + bool subset (hb_subset_context_t *c) const + { return Lookup::subset<SubTable> (c); } + + bool sanitize (hb_sanitize_context_t *c) const + { return Lookup::sanitize<SubTable> (c); } +}; /* - * GSUB -- The Glyph Substitution Table + * GSUB -- Glyph Substitution + * https://docs.microsoft.com/en-us/typography/opentype/spec/gsub */ struct GSUB : GSUBGPOS { - static const hb_tag_t tableTag = HB_OT_TAG_GSUB; + static constexpr hb_tag_t tableTag = HB_OT_TAG_GSUB; - inline const SubstLookup& get_lookup (unsigned int i) const + const SubstLookup& get_lookup (unsigned int i) const { return CastR<SubstLookup> (GSUBGPOS::get_lookup (i)); } - static inline void substitute_start (hb_font_t *font, hb_buffer_t *buffer); + bool subset (hb_subset_context_t *c) const + { return GSUBGPOS::subset<SubstLookup> (c); } - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - if (unlikely (!GSUBGPOS::sanitize (c))) return_trace (false); - const OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (lookupList); - return_trace (list.sanitize (c, this)); - } -}; + bool sanitize (hb_sanitize_context_t *c) const + { return GSUBGPOS::sanitize<SubstLookup> (c); } + HB_INTERNAL bool is_blacklisted (hb_blob_t *blob, + hb_face_t *face) const; -void -GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer) -{ - _hb_buffer_assert_gsubgpos_vars (buffer); + typedef GSUBGPOS::accelerator_t<GSUB> accelerator_t; +}; - const GDEF &gdef = *hb_ot_layout_from_face (font->face)->gdef; - unsigned int count = buffer->len; - for (unsigned int i = 0; i < count; i++) - { - _hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buffer->info[i].codepoint)); - _hb_glyph_info_clear_lig_props (&buffer->info[i]); - buffer->info[i].syllable() = 0; - } -} + +struct GSUB_accelerator_t : GSUB::accelerator_t {}; /* Out-of-class implementation for methods recursing */ -/*static*/ inline bool ExtensionSubst::is_reverse (void) const +#ifndef HB_NO_OT_LAYOUT +/*static*/ inline bool ExtensionSubst::is_reverse () const { unsigned int type = get_type (); - if (unlikely (type == SubstLookupSubTable::Extension)) - return CastR<ExtensionSubst> (get_subtable<LookupSubTable>()).is_reverse (); + if (unlikely (type == SubTable::Extension)) + return CastR<ExtensionSubst> (get_subtable<SubTable>()).is_reverse (); return SubstLookup::lookup_type_is_reverse (type); } - template <typename context_t> /*static*/ inline typename context_t::return_t SubstLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index) { - const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub); - const SubstLookup &l = gsub.get_lookup (lookup_index); + const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index); return l.dispatch (c); } - -/*static*/ inline bool SubstLookup::apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index) +/*static*/ inline bool SubstLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index) { - const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub); - const SubstLookup &l = gsub.get_lookup (lookup_index); + const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index); unsigned int saved_lookup_props = c->lookup_props; unsigned int saved_lookup_index = c->lookup_index; c->set_lookup_index (lookup_index); @@ -1357,6 +1545,7 @@ template <typename context_t> c->set_lookup_props (saved_lookup_props); return ret; } +#endif } /* namespace OT */ |