diff --git a/src/hb-aat-layout-common-private.hh b/src/hb-aat-layout-common-private.hh index 2462701c7..04007db34 100644 --- a/src/hb-aat-layout-common-private.hh +++ b/src/hb-aat-layout-common-private.hh @@ -605,6 +605,57 @@ struct StateTable DEFINE_SIZE_UNION (2, format); }; +template +struct StateTableDriver +{ + inline StateTableDriver (const StateTable &machine_, + hb_buffer_t *buffer_, + hb_face_t *face_) : + machine (machine_), + buffer (buffer_), + num_glyphs (face_->get_num_glyphs ()), + state (0), + last_zero (0) {} + + template + inline void drive (context_t *c) + { + hb_glyph_info_t *info = buffer->info; + unsigned int count = buffer->len; + + for (buffer->idx = 0; buffer->idx <= count; buffer->idx++) + { + if (!state) + last_zero = buffer->idx; + + unsigned int klass = buffer->idx < count ? + machine.get_class (info[buffer->idx].codepoint, num_glyphs) : + 0 /* End of text */; + const Entry *entry = machine.get_entryZ (state, klass); + if (unlikely (!entry)) + break; + + c->transition (this, entry); + + if (entry->flags & context_t::Flags::DontAdvance) + buffer->idx--; /* TODO Detect infinite loop. */ + + state = entry->newState; + } + + /* XXX finish if not in-place */ + } + + public: + const StateTable &machine; + hb_buffer_t *buffer; + + unsigned int num_glyphs; + + unsigned int state; + unsigned int last_zero; +}; + } /* namespace AAT */ diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 95f4245de..bfe239e47 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -176,14 +176,6 @@ struct RearrangementSubtable struct ContextualSubtable { - enum Flags { - SetMark = 0x8000, /* If set, make the current glyph the marked glyph. */ - DontAdvance = 0x4000, /* If set, don't advance to the next glyph before - * going to the new state. */ - Reserved = 0x3FFF, /* These bits are reserved and should be set to 0. */ - }; - - /* XXX the following is different in mort: it's directly index to sublookups. */ struct EntryData { HBUINT16 markIndex; /* Index of the substitution table for the @@ -194,50 +186,40 @@ struct ContextualSubtable DEFINE_SIZE_STATIC (4); }; - inline bool apply (hb_apply_context_t *c) const + struct driver_context_t { - TRACE_APPLY (this); - - bool ret = false; - unsigned int num_glyphs = c->face->get_num_glyphs (); - - const UnsizedOffsetListOf, HBUINT32> &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++) + enum Flags { + SetMark = 0x8000, /* If set, make the current glyph the marked glyph. */ + DontAdvance = 0x4000, /* If set, don't advance to the next glyph before + * going to the new state. */ + Reserved = 0x3FFF, /* These bits are reserved and should be set to 0. */ + }; + + inline driver_context_t (const ContextualSubtable *table) : + ret (false), + mark (0), + last_zero_before_mark (0), + subs (table+table->substitutionTables) {} + + inline void transition (StateTableDriver *driver, + const Entry *entry) { - 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_entryZ (state, klass); - if (unlikely (!entry)) - break; + hb_buffer_t *buffer = driver->buffer; - unsigned int flags = entry->flags; - - if (flags & SetMark) + if (entry->flags & SetMark) { - mark = i; - last_zero_before_mark = last_zero; + mark = buffer->idx; + last_zero_before_mark = driver->last_zero; } if (entry->data.markIndex != 0xFFFF) { const Lookup &lookup = subs[entry->data.markIndex]; - const GlyphID *replacement = lookup.get_value (info[mark].codepoint, num_glyphs); + hb_glyph_info_t *info = buffer->info; + const GlyphID *replacement = lookup.get_value (info[mark].codepoint, driver->num_glyphs); if (replacement) { - c->buffer->unsafe_to_break (last_zero_before_mark, MIN (i + 1, count)); + buffer->unsafe_to_break (last_zero_before_mark, MIN (buffer->idx + 1, buffer->len)); info[mark].codepoint = *replacement; ret = true; } @@ -245,22 +227,35 @@ struct ContextualSubtable if (entry->data.currentIndex != 0xFFFF) { const Lookup &lookup = subs[entry->data.currentIndex]; - const GlyphID *replacement = lookup.get_value (info[i].codepoint, num_glyphs); + hb_glyph_info_t *info = buffer->info; + const GlyphID *replacement = lookup.get_value (info[buffer->idx].codepoint, driver->num_glyphs); if (replacement) { - c->buffer->unsafe_to_break (last_zero, MIN (i + 1, count)); - info[i].codepoint = *replacement; + buffer->unsafe_to_break (driver->last_zero, MIN (buffer->idx + 1, buffer->len)); + info[buffer->idx].codepoint = *replacement; ret = true; } } + } - if (flags & DontAdvance) - i--; /* TODO Detect infinite loop. */ + public: + bool ret; + private: + unsigned int mark; + unsigned int last_zero_before_mark; + const UnsizedOffsetListOf, HBUINT32> &subs; + }; - state = entry->newState; - } + inline bool apply (hb_apply_context_t *c) const + { + TRACE_APPLY (this); - return_trace (ret); + driver_context_t dc (this); + + StateTableDriver driver (machine, c->buffer, c->face); + driver.drive (&dc); + + return_trace (dc.ret); } inline bool sanitize (hb_sanitize_context_t *c) const