diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 9fc88f6c8..cdffc6172 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -902,20 +902,79 @@ struct GPOSProxy }; -template +struct hb_get_subtables_context_t : + OT::hb_dispatch_context_t +{ + template + static inline bool apply_to (const void *obj, OT::hb_apply_context_t *c) + { + const Type *typed_obj = (const Type *) obj; + return typed_obj->apply (c); + } + + typedef bool (*hb_apply_func_t) (const void *obj, OT::hb_apply_context_t *c); + + struct hb_applicable_t + { + inline void init (const void *obj_, hb_apply_func_t apply_func_) + { + obj = obj_; + apply_func = apply_func_; + } + + inline bool apply (OT::hb_apply_context_t *c) const { return apply_func (obj, c); } + + private: + const void *obj; + hb_apply_func_t apply_func; + }; + + typedef hb_auto_array_t array_t; + + /* Dispatch interface. */ + inline const char *get_name (void) { return "GET_SUBTABLES"; } + template + inline return_t dispatch (const T &obj) + { + hb_applicable_t *entry = array.push(); + if (likely (entry)) + entry->init (&obj, apply_to); + return HB_VOID; + } + static return_t default_return_value (void) { return HB_VOID; } + bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; } + + hb_get_subtables_context_t (array_t &array_) : + array (array_), + debug_depth (0) {} + + array_t &array; + unsigned int debug_depth; +}; + static inline bool apply_forward (OT::hb_apply_context_t *c, - const Obj &obj, - const hb_ot_layout_lookup_accelerator_t &accel) + const hb_ot_layout_lookup_accelerator_t &accel, + const hb_get_subtables_context_t::array_t &subtables) { bool ret = false; hb_buffer_t *buffer = c->buffer; while (buffer->idx < buffer->len && !buffer->in_error) { + bool applied = false; if (accel.may_have (buffer->cur().codepoint) && (buffer->cur().mask & c->lookup_mask) && - c->check_glyph_property (&buffer->cur(), c->lookup_props) && - obj.apply (c)) + c->check_glyph_property (&buffer->cur(), c->lookup_props)) + { + for (unsigned int i = 0; i < subtables.len; i++) + if (subtables[i].apply (c)) + { + applied = true; + break; + } + } + + if (applied) ret = true; else buffer->next_glyph (); @@ -923,11 +982,10 @@ apply_forward (OT::hb_apply_context_t *c, return ret; } -template static inline bool apply_backward (OT::hb_apply_context_t *c, - const Obj &obj, - const hb_ot_layout_lookup_accelerator_t &accel) + const hb_ot_layout_lookup_accelerator_t &accel, + const hb_get_subtables_context_t::array_t &subtables) { bool ret = false; hb_buffer_t *buffer = c->buffer; @@ -935,9 +993,15 @@ apply_backward (OT::hb_apply_context_t *c, { if (accel.may_have (buffer->cur().codepoint) && (buffer->cur().mask & c->lookup_mask) && - c->check_glyph_property (&buffer->cur(), c->lookup_props) && - obj.apply (c)) - ret = true; + c->check_glyph_property (&buffer->cur(), c->lookup_props)) + { + for (unsigned int i = 0; i < subtables.len; i++) + if (subtables[i].apply (c)) + { + ret = true; + break; + } + } /* The reverse lookup doesn't "advance" cursor (for good reason). */ buffer->idx--; @@ -946,26 +1010,6 @@ apply_backward (OT::hb_apply_context_t *c, return ret; } -struct hb_apply_forward_context_t : - OT::hb_dispatch_context_t -{ - inline const char *get_name (void) { return "APPLY_FWD"; } - template - inline return_t dispatch (const T &obj) { return apply_forward (c, obj, accel); } - static return_t default_return_value (void) { return false; } - bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return true; } - - hb_apply_forward_context_t (OT::hb_apply_context_t *c_, - const hb_ot_layout_lookup_accelerator_t &accel_) : - c (c_), - accel (accel_), - debug_depth (0) {} - - OT::hb_apply_context_t *c; - const hb_ot_layout_lookup_accelerator_t &accel; - unsigned int debug_depth; -}; - template static inline void apply_string (OT::hb_apply_context_t *c, @@ -979,6 +1023,10 @@ apply_string (OT::hb_apply_context_t *c, c->set_lookup_props (lookup.get_props ()); + hb_get_subtables_context_t::array_t subtables; + hb_get_subtables_context_t c_get_subtables (subtables); + lookup.dispatch (&c_get_subtables); + if (likely (!lookup.is_reverse ())) { /* in/out forward substitution/positioning */ @@ -987,13 +1035,7 @@ apply_string (OT::hb_apply_context_t *c, buffer->idx = 0; bool ret; - if (lookup.get_subtable_count () == 1) - { - hb_apply_forward_context_t c_forward (c, accel); - ret = lookup.dispatch (&c_forward); - } - else - ret = apply_forward (c, lookup, accel); + ret = apply_forward (c, accel, subtables); if (ret) { if (!Proxy::inplace) @@ -1009,7 +1051,7 @@ apply_string (OT::hb_apply_context_t *c, buffer->remove_output (); buffer->idx = buffer->len - 1; - apply_backward (c, lookup, accel); + apply_backward (c, accel, subtables); } }