diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 6c9c51544..80164af03 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -200,8 +200,70 @@ struct ContextualSubtable inline bool apply (hb_apply_context_t *c) const { TRACE_APPLY (this); - /* TODO */ - return_trace (false); + + bool ret = false; + unsigned int num_glyphs = c->face->get_num_glyphs (); + + const UnsizedOffsetListOf, HBUINT> &subs = this+substitutionTables; + + unsigned int state = 0; + unsigned int last_zero = 0; + unsigned int last_zero_before_mark = 0; + unsigned int mark = 0; + + hb_glyph_info_t *info = c->buffer->info; + unsigned int count = c->buffer->len; + + for (unsigned int i = 0; i <= count; i++) + { + if (!state) + last_zero = i; + + unsigned int klass = i < count ? + machine.get_class (info[i].codepoint, num_glyphs) : + 0 /* End of text */; + const Entry *entry = machine.get_entry (state, klass); + if (unlikely (!entry)) + break; + + unsigned int flags = entry->flags; + + if (flags & SetMark) + { + mark = i; + last_zero_before_mark = last_zero; + } + + if (entry->data.markIndex != 0xFFFF) + { + const Lookup &lookup = subs[entry->data.markIndex]; // XXX bounds + const GlyphID *replacement = lookup.get_value (info[mark].codepoint, num_glyphs); + if (replacement) + { + c->buffer->unsafe_to_break (last_zero_before_mark, MIN (i + 1, count)); + info[mark].codepoint = *replacement; + ret = true; + } + } + if (entry->data.currentIndex != 0xFFFF) + { + const Lookup &lookup = subs[entry->data.currentIndex]; // XXX bounds + const GlyphID *replacement = lookup.get_value (info[i].codepoint, num_glyphs); + if (replacement) + { + c->buffer->unsafe_to_break (last_zero, MIN (i + 1, count)); + info[i].codepoint = *replacement; + ret = true; + } + } + + if (false/* XXX */ && flags & DontAdvance) + i--; /* XXX Detect infinite loop. */ + + state = entry->newState; + } + + return_trace (ret); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -233,7 +295,7 @@ struct LigatureSubtable { TRACE_SANITIZE (this); /* TODO */ - return_trace (false); + return_trace (true); } }; @@ -288,7 +350,7 @@ struct InsertionSubtable { TRACE_SANITIZE (this); /* TODO */ - return_trace (false); + return_trace (true); } };