--- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gsub-table.hh 2019-02-28 12:03:57.502502984 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gsub-table.hh 2019-02-28 12:03:57.374502986 -0800 @@ -29,34 +29,37 @@ #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 { +static inline void SingleSubst_serialize (hb_serialize_context_t *c, + hb_array_t glyphs, + hb_array_t substitutes); + 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 ()) + for (Coverage::Iter iter (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); + c->out->add ((glyph_id + deltaGlyphID) & 0xFFFFu); } } - 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 ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { /* TODO Switch to range-based API to work around malicious fonts. * https://github.com/harfbuzz/harfbuzz/issues/363 */ @@ -65,18 +68,15 @@ } } - 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 + 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); } - inline bool apply (hb_ot_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,19 +91,37 @@ return_trace (true); } - inline bool serialize (hb_serialize_context_t *c, - Supplier &glyphs, - unsigned int num_glyphs, - int delta) + bool serialize (hb_serialize_context_t *c, + hb_array_t glyphs, + int 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); + deltaGlyphID.set (delta); /* TODO(serialize) overflow? */ 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; + const hb_map_t &glyph_map = *c->plan->glyph_map; + hb_vector_t from; + hb_vector_t to; + hb_codepoint_t delta = deltaGlyphID; + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) + { + if (!glyphset.has (iter.get_glyph ())) continue; + from.push ()->set (glyph_map[iter.get_glyph ()]); + to.push ()->set (glyph_map[(iter.get_glyph () + delta) & 0xFFFF]); + } + c->serializer->propagate_error (from, to); + SingleSubst_serialize (c->serializer, from, to); + return_trace (from.length); + } + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c)); @@ -122,27 +140,26 @@ 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 ()) + for (Coverage::Iter iter (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 ()]); + c->out->add (substitute[iter.get_coverage ()]); } } - 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 ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ @@ -150,45 +167,57 @@ } } - 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 + 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); } - inline bool apply (hb_ot_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 &glyphs, - Supplier &substitutes, - unsigned int num_glyphs) + bool serialize (hb_serialize_context_t *c, + hb_array_t glyphs, + hb_array_t substitutes) { TRACE_SERIALIZE (this); 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; + const hb_map_t &glyph_map = *c->plan->glyph_map; + hb_vector_t from; + hb_vector_t to; + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) + { + if (!glyphset.has (iter.get_glyph ())) continue; + from.push ()->set (glyph_map[iter.get_glyph ()]); + to.push ()->set (glyph_map[substitute[iter.get_coverage ()]]); + } + c->serializer->propagate_error (from, to); + SingleSubst_serialize (c->serializer, from, to); + return_trace (from.length); + } + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (coverage.sanitize (c, this) && substitute.sanitize (c)); @@ -208,35 +237,35 @@ struct SingleSubst { - inline bool serialize (hb_serialize_context_t *c, - Supplier &glyphs, - Supplier &substitutes, - unsigned int num_glyphs) + bool serialize (hb_serialize_context_t *c, + hb_array_t glyphs, + hb_array_t substitutes) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (u.format))) return_trace (false); unsigned int format = 2; int delta = 0; - if (num_glyphs) { + if (glyphs.length) + { 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]) { + for (unsigned int i = 1; i < glyphs.length; i++) + if (delta != (int) (substitutes[i] - glyphs[i])) { format = 2; break; } } u.format.set (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, delta)); + case 2: return_trace (u.format2.serialize (c, glyphs, substitutes)); default:return_trace (false); } } template - inline typename context_t::return_t dispatch (context_t *c) const + typename context_t::return_t dispatch (context_t *c) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); @@ -255,24 +284,25 @@ } u; }; +static inline void +SingleSubst_serialize (hb_serialize_context_t *c, + hb_array_t glyphs, + hb_array_t substitutes) +{ c->start_embed ()->serialize (c, glyphs, substitutes); } struct Sequence { - inline void closure (hb_closure_context_t *c) const + 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]); + c->out->add (substitute[i]); } - inline void collect_glyphs (hb_collect_glyphs_context_t *c) const - { - TRACE_COLLECT_GLYPHS (this); - 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); } - inline bool apply (hb_ot_apply_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); unsigned int count = substitute.len; @@ -304,17 +334,14 @@ return_trace (true); } - inline bool serialize (hb_serialize_context_t *c, - Supplier &glyphs, - unsigned int num_glyphs) + bool serialize (hb_serialize_context_t *c, + hb_array_t glyphs) { 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, glyphs)); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (substitute.sanitize (c)); @@ -329,12 +356,13 @@ 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 ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ @@ -343,27 +371,23 @@ } } - 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); + (this+sequence[i]).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 + 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); } - inline bool apply (hb_ot_apply_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); @@ -373,25 +397,33 @@ return_trace ((this+sequence[index]).apply (c)); } - inline bool serialize (hb_serialize_context_t *c, - Supplier &glyphs, - Supplier &substitute_len_list, - unsigned int num_glyphs, - Supplier &substitute_glyphs_list) + bool serialize (hb_serialize_context_t *c, + hb_array_t glyphs, + hb_array_t substitute_len_list, + hb_array_t 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 += 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)); } - 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); return_trace (coverage.sanitize (c, this) && sequence.sanitize (c, this)); @@ -411,24 +443,23 @@ struct MultipleSubst { - inline bool serialize (hb_serialize_context_t *c, - Supplier &glyphs, - Supplier &substitute_len_list, - unsigned int num_glyphs, - Supplier &substitute_glyphs_list) + bool serialize (hb_serialize_context_t *c, + hb_array_t glyphs, + hb_array_t substitute_len_list, + hb_array_t substitute_glyphs_list) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (u.format))) return_trace (false); unsigned int format = 1; u.format.set (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 - inline typename context_t::return_t dispatch (context_t *c) const + typename context_t::return_t dispatch (context_t *c) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); @@ -445,103 +476,138 @@ } u; }; +struct AlternateSet +{ + void closure (hb_closure_context_t *c) const + { + unsigned int count = alternates.len; + for (unsigned int i = 0; i < count; i++) + c->out->add (alternates[i]); + } + + 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; -typedef ArrayOf AlternateSet; /* Array of alternate GlyphIDs--in + 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, 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); + } + + bool serialize (hb_serialize_context_t *c, + hb_array_t glyphs) + { + TRACE_SERIALIZE (this); + return_trace (alternates.serialize (c, glyphs)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (alternates.sanitize (c)); + } + + protected: + ArrayOf + alternates; /* Array of alternate GlyphIDs--in * arbitrary order */ + public: + DEFINE_SIZE_ARRAY (2, alternates); +}; struct AlternateSubstFormat1 { - 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 = alternateSet.len; - for (iter.init (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (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]); - } + if (c->glyphs->has (iter.get_glyph ())) + (this+alternateSet[iter.get_coverage ()]).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; - Coverage::Iter iter; unsigned int count = alternateSet.len; - for (iter.init (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (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.arrayZ, alt_set.len); + (this+alternateSet[iter.get_coverage ()]).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 + 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); } - inline bool apply (hb_ot_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 AlternateSet &alt_set = this+alternateSet[index]; - - if (unlikely (!alt_set.len)) 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 (unlikely (alt_index > alt_set.len || alt_index == 0)) return_trace (false); - - glyph_id = alt_set[alt_index - 1]; - - c->replace_glyph (glyph_id); - - return_trace (true); + return_trace ((this+alternateSet[index]).apply (c)); } - inline bool serialize (hb_serialize_context_t *c, - Supplier &glyphs, - Supplier &alternate_len_list, - unsigned int num_glyphs, - Supplier &alternate_glyphs_list) + bool serialize (hb_serialize_context_t *c, + hb_array_t glyphs, + hb_array_t alternate_len_list, + hb_array_t 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 += 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); + // TODO(subset) + return_trace (false); } - 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)); @@ -561,24 +627,23 @@ struct AlternateSubst { - inline bool serialize (hb_serialize_context_t *c, - Supplier &glyphs, - Supplier &alternate_len_list, - unsigned int num_glyphs, - Supplier &alternate_glyphs_list) + bool serialize (hb_serialize_context_t *c, + hb_array_t glyphs, + hb_array_t alternate_len_list, + hb_array_t alternate_glyphs_list) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (u.format))) return_trace (false); unsigned int format = 1; u.format.set (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 - inline typename context_t::return_t dispatch (context_t *c) const + typename context_t::return_t dispatch (context_t *c) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); @@ -598,27 +663,34 @@ struct Ligature { - inline void closure (hb_closure_context_t *c) const + bool intersects (const hb_set_t *glyphs) const { - TRACE_CLOSURE (this); - unsigned int count = component.len; + unsigned int count = component.lenP1; + for (unsigned int i = 1; i < count; i++) + if (!glyphs->has (component[i])) + return false; + return true; + } + + void closure (hb_closure_context_t *c) const + { + unsigned int count = component.lenP1; for (unsigned int i = 1; i < count; i++) if (!c->glyphs->has (component[i])) return; - c->glyphs->add (ligGlyph); + c->out->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.arrayZ, component.len ? component.len - 1 : 0); + c->input->add_array (component.arrayZ, component.lenP1 ? component.lenP1 - 1 : 0); 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) + if (c->len != component.lenP1) return_trace (false); for (unsigned int i = 1; i < c->len; i++) @@ -628,10 +700,10 @@ return_trace (true); } - inline bool apply (hb_ot_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 +715,6 @@ return_trace (true); } - bool is_mark_ligature = false; unsigned int total_component_count = 0; unsigned int match_length = 0; @@ -655,7 +726,6 @@ nullptr, &match_length, match_positions, - &is_mark_ligature, &total_component_count))) return_trace (false); @@ -664,26 +734,24 @@ 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 &components, /* Starting from second */ - unsigned int num_components /* Including first component */) + bool serialize (hb_serialize_context_t *c, + GlyphID ligature, + hb_array_t 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); } 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)); @@ -701,23 +769,30 @@ struct LigatureSet { - inline void closure (hb_closure_context_t *c) const + bool intersects (const hb_set_t *glyphs) const + { + unsigned int num_ligs = ligature.len; + for (unsigned int i = 0; i < num_ligs; i++) + if ((this+ligature[i]).intersects (glyphs)) + return true; + return false; + } + + void closure (hb_closure_context_t *c) const { - TRACE_CLOSURE (this); unsigned int num_ligs = ligature.len; for (unsigned int i = 0; i < num_ligs; i++) (this+ligature[i]).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); unsigned int num_ligs = ligature.len; for (unsigned int i = 0; i < num_ligs; i++) (this+ligature[i]).collect_glyphs (c); } - 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); unsigned int num_ligs = ligature.len; @@ -730,7 +805,7 @@ return_trace (false); } - inline bool apply (hb_ot_apply_context_t *c) const + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); unsigned int num_ligs = ligature.len; @@ -743,26 +818,28 @@ return_trace (false); } - inline bool serialize (hb_serialize_context_t *c, - Supplier &ligatures, - Supplier &component_count_list, - unsigned int num_ligatures, - Supplier &component_list /* Starting from second for each ligature */) + bool serialize (hb_serialize_context_t *c, + hb_array_t ligatures, + hb_array_t component_count_list, + hb_array_t &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 += num_ligatures; - component_count_list += 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 = MAX (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 sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (ligature.sanitize (c, this)); @@ -778,12 +855,24 @@ 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 ()) + for (Coverage::Iter iter (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 (glyphs->has (iter.get_glyph ()) && + (this+ligatureSet[iter.get_coverage ()]).intersects (glyphs)) + return true; + } + return false; + } + + void closure (hb_closure_context_t *c) const + { + unsigned int count = ligatureSet.len; + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ @@ -792,13 +881,11 @@ } } - 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 = ligatureSet.len; - for (iter.init (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ @@ -806,12 +893,9 @@ } } - 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 + bool would_apply (hb_would_apply_context_t *c) const { TRACE_WOULD_APPLY (this); unsigned int index = (this+coverage).get_coverage (c->glyphs[0]); @@ -821,41 +905,49 @@ return_trace (lig_set.would_apply (c)); } - inline bool apply (hb_ot_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 &first_glyphs, - Supplier &ligature_per_first_glyph_count_list, - unsigned int num_first_glyphs, - Supplier &ligatures_list, - Supplier &component_count_list, - Supplier &component_list /* Starting from second for each ligature */) + bool serialize (hb_serialize_context_t *c, + hb_array_t first_glyphs, + hb_array_t ligature_per_first_glyph_count_list, + hb_array_t ligatures_list, + hb_array_t component_count_list, + hb_array_t 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 += 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)); } - 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); return_trace (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this)); @@ -875,13 +967,12 @@ struct LigatureSubst { - inline bool serialize (hb_serialize_context_t *c, - Supplier &first_glyphs, - Supplier &ligature_per_first_glyph_count_list, - unsigned int num_first_glyphs, - Supplier &ligatures_list, - Supplier &component_count_list, - Supplier &component_list /* Starting from second for each ligature */) + bool serialize (hb_serialize_context_t *c, + hb_array_t first_glyphs, + hb_array_t ligature_per_first_glyph_count_list, + hb_array_t ligatures_list, + hb_array_t component_count_list, + hb_array_t component_list /* Starting from second for each ligature */) { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (u.format))) return_trace (false); @@ -891,7 +982,6 @@ 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)); @@ -900,7 +990,7 @@ } template - inline typename context_t::return_t dispatch (context_t *c) const + typename context_t::return_t dispatch (context_t *c) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); @@ -924,17 +1014,38 @@ struct ExtensionSubst : Extension { - 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 + { + if (!(this+coverage).intersects (glyphs)) + return false; + + const OffsetArrayOf &lookahead = StructAfter > (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; + } + + void closure (hb_closure_context_t *c) const { - TRACE_CLOSURE (this); const OffsetArrayOf &lookahead = StructAfter > (backtrack); unsigned int count; @@ -950,20 +1061,18 @@ return; const ArrayOf &substitute = StructAfter > (lookahead); - Coverage::Iter iter; count = substitute.len; - for (iter.init (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (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 ()]); + c->out->add (substitute[iter.get_coverage ()]); } } - 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; @@ -982,18 +1091,15 @@ 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 + 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); } - inline bool apply (hb_ot_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)) @@ -1026,7 +1132,14 @@ 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))) @@ -1045,7 +1158,7 @@ * beginning of table */ OffsetArrayOf backtrack; /* Array of coverage tables - * in backtracking sequence, in glyph + * in backtracking sequence, in glyph * sequence order */ OffsetArrayOf lookaheadX; /* Array of coverage tables @@ -1061,7 +1174,7 @@ struct ReverseChainSingleSubst { template - inline typename context_t::return_t dispatch (context_t *c) const + typename context_t::return_t dispatch (context_t *c) const { TRACE_DISPATCH (this, u.format); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); @@ -1086,6 +1199,7 @@ struct SubstLookupSubTable { + friend struct Lookup; friend struct SubstLookup; enum Type { @@ -1100,10 +1214,9 @@ }; template - inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const + typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) 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)); @@ -1119,7 +1232,6 @@ protected: union { - HBUINT16 sub_format; SingleSubst single; MultipleSubst multiple; AlternateSubst alternate; @@ -1130,58 +1242,69 @@ 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 (i); } + typedef SubstLookupSubTable SubTable; + + const SubTable& get_subtable (unsigned int i) const + { return Lookup::get_subtable (i); } - inline static bool lookup_type_is_reverse (unsigned int lookup_type) - { return lookup_type == SubstLookupSubTable::ReverseChainSingle; } + static bool lookup_type_is_reverse (unsigned int lookup_type) + { return lookup_type == SubTable::ReverseChainSingle; } - inline bool is_reverse (void) const + bool is_reverse () const { unsigned int type = get_type (); - if (unlikely (type == SubstLookupSubTable::Extension)) + if (unlikely (type == SubTable::Extension)) return CastR (get_subtable(0)).is_reverse (); return lookup_type_is_reverse (type); } - inline bool apply (hb_ot_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, unsigned int this_index) const + 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 { - TRACE_CLOSURE (this); if (!c->should_visit_lookup (this_index)) - return_trace (HB_VOID); + return hb_closure_context_t::default_return_value (); c->set_recurse_func (dispatch_closure_recurse_func); - return_trace (dispatch (c)); + + hb_closure_context_t::return_t ret = dispatch (c); + + c->flush (); + + return ret; } - inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const + 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); - return_trace (dispatch (c)); + return dispatch (c); } template - inline void add_coverage (set_t *glyphs) const + void add_coverage (set_t *glyphs) const { hb_add_coverage_context_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); @@ -1191,111 +1314,95 @@ 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 ()[i].serialize (c, this); } - - inline bool serialize_single (hb_serialize_context_t *c, - uint32_t lookup_props, - Supplier &glyphs, - Supplier &substitutes, - unsigned int num_glyphs) + SubTable& serialize_subtable (hb_serialize_context_t *c, + unsigned int i) + { return get_subtables ()[i].serialize (c, this); } + + bool serialize_single (hb_serialize_context_t *c, + uint32_t lookup_props, + hb_array_t glyphs, + hb_array_t 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, glyphs, substitutes)); } - inline bool serialize_multiple (hb_serialize_context_t *c, - uint32_t lookup_props, - Supplier &glyphs, - Supplier &substitute_len_list, - unsigned int num_glyphs, - Supplier &substitute_glyphs_list) + bool serialize_multiple (hb_serialize_context_t *c, + uint32_t lookup_props, + hb_array_t glyphs, + hb_array_t substitute_len_list, + hb_array_t substitute_glyphs_list) { TRACE_SERIALIZE (this); - if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Multiple, lookup_props, 1))) return_trace (false); + 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, - num_glyphs, substitute_glyphs_list)); } - inline bool serialize_alternate (hb_serialize_context_t *c, - uint32_t lookup_props, - Supplier &glyphs, - Supplier &alternate_len_list, - unsigned int num_glyphs, - Supplier &alternate_glyphs_list) + bool serialize_alternate (hb_serialize_context_t *c, + uint32_t lookup_props, + hb_array_t glyphs, + hb_array_t alternate_len_list, + hb_array_t alternate_glyphs_list) { TRACE_SERIALIZE (this); - if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Alternate, lookup_props, 1))) return_trace (false); + 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, - num_glyphs, alternate_glyphs_list)); } - inline bool serialize_ligature (hb_serialize_context_t *c, - uint32_t lookup_props, - Supplier &first_glyphs, - Supplier &ligature_per_first_glyph_count_list, - unsigned int num_first_glyphs, - Supplier &ligatures_list, - Supplier &component_count_list, - Supplier &component_list /* Starting from second for each ligature */) + bool serialize_ligature (hb_serialize_context_t *c, + uint32_t lookup_props, + hb_array_t first_glyphs, + hb_array_t ligature_per_first_glyph_count_list, + hb_array_t ligatures_list, + hb_array_t component_count_list, + hb_array_t component_list /* Starting from second for each ligature */) { TRACE_SERIALIZE (this); - if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Ligature, lookup_props, 1))) return_trace (false); + 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, - num_first_glyphs, ligatures_list, component_count_list, component_list)); } template - static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index); + static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index); - static inline hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned int lookup_index) + static hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned int lookup_index) { if (!c->should_visit_lookup (lookup_index)) return HB_VOID; - return dispatch_recurse_func (c, lookup_index); + + 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; } template - inline typename context_t::return_t dispatch (context_t *c) const - { return Lookup::dispatch (c); } + typename context_t::return_t dispatch (context_t *c) const + { return Lookup::dispatch (c); } - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - if (unlikely (!Lookup::sanitize (c))) return_trace (false); - if (unlikely (!dispatch (c))) return_trace (false); + bool subset (hb_subset_context_t *c) const + { return Lookup::subset (c); } - 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 (but we already checked for that). - * This is specially important if one has a reverse type! */ - unsigned int type = get_subtable (0).u.extension.get_type (); - 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); - } + bool sanitize (hb_sanitize_context_t *c) const + { return Lookup::sanitize (c); } }; -typedef OffsetListOf SubstLookupList; - /* * GSUB -- Glyph Substitution * https://docs.microsoft.com/en-us/typography/opentype/spec/gsub @@ -1303,61 +1410,47 @@ 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 (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 (c); } - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - if (unlikely (!GSUBGPOS::sanitize (c))) return_trace (false); - const OffsetTo &list = CastR > (lookupList); - return_trace (list.sanitize (c, this)); - } -}; + bool sanitize (hb_sanitize_context_t *c) const + { return GSUBGPOS::sanitize (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 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 +/*static*/ inline bool ExtensionSubst::is_reverse () const { unsigned int type = get_type (); - if (unlikely (type == SubstLookupSubTable::Extension)) - return CastR (get_subtable()).is_reverse (); + if (unlikely (type == SubTable::Extension)) + return CastR (get_subtable()).is_reverse (); return SubstLookup::lookup_type_is_reverse (type); } template /*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_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); @@ -1368,7 +1461,6 @@ return ret; } - } /* namespace OT */