[subset] optimize glyph closure method: step1
Previous GSUB glyph closure is done by recursively visiting all reachable lookup tables that apply to any glyphs in the current/input glyph set, but actually only the glyphs that the parent lookup can apply the recursion to can participate in recursing the lookup. This is step 1 for glyph closure optimization: 1. Add stack of currently active glyph set pointers into hb_closure_context_t 2. Update closure() method in simple GSUB tables to use this stack in order not to change current glyph set at different stages of recursion 3. Add function may_have_non_1to1() to GSUB tables
This commit is contained in:
parent
5f4c321d4a
commit
b4fc593c3c
|
@ -46,14 +46,28 @@ struct SingleSubstFormat1
|
|||
bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
bool may_have_non_1to1 () const
|
||||
{ return false; }
|
||||
|
||||
void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
unsigned d = deltaGlyphID;
|
||||
hb_set_t *active_parent_glyphs;
|
||||
|
||||
if (c->active_glyphs_stack.length >= 1)
|
||||
{
|
||||
active_parent_glyphs = c->parent_active_glyphs ();
|
||||
} else
|
||||
{
|
||||
active_parent_glyphs = c->glyphs;
|
||||
}
|
||||
|
||||
+ hb_iter (this+coverage)
|
||||
| hb_filter (*c->glyphs)
|
||||
| hb_filter (active_parent_glyphs)
|
||||
| hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; })
|
||||
| hb_sink (c->output)
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
@ -147,13 +161,27 @@ struct SingleSubstFormat2
|
|||
bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
bool may_have_non_1to1 () const
|
||||
{ return false; }
|
||||
|
||||
void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
hb_set_t *active_parent_glyphs;
|
||||
|
||||
if (c->active_glyphs_stack.length >= 1)
|
||||
{
|
||||
active_parent_glyphs = c->parent_active_glyphs ();
|
||||
} else
|
||||
{
|
||||
active_parent_glyphs = c->glyphs;
|
||||
}
|
||||
|
||||
+ hb_zip (this+coverage, substitute)
|
||||
| hb_filter (*c->glyphs, hb_first)
|
||||
| hb_filter (active_parent_glyphs, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_sink (c->output)
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
@ -388,14 +416,28 @@ struct MultipleSubstFormat1
|
|||
bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
bool may_have_non_1to1 () const
|
||||
{ return true; }
|
||||
|
||||
void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
hb_set_t *active_parent_glyphs;
|
||||
|
||||
if (c->active_glyphs_stack.length >= 1)
|
||||
{
|
||||
active_parent_glyphs = c->parent_active_glyphs ();
|
||||
} else
|
||||
{
|
||||
active_parent_glyphs = c->glyphs;
|
||||
}
|
||||
|
||||
+ hb_zip (this+coverage, sequence)
|
||||
| hb_filter (*c->glyphs, hb_first)
|
||||
| hb_filter (active_parent_glyphs, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_apply ([c] (const Sequence &_) { _.closure (c); })
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
@ -615,14 +657,28 @@ struct AlternateSubstFormat1
|
|||
bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
bool may_have_non_1to1 () const
|
||||
{ return false; }
|
||||
|
||||
void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
hb_set_t *active_parent_glyphs;
|
||||
|
||||
if (c->active_glyphs_stack.length >= 1)
|
||||
{
|
||||
active_parent_glyphs = c->parent_active_glyphs ();
|
||||
} else
|
||||
{
|
||||
active_parent_glyphs = c->glyphs;
|
||||
}
|
||||
|
||||
+ hb_zip (this+coverage, alternateSet)
|
||||
| hb_filter (c->glyphs, hb_first)
|
||||
| hb_filter (active_parent_glyphs, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_apply ([c] (const AlternateSet &_) { _.closure (c); })
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
@ -986,14 +1042,28 @@ struct LigatureSubstFormat1
|
|||
;
|
||||
}
|
||||
|
||||
bool may_have_non_1to1 () const
|
||||
{ return true; }
|
||||
|
||||
void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
hb_set_t *active_parent_glyphs;
|
||||
|
||||
if (c->active_glyphs_stack.length >= 1)
|
||||
{
|
||||
active_parent_glyphs = c->parent_active_glyphs ();
|
||||
} else
|
||||
{
|
||||
active_parent_glyphs = c->glyphs;
|
||||
}
|
||||
|
||||
+ hb_zip (this+coverage, ligatureSet)
|
||||
| hb_filter (*c->glyphs, hb_first)
|
||||
| hb_filter (active_parent_glyphs, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_apply ([c] (const LigatureSet &_) { _.closure (c); })
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
@ -1174,15 +1244,27 @@ struct ReverseChainSingleSubstFormat1
|
|||
return true;
|
||||
}
|
||||
|
||||
bool may_have_non_1to1 () const
|
||||
{ return false; }
|
||||
|
||||
void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
if (!intersects (c->glyphs)) return;
|
||||
|
||||
hb_set_t *active_parent_glyphs;
|
||||
if (c->active_glyphs_stack.length >= 1)
|
||||
{
|
||||
active_parent_glyphs = c->parent_active_glyphs ();
|
||||
} else
|
||||
{
|
||||
active_parent_glyphs = c->glyphs;
|
||||
}
|
||||
|
||||
const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
|
||||
const ArrayOf<HBGlyphID> &substitute = StructAfter<ArrayOf<HBGlyphID>> (lookahead);
|
||||
|
||||
+ hb_zip (this+coverage, substitute)
|
||||
| hb_filter (*c->glyphs, hb_first)
|
||||
| hb_filter (active_parent_glyphs, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_sink (c->output)
|
||||
;
|
||||
|
@ -1388,6 +1470,12 @@ struct SubstLookup : Lookup
|
|||
return lookup_type_is_reverse (type);
|
||||
}
|
||||
|
||||
bool may_have_non_1to1 () const
|
||||
{
|
||||
hb_have_non_1to1_context_t c;
|
||||
return dispatch (&c);
|
||||
}
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
|
|
|
@ -55,6 +55,15 @@ struct hb_intersects_context_t :
|
|||
glyphs (glyphs_) {}
|
||||
};
|
||||
|
||||
struct hb_have_non_1to1_context_t :
|
||||
hb_dispatch_context_t<hb_have_non_1to1_context_t, bool>
|
||||
{
|
||||
template <typename T>
|
||||
return_t dispatch (const T &obj) { return obj.may_have_non_1to1 (); }
|
||||
static return_t default_return_value () { return false; }
|
||||
bool stop_sublookup_iteration (return_t r) const { return r; }
|
||||
};
|
||||
|
||||
struct hb_closure_context_t :
|
||||
hb_dispatch_context_t<hb_closure_context_t>
|
||||
{
|
||||
|
@ -96,9 +105,29 @@ struct hb_closure_context_t :
|
|||
return done_lookups->get (lookup_index) == glyphs->get_population ();
|
||||
}
|
||||
|
||||
hb_set_t* parent_active_glyphs ()
|
||||
{
|
||||
return active_glyphs_stack.tail ();
|
||||
}
|
||||
|
||||
void push_cur_active_glyphs (hb_set_t* cur_active_glyph_set)
|
||||
{
|
||||
active_glyphs_stack.push (cur_active_glyph_set);
|
||||
}
|
||||
|
||||
bool pop_cur_done_glyphs ()
|
||||
{
|
||||
if (active_glyphs_stack.length < 1)
|
||||
return false;
|
||||
|
||||
active_glyphs_stack.pop ();
|
||||
return true;
|
||||
}
|
||||
|
||||
hb_face_t *face;
|
||||
hb_set_t *glyphs;
|
||||
hb_set_t output[1];
|
||||
hb_vector_t<hb_set_t *> active_glyphs_stack;
|
||||
recurse_func_t recurse_func;
|
||||
unsigned int nesting_level_left;
|
||||
|
||||
|
@ -112,7 +141,9 @@ struct hb_closure_context_t :
|
|||
nesting_level_left (nesting_level_left_),
|
||||
done_lookups (done_lookups_),
|
||||
lookup_count (0)
|
||||
{}
|
||||
{
|
||||
push_cur_active_glyphs (glyphs_);
|
||||
}
|
||||
|
||||
~hb_closure_context_t () { flush (); }
|
||||
|
||||
|
@ -123,6 +154,8 @@ struct hb_closure_context_t :
|
|||
hb_set_del_range (output, face->get_num_glyphs (), hb_set_get_max (output)); /* Remove invalid glyphs. */
|
||||
hb_set_union (glyphs, output);
|
||||
hb_set_clear (output);
|
||||
active_glyphs_stack.pop ();
|
||||
active_glyphs_stack.fini ();
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -1151,8 +1184,11 @@ static inline void recurse_lookups (context_t *c,
|
|||
unsigned int lookupCount,
|
||||
const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */)
|
||||
{
|
||||
hb_set_t *chaos = hb_set_create ();
|
||||
for (unsigned int i = 0; i < lookupCount; i++)
|
||||
c->recurse (lookupRecord[i].lookupListIndex);
|
||||
|
||||
hb_set_destroy (chaos);
|
||||
}
|
||||
|
||||
static inline bool apply_lookup (hb_ot_apply_context_t *c,
|
||||
|
@ -1631,6 +1667,9 @@ struct ContextFormat1
|
|||
;
|
||||
}
|
||||
|
||||
bool may_have_non_1to1 () const
|
||||
{ return true; }
|
||||
|
||||
void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
struct ContextClosureLookupContext lookup_context = {
|
||||
|
@ -1774,6 +1813,9 @@ struct ContextFormat2
|
|||
;
|
||||
}
|
||||
|
||||
bool may_have_non_1to1 () const
|
||||
{ return true; }
|
||||
|
||||
void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
if (!(this+coverage).intersects (c->glyphs))
|
||||
|
@ -1949,6 +1991,9 @@ struct ContextFormat3
|
|||
lookup_context);
|
||||
}
|
||||
|
||||
bool may_have_non_1to1 () const
|
||||
{ return true; }
|
||||
|
||||
void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
if (!(this+coverageZ[0]).intersects (c->glyphs))
|
||||
|
@ -2565,6 +2610,9 @@ struct ChainContextFormat1
|
|||
;
|
||||
}
|
||||
|
||||
bool may_have_non_1to1 () const
|
||||
{ return true; }
|
||||
|
||||
void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
struct ChainContextClosureLookupContext lookup_context = {
|
||||
|
@ -2709,6 +2757,10 @@ struct ChainContextFormat2
|
|||
| hb_any
|
||||
;
|
||||
}
|
||||
|
||||
bool may_have_non_1to1 () const
|
||||
{ return true; }
|
||||
|
||||
void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
if (!(this+coverage).intersects (c->glyphs))
|
||||
|
@ -2941,6 +2993,9 @@ struct ChainContextFormat3
|
|||
lookup_context);
|
||||
}
|
||||
|
||||
bool may_have_non_1to1 () const
|
||||
{ return true; }
|
||||
|
||||
void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
|
||||
|
|
Loading…
Reference in New Issue