| Index: third_party/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh
|
| diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh
|
| index 4229f32f053a8a173b59efb950f26bc3f5fec9e7..90faa79c64524889d02c9c434fd09bb1dccf9ce9 100644
|
| --- a/third_party/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh
|
| +++ b/third_party/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh
|
| @@ -32,6 +32,8 @@
|
| #include "hb-ot-layout-gsubgpos-private.hh"
|
|
|
|
|
| +namespace OT {
|
| +
|
|
|
| struct SingleSubstFormat1
|
| {
|
| @@ -50,9 +52,9 @@ struct SingleSubstFormat1
|
| }
|
| }
|
|
|
| - inline bool would_apply (hb_codepoint_t glyph_id) const
|
| + inline const Coverage &get_coverage (void) const
|
| {
|
| - return (this+coverage) (glyph_id) != NOT_COVERED;
|
| + return this+coverage;
|
| }
|
|
|
| inline bool apply (hb_apply_context_t *c) const
|
| @@ -70,12 +72,24 @@ struct SingleSubstFormat1
|
| return TRACE_RETURN (true);
|
| }
|
|
|
| + inline bool serialize (hb_serialize_context_t *c,
|
| + Supplier<GlyphID> &glyphs,
|
| + unsigned int num_glyphs,
|
| + int delta)
|
| + {
|
| + TRACE_SERIALIZE ();
|
| + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
|
| + if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false);
|
| + deltaGlyphID.set (delta); /* TODO(serilaize) overflow? */
|
| + return TRACE_RETURN (true);
|
| + }
|
| +
|
| inline bool sanitize (hb_sanitize_context_t *c) {
|
| TRACE_SANITIZE ();
|
| return TRACE_RETURN (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c));
|
| }
|
|
|
| - private:
|
| + protected:
|
| USHORT format; /* Format identifier--format = 1 */
|
| OffsetTo<Coverage>
|
| coverage; /* Offset to Coverage table--from
|
| @@ -102,9 +116,9 @@ struct SingleSubstFormat2
|
| }
|
| }
|
|
|
| - inline bool would_apply (hb_codepoint_t glyph_id) const
|
| + inline const Coverage &get_coverage (void) const
|
| {
|
| - return (this+coverage) (glyph_id) != NOT_COVERED;
|
| + return this+coverage;
|
| }
|
|
|
| inline bool apply (hb_apply_context_t *c) const
|
| @@ -122,12 +136,24 @@ struct SingleSubstFormat2
|
| return TRACE_RETURN (true);
|
| }
|
|
|
| + inline bool serialize (hb_serialize_context_t *c,
|
| + Supplier<GlyphID> &glyphs,
|
| + Supplier<GlyphID> &substitutes,
|
| + unsigned int num_glyphs)
|
| + {
|
| + TRACE_SERIALIZE ();
|
| + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
|
| + if (unlikely (!substitute.serialize (c, substitutes, num_glyphs))) return TRACE_RETURN (false);
|
| + if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false);
|
| + return TRACE_RETURN (true);
|
| + }
|
| +
|
| inline bool sanitize (hb_sanitize_context_t *c) {
|
| TRACE_SANITIZE ();
|
| return TRACE_RETURN (coverage.sanitize (c, this) && substitute.sanitize (c));
|
| }
|
|
|
| - private:
|
| + protected:
|
| USHORT format; /* Format identifier--format = 2 */
|
| OffsetTo<Coverage>
|
| coverage; /* Offset to Coverage table--from
|
| @@ -142,6 +168,7 @@ struct SingleSubstFormat2
|
| struct SingleSubst
|
| {
|
| friend struct SubstLookupSubTable;
|
| + friend struct SubstLookup;
|
|
|
| private:
|
|
|
| @@ -155,12 +182,12 @@ struct SingleSubst
|
| }
|
| }
|
|
|
| - inline bool would_apply (hb_codepoint_t glyph_id) const
|
| + inline const Coverage &get_coverage (void) const
|
| {
|
| switch (u.format) {
|
| - case 1: return u.format1.would_apply (glyph_id);
|
| - case 2: return u.format2.would_apply (glyph_id);
|
| - default:return false;
|
| + case 1: return u.format1.get_coverage ();
|
| + case 2: return u.format2.get_coverage ();
|
| + default:return Null(Coverage);
|
| }
|
| }
|
|
|
| @@ -174,6 +201,33 @@ struct SingleSubst
|
| }
|
| }
|
|
|
| + inline bool serialize (hb_serialize_context_t *c,
|
| + Supplier<GlyphID> &glyphs,
|
| + Supplier<GlyphID> &substitutes,
|
| + unsigned int num_glyphs)
|
| + {
|
| + TRACE_SERIALIZE ();
|
| + if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false);
|
| + unsigned int format = 2;
|
| + int delta;
|
| + if (num_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;
|
| + }
|
| + }
|
| + u.format.set (format);
|
| + switch (u.format) {
|
| + case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, num_glyphs, delta));
|
| + case 2: return TRACE_RETURN (u.format2.serialize (c, glyphs, substitutes, num_glyphs));
|
| + default:return TRACE_RETURN (false);
|
| + }
|
| + }
|
| +
|
| inline bool sanitize (hb_sanitize_context_t *c) {
|
| TRACE_SANITIZE ();
|
| if (!u.format.sanitize (c)) return TRACE_RETURN (false);
|
| @@ -184,7 +238,7 @@ struct SingleSubst
|
| }
|
| }
|
|
|
| - private:
|
| + protected:
|
| union {
|
| USHORT format; /* Format identifier */
|
| SingleSubstFormat1 format1;
|
| @@ -213,8 +267,23 @@ struct Sequence
|
| if (unlikely (!substitute.len)) return TRACE_RETURN (false);
|
|
|
| unsigned int klass = c->property & HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE ? HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH : 0;
|
| - c->replace_glyphs_be16 (1, substitute.len, (const char *) substitute.array, klass);
|
| + unsigned int count = substitute.len;
|
| + for (unsigned int i = 0; i < count; i++) {
|
| + set_lig_props_for_component (c->buffer->cur(), i);
|
| + c->output_glyph (substitute.array[i], klass);
|
| + }
|
| + c->buffer->skip_glyph ();
|
| +
|
| + return TRACE_RETURN (true);
|
| + }
|
|
|
| + inline bool serialize (hb_serialize_context_t *c,
|
| + Supplier<GlyphID> &glyphs,
|
| + unsigned int num_glyphs)
|
| + {
|
| + TRACE_SERIALIZE ();
|
| + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
|
| + if (unlikely (!substitute.serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false);
|
| return TRACE_RETURN (true);
|
| }
|
|
|
| @@ -224,7 +293,7 @@ struct Sequence
|
| return TRACE_RETURN (substitute.sanitize (c));
|
| }
|
|
|
| - private:
|
| + protected:
|
| ArrayOf<GlyphID>
|
| substitute; /* String of GlyphIDs to substitute */
|
| public:
|
| @@ -247,9 +316,9 @@ struct MultipleSubstFormat1
|
| }
|
| }
|
|
|
| - inline bool would_apply (hb_codepoint_t glyph_id) const
|
| + inline const Coverage &get_coverage (void) const
|
| {
|
| - return (this+coverage) (glyph_id) != NOT_COVERED;
|
| + return this+coverage;
|
| }
|
|
|
| inline bool apply (hb_apply_context_t *c) const
|
| @@ -262,12 +331,30 @@ struct MultipleSubstFormat1
|
| return TRACE_RETURN ((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)
|
| + {
|
| + TRACE_SERIALIZE ();
|
| + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
|
| + if (unlikely (!sequence.serialize (c, num_glyphs))) return TRACE_RETURN (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_RETURN (false);
|
| + substitute_len_list.advance (num_glyphs);
|
| + if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false);
|
| + return TRACE_RETURN (true);
|
| + }
|
| +
|
| inline bool sanitize (hb_sanitize_context_t *c) {
|
| TRACE_SANITIZE ();
|
| return TRACE_RETURN (coverage.sanitize (c, this) && sequence.sanitize (c, this));
|
| }
|
|
|
| - private:
|
| + protected:
|
| USHORT format; /* Format identifier--format = 1 */
|
| OffsetTo<Coverage>
|
| coverage; /* Offset to Coverage table--from
|
| @@ -282,6 +369,7 @@ struct MultipleSubstFormat1
|
| struct MultipleSubst
|
| {
|
| friend struct SubstLookupSubTable;
|
| + friend struct SubstLookup;
|
|
|
| private:
|
|
|
| @@ -294,11 +382,11 @@ struct MultipleSubst
|
| }
|
| }
|
|
|
| - inline bool would_apply (hb_codepoint_t glyph_id) const
|
| + inline const Coverage &get_coverage (void) const
|
| {
|
| switch (u.format) {
|
| - case 1: return u.format1.would_apply (glyph_id);
|
| - default:return false;
|
| + case 1: return u.format1.get_coverage ();
|
| + default:return Null(Coverage);
|
| }
|
| }
|
|
|
| @@ -311,6 +399,22 @@ 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)
|
| + {
|
| + TRACE_SERIALIZE ();
|
| + if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false);
|
| + unsigned int format = 1;
|
| + u.format.set (format);
|
| + switch (u.format) {
|
| + case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, substitute_len_list, num_glyphs, substitute_glyphs_list));
|
| + default:return TRACE_RETURN (false);
|
| + }
|
| + }
|
| +
|
| inline bool sanitize (hb_sanitize_context_t *c) {
|
| TRACE_SANITIZE ();
|
| if (!u.format.sanitize (c)) return TRACE_RETURN (false);
|
| @@ -320,7 +424,7 @@ struct MultipleSubst
|
| }
|
| }
|
|
|
| - private:
|
| + protected:
|
| union {
|
| USHORT format; /* Format identifier */
|
| MultipleSubstFormat1 format1;
|
| @@ -351,9 +455,9 @@ struct AlternateSubstFormat1
|
| }
|
| }
|
|
|
| - inline bool would_apply (hb_codepoint_t glyph_id) const
|
| + inline const Coverage &get_coverage (void) const
|
| {
|
| - return (this+coverage) (glyph_id) != NOT_COVERED;
|
| + return this+coverage;
|
| }
|
|
|
| inline bool apply (hb_apply_context_t *c) const
|
| @@ -384,12 +488,30 @@ struct AlternateSubstFormat1
|
| return TRACE_RETURN (true);
|
| }
|
|
|
| + 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)
|
| + {
|
| + TRACE_SERIALIZE ();
|
| + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
|
| + if (unlikely (!alternateSet.serialize (c, num_glyphs))) return TRACE_RETURN (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_RETURN (false);
|
| + alternate_len_list.advance (num_glyphs);
|
| + if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false);
|
| + return TRACE_RETURN (true);
|
| + }
|
| +
|
| inline bool sanitize (hb_sanitize_context_t *c) {
|
| TRACE_SANITIZE ();
|
| return TRACE_RETURN (coverage.sanitize (c, this) && alternateSet.sanitize (c, this));
|
| }
|
|
|
| - private:
|
| + protected:
|
| USHORT format; /* Format identifier--format = 1 */
|
| OffsetTo<Coverage>
|
| coverage; /* Offset to Coverage table--from
|
| @@ -404,6 +526,7 @@ struct AlternateSubstFormat1
|
| struct AlternateSubst
|
| {
|
| friend struct SubstLookupSubTable;
|
| + friend struct SubstLookup;
|
|
|
| private:
|
|
|
| @@ -416,11 +539,11 @@ struct AlternateSubst
|
| }
|
| }
|
|
|
| - inline bool would_apply (hb_codepoint_t glyph_id) const
|
| + inline const Coverage &get_coverage (void) const
|
| {
|
| switch (u.format) {
|
| - case 1: return u.format1.would_apply (glyph_id);
|
| - default:return false;
|
| + case 1: return u.format1.get_coverage ();
|
| + default:return Null(Coverage);
|
| }
|
| }
|
|
|
| @@ -433,6 +556,22 @@ 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)
|
| + {
|
| + TRACE_SERIALIZE ();
|
| + if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false);
|
| + unsigned int format = 1;
|
| + u.format.set (format);
|
| + switch (u.format) {
|
| + case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, alternate_len_list, num_glyphs, alternate_glyphs_list));
|
| + default:return TRACE_RETURN (false);
|
| + }
|
| + }
|
| +
|
| inline bool sanitize (hb_sanitize_context_t *c) {
|
| TRACE_SANITIZE ();
|
| if (!u.format.sanitize (c)) return TRACE_RETURN (false);
|
| @@ -442,7 +581,7 @@ struct AlternateSubst
|
| }
|
| }
|
|
|
| - private:
|
| + protected:
|
| union {
|
| USHORT format; /* Format identifier */
|
| AlternateSubstFormat1 format1;
|
| @@ -466,68 +605,61 @@ struct Ligature
|
| c->glyphs->add (ligGlyph);
|
| }
|
|
|
| - inline bool would_apply (hb_codepoint_t second) const
|
| + inline bool would_apply (hb_would_apply_context_t *c) const
|
| {
|
| - return component.len == 2 && component[1] == second;
|
| + if (c->len != component.len)
|
| + return false;
|
| +
|
| + for (unsigned int i = 1; i < c->len; i++)
|
| + if (likely (c->glyphs[i] != component[i]))
|
| + return false;
|
| +
|
| + return true;
|
| }
|
|
|
| inline bool apply (hb_apply_context_t *c) const
|
| {
|
| TRACE_APPLY ();
|
| unsigned int count = component.len;
|
| - if (unlikely (count < 2)) return TRACE_RETURN (false);
|
| -
|
| - hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1);
|
| - if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
|
| -
|
| - bool first_was_mark = (c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK);
|
| - bool found_non_mark = false;
|
| -
|
| - for (unsigned int i = 1; i < count; i++)
|
| - {
|
| - unsigned int property;
|
| -
|
| - if (!skippy_iter.next (&property)) return TRACE_RETURN (false);
|
| -
|
| - found_non_mark |= !(property & HB_OT_LAYOUT_GLYPH_CLASS_MARK);
|
| -
|
| - if (likely (c->buffer->info[skippy_iter.idx].codepoint != component[i])) return TRACE_RETURN (false);
|
| - }
|
| -
|
| - unsigned int klass = first_was_mark && found_non_mark ? HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE : 0;
|
| -
|
| - /* Allocate new ligature id */
|
| - unsigned int lig_id = allocate_lig_id (c->buffer);
|
| - set_lig_props (c->buffer->cur(), lig_id, 0);
|
| -
|
| - if (skippy_iter.idx < c->buffer->idx + count) /* No input glyphs skipped */
|
| - {
|
| - c->replace_glyphs_be16 (count, 1, (const char *) &ligGlyph, klass);
|
| - }
|
| - else
|
| - {
|
| - c->replace_glyph (ligGlyph);
|
| + if (unlikely (count < 1)) return TRACE_RETURN (false);
|
| +
|
| + unsigned int end_offset;
|
| + bool is_mark_ligature;
|
| + unsigned int total_component_count;
|
| +
|
| + if (likely (!match_input (c, count,
|
| + &component[1],
|
| + match_glyph,
|
| + NULL,
|
| + &end_offset,
|
| + &is_mark_ligature,
|
| + &total_component_count)))
|
| + return TRACE_RETURN (false);
|
|
|
| - /* Now we must do a second loop to copy the skipped glyphs to
|
| - `out' and assign component values to it. We start with the
|
| - glyph after the first component. Glyphs between component
|
| - i and i+1 belong to component i. Together with the lig_id
|
| - value it is later possible to check whether a specific
|
| - component value really belongs to a given ligature. */
|
| + /* Deal, we are forming the ligature. */
|
| + c->buffer->merge_clusters (c->buffer->idx, c->buffer->idx + end_offset);
|
|
|
| - for (unsigned int i = 1; i < count; i++)
|
| - {
|
| - while (c->should_mark_skip_current_glyph ())
|
| - {
|
| - set_lig_props (c->buffer->cur(), lig_id, i);
|
| - c->replace_glyph (c->buffer->cur().codepoint);
|
| - }
|
| + ligate_input (c,
|
| + count,
|
| + &component[1],
|
| + ligGlyph,
|
| + match_glyph,
|
| + NULL,
|
| + is_mark_ligature,
|
| + total_component_count);
|
|
|
| - /* Skip the base glyph */
|
| - c->buffer->idx++;
|
| - }
|
| - }
|
| + return TRACE_RETURN (true);
|
| + }
|
|
|
| + inline bool serialize (hb_serialize_context_t *c,
|
| + GlyphID ligature,
|
| + Supplier<GlyphID> &components, /* Starting from second */
|
| + unsigned int num_components /* Including first component */)
|
| + {
|
| + TRACE_SERIALIZE ();
|
| + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
|
| + ligGlyph = ligature;
|
| + if (unlikely (!component.serialize (c, components, num_components))) return TRACE_RETURN (false);
|
| return TRACE_RETURN (true);
|
| }
|
|
|
| @@ -537,7 +669,7 @@ struct Ligature
|
| return TRACE_RETURN (ligGlyph.sanitize (c) && component.sanitize (c));
|
| }
|
|
|
| - private:
|
| + protected:
|
| GlyphID ligGlyph; /* GlyphID of ligature to substitute */
|
| HeadlessArrayOf<GlyphID>
|
| component; /* Array of component GlyphIDs--start
|
| @@ -561,13 +693,13 @@ struct LigatureSet
|
| (this+ligature[i]).closure (c);
|
| }
|
|
|
| - inline bool would_apply (hb_codepoint_t second) const
|
| + inline bool would_apply (hb_would_apply_context_t *c) const
|
| {
|
| 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 (second))
|
| + if (lig.would_apply (c))
|
| return true;
|
| }
|
| return false;
|
| @@ -586,13 +718,32 @@ struct LigatureSet
|
| return TRACE_RETURN (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 */)
|
| + {
|
| + TRACE_SERIALIZE ();
|
| + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
|
| + if (unlikely (!ligature.serialize (c, num_ligatures))) return TRACE_RETURN (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_RETURN (false);
|
| + ligatures.advance (num_ligatures);
|
| + component_count_list.advance (num_ligatures);
|
| + return TRACE_RETURN (true);
|
| + }
|
| +
|
| public:
|
| inline bool sanitize (hb_sanitize_context_t *c) {
|
| TRACE_SANITIZE ();
|
| return TRACE_RETURN (ligature.sanitize (c, this));
|
| }
|
|
|
| - private:
|
| + protected:
|
| OffsetArrayOf<Ligature>
|
| ligature; /* Array LigatureSet tables
|
| * ordered by preference */
|
| @@ -616,11 +767,14 @@ struct LigatureSubstFormat1
|
| }
|
| }
|
|
|
| - inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) const
|
| + inline const Coverage &get_coverage (void) const
|
| {
|
| - unsigned int index;
|
| - return (index = (this+coverage) (first)) != NOT_COVERED &&
|
| - (this+ligatureSet[index]).would_apply (second);
|
| + return this+coverage;
|
| + }
|
| +
|
| + inline bool would_apply (hb_would_apply_context_t *c) const
|
| + {
|
| + return (this+ligatureSet[(this+coverage) (c->glyphs[0])]).would_apply (c);
|
| }
|
|
|
| inline bool apply (hb_apply_context_t *c) const
|
| @@ -635,12 +789,34 @@ struct LigatureSubstFormat1
|
| return TRACE_RETURN (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 */)
|
| + {
|
| + TRACE_SERIALIZE ();
|
| + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
|
| + if (unlikely (!ligatureSet.serialize (c, num_first_glyphs))) return TRACE_RETURN (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_RETURN (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_RETURN (false);
|
| + return TRACE_RETURN (true);
|
| + }
|
| +
|
| inline bool sanitize (hb_sanitize_context_t *c) {
|
| TRACE_SANITIZE ();
|
| return TRACE_RETURN (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this));
|
| }
|
|
|
| - private:
|
| + protected:
|
| USHORT format; /* Format identifier--format = 1 */
|
| OffsetTo<Coverage>
|
| coverage; /* Offset to Coverage table--from
|
| @@ -655,6 +831,7 @@ struct LigatureSubstFormat1
|
| struct LigatureSubst
|
| {
|
| friend struct SubstLookupSubTable;
|
| + friend struct SubstLookup;
|
|
|
| private:
|
|
|
| @@ -667,10 +844,18 @@ struct LigatureSubst
|
| }
|
| }
|
|
|
| - inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) const
|
| + inline const Coverage &get_coverage (void) const
|
| {
|
| switch (u.format) {
|
| - case 1: return u.format1.would_apply (first, second);
|
| + case 1: return u.format1.get_coverage ();
|
| + default:return Null(Coverage);
|
| + }
|
| + }
|
| +
|
| + inline bool would_apply (hb_would_apply_context_t *c) const
|
| + {
|
| + switch (u.format) {
|
| + case 1: return u.format1.would_apply (c);
|
| default:return false;
|
| }
|
| }
|
| @@ -684,6 +869,25 @@ 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 */)
|
| + {
|
| + TRACE_SERIALIZE ();
|
| + if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false);
|
| + unsigned int format = 1;
|
| + u.format.set (format);
|
| + switch (u.format) {
|
| + case 1: return TRACE_RETURN (u.format1.serialize (c, first_glyphs, ligature_per_first_glyph_count_list, num_first_glyphs,
|
| + ligatures_list, component_count_list, component_list));
|
| + default:return TRACE_RETURN (false);
|
| + }
|
| + }
|
| +
|
| inline bool sanitize (hb_sanitize_context_t *c) {
|
| TRACE_SANITIZE ();
|
| if (!u.format.sanitize (c)) return TRACE_RETURN (false);
|
| @@ -693,7 +897,7 @@ struct LigatureSubst
|
| }
|
| }
|
|
|
| - private:
|
| + protected:
|
| union {
|
| USHORT format; /* Format identifier */
|
| LigatureSubstFormat1 format1;
|
| @@ -757,8 +961,10 @@ struct ExtensionSubst : Extension
|
| }
|
|
|
| inline void closure (hb_closure_context_t *c) const;
|
| - inline bool would_apply (hb_codepoint_t glyph_id) const;
|
| - inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) const;
|
| +
|
| + inline const Coverage &get_coverage (void) const;
|
| +
|
| + inline bool would_apply (hb_would_apply_context_t *c) const;
|
|
|
| inline bool apply (hb_apply_context_t *c) const;
|
|
|
| @@ -799,6 +1005,11 @@ struct ReverseChainSingleSubstFormat1
|
| }
|
| }
|
|
|
| + inline const Coverage &get_coverage (void) const
|
| + {
|
| + return this+coverage;
|
| + }
|
| +
|
| inline bool apply (hb_apply_context_t *c) const
|
| {
|
| TRACE_APPLY ();
|
| @@ -819,7 +1030,7 @@ struct ReverseChainSingleSubstFormat1
|
| match_coverage, this,
|
| 1))
|
| {
|
| - c->buffer->cur().codepoint = substitute[index];
|
| + c->replace_glyph_inplace (substitute[index]);
|
| c->buffer->idx--; /* Reverse! */
|
| return TRACE_RETURN (true);
|
| }
|
| @@ -838,7 +1049,7 @@ struct ReverseChainSingleSubstFormat1
|
| return TRACE_RETURN (substitute.sanitize (c));
|
| }
|
|
|
| - private:
|
| + protected:
|
| USHORT format; /* Format identifier--format = 1 */
|
| OffsetTo<Coverage>
|
| coverage; /* Offset to Coverage table--from
|
| @@ -873,6 +1084,14 @@ struct ReverseChainSingleSubst
|
| }
|
| }
|
|
|
| + inline const Coverage &get_coverage (void) const
|
| + {
|
| + switch (u.format) {
|
| + case 1: return u.format1.get_coverage ();
|
| + default:return Null(Coverage);
|
| + }
|
| + }
|
| +
|
| inline bool apply (hb_apply_context_t *c) const
|
| {
|
| TRACE_APPLY ();
|
| @@ -891,7 +1110,7 @@ struct ReverseChainSingleSubst
|
| }
|
| }
|
|
|
| - private:
|
| + protected:
|
| union {
|
| USHORT format; /* Format identifier */
|
| ReverseChainSingleSubstFormat1 format1;
|
| @@ -928,7 +1147,7 @@ struct SubstLookupSubTable
|
| case Multiple: u.multiple.closure (c); break;
|
| case Alternate: u.alternate.closure (c); break;
|
| case Ligature: u.ligature.closure (c); break;
|
| - case Context: u.c.closure (c); break;
|
| + case Context: u.context.closure (c); break;
|
| case ChainContext: u.chainContext.closure (c); break;
|
| case Extension: u.extension.closure (c); break;
|
| case ReverseChainSingle: u.reverseChainContextSingle.closure (c); break;
|
| @@ -936,24 +1155,43 @@ struct SubstLookupSubTable
|
| }
|
| }
|
|
|
| - inline bool would_apply (hb_codepoint_t glyph_id,
|
| - unsigned int lookup_type) const
|
| + inline const Coverage &get_coverage (unsigned int lookup_type) const
|
| {
|
| switch (lookup_type) {
|
| - case Single: return u.single.would_apply (glyph_id);
|
| - case Multiple: return u.multiple.would_apply (glyph_id);
|
| - case Alternate: return u.alternate.would_apply (glyph_id);
|
| - case Extension: return u.extension.would_apply (glyph_id);
|
| - default: return false;
|
| + case Single: return u.single.get_coverage ();
|
| + case Multiple: return u.multiple.get_coverage ();
|
| + case Alternate: return u.alternate.get_coverage ();
|
| + case Ligature: return u.ligature.get_coverage ();
|
| + case Context: return u.context.get_coverage ();
|
| + case ChainContext: return u.chainContext.get_coverage ();
|
| + case Extension: return u.extension.get_coverage ();
|
| + case ReverseChainSingle: return u.reverseChainContextSingle.get_coverage ();
|
| + default: return Null(Coverage);
|
| }
|
| }
|
| - inline bool would_apply (hb_codepoint_t first,
|
| - hb_codepoint_t second,
|
| +
|
| + inline bool would_apply (hb_would_apply_context_t *c,
|
| unsigned int lookup_type) const
|
| {
|
| + TRACE_WOULD_APPLY ();
|
| + if (get_coverage (lookup_type).get_coverage (c->glyphs[0]) == NOT_COVERED) return false;
|
| + if (c->len == 1) {
|
| + switch (lookup_type) {
|
| + case Single:
|
| + case Multiple:
|
| + case Alternate:
|
| + case ReverseChainSingle:
|
| + return true;
|
| + }
|
| + }
|
| +
|
| + /* Only need to look further for lookups that support substitutions
|
| + * of input longer than 1. */
|
| switch (lookup_type) {
|
| - case Ligature: return u.ligature.would_apply (first, second);
|
| - case Extension: return u.extension.would_apply (first, second);
|
| + case Ligature: return u.ligature.would_apply (c);
|
| + case Context: return u.context.would_apply (c);
|
| + case ChainContext: return u.chainContext.would_apply (c);
|
| + case Extension: return u.extension.would_apply (c);
|
| default: return false;
|
| }
|
| }
|
| @@ -966,7 +1204,7 @@ struct SubstLookupSubTable
|
| case Multiple: return TRACE_RETURN (u.multiple.apply (c));
|
| case Alternate: return TRACE_RETURN (u.alternate.apply (c));
|
| case Ligature: return TRACE_RETURN (u.ligature.apply (c));
|
| - case Context: return TRACE_RETURN (u.c.apply (c));
|
| + case Context: return TRACE_RETURN (u.context.apply (c));
|
| case ChainContext: return TRACE_RETURN (u.chainContext.apply (c));
|
| case Extension: return TRACE_RETURN (u.extension.apply (c));
|
| case ReverseChainSingle: return TRACE_RETURN (u.reverseChainContextSingle.apply (c));
|
| @@ -976,12 +1214,14 @@ struct SubstLookupSubTable
|
|
|
| inline bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) {
|
| TRACE_SANITIZE ();
|
| + if (!u.header.sub_format.sanitize (c))
|
| + return TRACE_RETURN (false);
|
| switch (lookup_type) {
|
| case Single: return TRACE_RETURN (u.single.sanitize (c));
|
| case Multiple: return TRACE_RETURN (u.multiple.sanitize (c));
|
| case Alternate: return TRACE_RETURN (u.alternate.sanitize (c));
|
| case Ligature: return TRACE_RETURN (u.ligature.sanitize (c));
|
| - case Context: return TRACE_RETURN (u.c.sanitize (c));
|
| + case Context: return TRACE_RETURN (u.context.sanitize (c));
|
| case ChainContext: return TRACE_RETURN (u.chainContext.sanitize (c));
|
| case Extension: return TRACE_RETURN (u.extension.sanitize (c));
|
| case ReverseChainSingle: return TRACE_RETURN (u.reverseChainContextSingle.sanitize (c));
|
| @@ -989,20 +1229,22 @@ struct SubstLookupSubTable
|
| }
|
| }
|
|
|
| - private:
|
| + protected:
|
| union {
|
| - USHORT sub_format;
|
| + struct {
|
| + USHORT sub_format;
|
| + } header;
|
| SingleSubst single;
|
| MultipleSubst multiple;
|
| AlternateSubst alternate;
|
| LigatureSubst ligature;
|
| - ContextSubst c;
|
| + ContextSubst context;
|
| ChainContextSubst chainContext;
|
| ExtensionSubst extension;
|
| ReverseChainSingleSubst reverseChainContextSingle;
|
| } u;
|
| public:
|
| - DEFINE_SIZE_UNION (2, sub_format);
|
| + DEFINE_SIZE_UNION (2, header.sub_format);
|
| };
|
|
|
|
|
| @@ -1030,21 +1272,28 @@ struct SubstLookup : Lookup
|
| get_subtable (i).closure (c, lookup_type);
|
| }
|
|
|
| - inline bool would_apply (hb_codepoint_t glyph_id) const
|
| + template <typename set_t>
|
| + inline void add_coverage (set_t *glyphs) const
|
| {
|
| - unsigned int lookup_type = get_type ();
|
| + const Coverage *last = NULL;
|
| unsigned int count = get_subtable_count ();
|
| - for (unsigned int i = 0; i < count; i++)
|
| - if (get_subtable (i).would_apply (glyph_id, lookup_type))
|
| - return true;
|
| - return false;
|
| + for (unsigned int i = 0; i < count; i++) {
|
| + const Coverage *c = &get_subtable (i).get_coverage (get_type ());
|
| + if (c != last) {
|
| + c->add_coverage (glyphs);
|
| + last = c;
|
| + }
|
| + }
|
| }
|
| - inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) const
|
| +
|
| + inline bool would_apply (hb_would_apply_context_t *c, const hb_set_digest_t *digest) const
|
| {
|
| + if (unlikely (!c->len)) return false;
|
| + if (!digest->may_have (c->glyphs[0])) return false;
|
| unsigned int lookup_type = get_type ();
|
| unsigned int count = get_subtable_count ();
|
| for (unsigned int i = 0; i < count; i++)
|
| - if (get_subtable (i).would_apply (first, second, lookup_type))
|
| + if (get_subtable (i).would_apply (c, lookup_type))
|
| return true;
|
| return false;
|
| }
|
| @@ -1053,23 +1302,9 @@ struct SubstLookup : Lookup
|
| {
|
| unsigned int lookup_type = get_type ();
|
|
|
| - if (!_hb_ot_layout_check_glyph_property (c->face, &c->buffer->cur(), c->lookup_props, &c->property))
|
| + if (!c->check_glyph_property (&c->buffer->cur(), c->lookup_props, &c->property))
|
| return false;
|
|
|
| - if (unlikely (lookup_type == SubstLookupSubTable::Extension))
|
| - {
|
| - /* The spec says all subtables should have the same type.
|
| - * This is specially important if one has a reverse type!
|
| - *
|
| - * This is rather slow to do this here for every glyph,
|
| - * but it's easiest, and who uses extension lookups anyway?!*/
|
| - 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 false;
|
| - }
|
| -
|
| unsigned int count = get_subtable_count ();
|
| for (unsigned int i = 0; i < count; i++)
|
| if (get_subtable (i).apply (c, lookup_type))
|
| @@ -1078,11 +1313,11 @@ struct SubstLookup : Lookup
|
| return false;
|
| }
|
|
|
| - inline bool apply_string (hb_apply_context_t *c) const
|
| + inline bool apply_string (hb_apply_context_t *c, const hb_set_digest_t *digest) const
|
| {
|
| bool ret = false;
|
|
|
| - if (unlikely (!c->buffer->len))
|
| + if (unlikely (!c->buffer->len || !c->lookup_mask))
|
| return false;
|
|
|
| c->set_lookup (*this);
|
| @@ -1092,13 +1327,15 @@ struct SubstLookup : Lookup
|
| /* in/out forward substitution */
|
| c->buffer->clear_output ();
|
| c->buffer->idx = 0;
|
| +
|
| while (c->buffer->idx < c->buffer->len)
|
| {
|
| - if ((c->buffer->cur().mask & c->lookup_mask) && apply_once (c))
|
| + if ((c->buffer->cur().mask & c->lookup_mask) &&
|
| + digest->may_have (c->buffer->cur().codepoint) &&
|
| + apply_once (c))
|
| ret = true;
|
| else
|
| c->buffer->next_glyph ();
|
| -
|
| }
|
| if (ret)
|
| c->buffer->swap_buffers ();
|
| @@ -1109,7 +1346,9 @@ struct SubstLookup : Lookup
|
| c->buffer->idx = c->buffer->len - 1;
|
| do
|
| {
|
| - if ((c->buffer->cur().mask & c->lookup_mask) && apply_once (c))
|
| + if ((c->buffer->cur().mask & c->lookup_mask) &&
|
| + digest->may_have (c->buffer->cur().codepoint) &&
|
| + apply_once (c))
|
| ret = true;
|
| else
|
| c->buffer->idx--;
|
| @@ -1121,11 +1360,85 @@ struct SubstLookup : Lookup
|
| return ret;
|
| }
|
|
|
| - inline bool sanitize (hb_sanitize_context_t *c) {
|
| + private:
|
| + inline SubstLookupSubTable& serialize_subtable (hb_serialize_context_t *c,
|
| + unsigned int i)
|
| + { return CastR<OffsetArrayOf<SubstLookupSubTable> > (subTable)[i].serialize (c, this); }
|
| + public:
|
| +
|
| + inline bool serialize_single (hb_serialize_context_t *c,
|
| + uint32_t lookup_props,
|
| + Supplier<GlyphID> &glyphs,
|
| + Supplier<GlyphID> &substitutes,
|
| + unsigned int num_glyphs)
|
| + {
|
| + TRACE_SERIALIZE ();
|
| + if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Single, lookup_props, 1))) return TRACE_RETURN (false);
|
| + return TRACE_RETURN (serialize_subtable (c, 0).u.single.serialize (c, glyphs, substitutes, num_glyphs));
|
| + }
|
| +
|
| + 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)
|
| + {
|
| + TRACE_SERIALIZE ();
|
| + if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Multiple, lookup_props, 1))) return TRACE_RETURN (false);
|
| + return TRACE_RETURN (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<GlyphID> &glyphs,
|
| + Supplier<unsigned int> &alternate_len_list,
|
| + unsigned int num_glyphs,
|
| + Supplier<GlyphID> &alternate_glyphs_list)
|
| + {
|
| + TRACE_SERIALIZE ();
|
| + if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Alternate, lookup_props, 1))) return TRACE_RETURN (false);
|
| + return TRACE_RETURN (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 */)
|
| + {
|
| + TRACE_SERIALIZE ();
|
| + if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Ligature, lookup_props, 1))) return TRACE_RETURN (false);
|
| + return TRACE_RETURN (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));
|
| + }
|
| +
|
| + inline bool sanitize (hb_sanitize_context_t *c)
|
| + {
|
| TRACE_SANITIZE ();
|
| if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false);
|
| OffsetArrayOf<SubstLookupSubTable> &list = CastR<OffsetArrayOf<SubstLookupSubTable> > (subTable);
|
| - return TRACE_RETURN (list.sanitize (c, this, get_type ()));
|
| + if (unlikely (!list.sanitize (c, this, get_type ()))) return TRACE_RETURN (false);
|
| +
|
| + if (unlikely (get_type () == SubstLookupSubTable::Extension))
|
| + {
|
| + /* The spec says all subtables of an Extension lookup should
|
| + * have the same type. This is specially important if one has
|
| + * a reverse type!
|
| + *
|
| + * We just check that they are all either forward, or reverse. */
|
| + 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_RETURN (false);
|
| + }
|
| + return TRACE_RETURN (true);
|
| }
|
| };
|
|
|
| @@ -1142,11 +1455,12 @@ struct GSUB : GSUBGPOS
|
| inline const SubstLookup& get_lookup (unsigned int i) const
|
| { return CastR<SubstLookup> (GSUBGPOS::get_lookup (i)); }
|
|
|
| - inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup_index) const
|
| - { return get_lookup (lookup_index).apply_string (c); }
|
| + template <typename set_t>
|
| + inline void add_coverage (set_t *glyphs, unsigned int lookup_index) const
|
| + { get_lookup (lookup_index).add_coverage (glyphs); }
|
|
|
| - static inline void substitute_start (hb_buffer_t *buffer);
|
| - static inline void substitute_finish (hb_buffer_t *buffer);
|
| + static inline void substitute_start (hb_font_t *font, hb_buffer_t *buffer);
|
| + static inline void substitute_finish (hb_font_t *font, hb_buffer_t *buffer);
|
|
|
| inline void closure_lookup (hb_closure_context_t *c,
|
| unsigned int lookup_index) const
|
| @@ -1164,19 +1478,22 @@ struct GSUB : GSUBGPOS
|
|
|
|
|
| void
|
| -GSUB::substitute_start (hb_buffer_t *buffer)
|
| +GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer)
|
| {
|
| - HB_BUFFER_ALLOCATE_VAR (buffer, props_cache);
|
| + HB_BUFFER_ALLOCATE_VAR (buffer, glyph_props);
|
| HB_BUFFER_ALLOCATE_VAR (buffer, lig_props);
|
| HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
|
|
|
| + const GDEF &gdef = *hb_ot_layout_from_face (font->face)->gdef;
|
| unsigned int count = buffer->len;
|
| - for (unsigned int i = 0; i < count; i++)
|
| - buffer->info[i].props_cache() = buffer->info[i].lig_props() = buffer->info[i].syllable() = 0;
|
| + for (unsigned int i = 0; i < count; i++) {
|
| + buffer->info[i].lig_props() = buffer->info[i].syllable() = 0;
|
| + buffer->info[i].glyph_props() = gdef.get_glyph_props (buffer->info[i].codepoint);
|
| + }
|
| }
|
|
|
| void
|
| -GSUB::substitute_finish (hb_buffer_t *buffer HB_UNUSED)
|
| +GSUB::substitute_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSED)
|
| {
|
| }
|
|
|
| @@ -1188,14 +1505,14 @@ inline void ExtensionSubst::closure (hb_closure_context_t *c) const
|
| get_subtable ().closure (c, get_type ());
|
| }
|
|
|
| -inline bool ExtensionSubst::would_apply (hb_codepoint_t glyph_id) const
|
| +inline const Coverage & ExtensionSubst::get_coverage (void) const
|
| {
|
| - return get_subtable ().would_apply (glyph_id, get_type ());
|
| + return get_subtable ().get_coverage (get_type ());
|
| }
|
|
|
| -inline bool ExtensionSubst::would_apply (hb_codepoint_t first, hb_codepoint_t second) const
|
| +inline bool ExtensionSubst::would_apply (hb_would_apply_context_t *c) const
|
| {
|
| - return get_subtable ().would_apply (first, second, get_type ());
|
| + return get_subtable ().would_apply (c, get_type ());
|
| }
|
|
|
| inline bool ExtensionSubst::apply (hb_apply_context_t *c) const
|
| @@ -1223,7 +1540,7 @@ inline bool ExtensionSubst::is_reverse (void) const
|
|
|
| static inline void closure_lookup (hb_closure_context_t *c, unsigned int lookup_index)
|
| {
|
| - const GSUB &gsub = *(c->face->ot_layout->gsub);
|
| + const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub);
|
| const SubstLookup &l = gsub.get_lookup (lookup_index);
|
|
|
| if (unlikely (c->nesting_level_left == 0))
|
| @@ -1236,7 +1553,7 @@ static inline void closure_lookup (hb_closure_context_t *c, unsigned int lookup_
|
|
|
| static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup_index)
|
| {
|
| - const GSUB &gsub = *(c->face->ot_layout->gsub);
|
| + const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub);
|
| const SubstLookup &l = gsub.get_lookup (lookup_index);
|
|
|
| if (unlikely (c->nesting_level_left == 0))
|
| @@ -1249,5 +1566,7 @@ static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup
|
| }
|
|
|
|
|
| +} // namespace OT
|
| +
|
|
|
| #endif /* HB_OT_LAYOUT_GSUB_TABLE_HH */
|
|
|