[OT] Get list of lookup subtables once and loop through them
This speeds up shaping the Amiri font by over 15%. This was primarily needed for my work on OpenType GX, since we will be collecting only sublookups that are "active" for current font instance; but it's a nice boost in general as well. We might, in the future, collect subtables in the lookup_accel. That would also allow us to do a per-subtbale set-digest, which should speed things up some more, specially for ContextChainFormat3 lookups... Amiri, for example, contains one lookup with 53 subtables!
This commit is contained in:
parent
11441291bb
commit
3e704521f6
|
@ -902,20 +902,79 @@ struct GPOSProxy
|
|||
};
|
||||
|
||||
|
||||
template <typename Obj>
|
||||
struct hb_get_subtables_context_t :
|
||||
OT::hb_dispatch_context_t<hb_get_subtables_context_t, hb_void_t, HB_DEBUG_APPLY>
|
||||
{
|
||||
template <typename Type>
|
||||
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<hb_applicable_t> array_t;
|
||||
|
||||
/* Dispatch interface. */
|
||||
inline const char *get_name (void) { return "GET_SUBTABLES"; }
|
||||
template <typename T>
|
||||
inline return_t dispatch (const T &obj)
|
||||
{
|
||||
hb_applicable_t *entry = array.push();
|
||||
if (likely (entry))
|
||||
entry->init (&obj, apply_to<T>);
|
||||
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 <typename Obj>
|
||||
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<hb_apply_forward_context_t, bool, HB_DEBUG_APPLY>
|
||||
{
|
||||
inline const char *get_name (void) { return "APPLY_FWD"; }
|
||||
template <typename T>
|
||||
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 <typename Proxy>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue