[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
|
bool intersects (const hb_set_t *glyphs) const
|
||||||
{ return (this+coverage).intersects (glyphs); }
|
{ return (this+coverage).intersects (glyphs); }
|
||||||
|
|
||||||
|
bool may_have_non_1to1 () const
|
||||||
|
{ return false; }
|
||||||
|
|
||||||
void closure (hb_closure_context_t *c) const
|
void closure (hb_closure_context_t *c) const
|
||||||
{
|
{
|
||||||
unsigned d = deltaGlyphID;
|
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_iter (this+coverage)
|
||||||
| hb_filter (*c->glyphs)
|
| hb_filter (active_parent_glyphs)
|
||||||
| hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; })
|
| hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; })
|
||||||
| hb_sink (c->output)
|
| hb_sink (c->output)
|
||||||
;
|
;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||||
|
@ -147,13 +161,27 @@ struct SingleSubstFormat2
|
||||||
bool intersects (const hb_set_t *glyphs) const
|
bool intersects (const hb_set_t *glyphs) const
|
||||||
{ return (this+coverage).intersects (glyphs); }
|
{ return (this+coverage).intersects (glyphs); }
|
||||||
|
|
||||||
|
bool may_have_non_1to1 () const
|
||||||
|
{ return false; }
|
||||||
|
|
||||||
void closure (hb_closure_context_t *c) const
|
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_zip (this+coverage, substitute)
|
||||||
| hb_filter (*c->glyphs, hb_first)
|
| hb_filter (active_parent_glyphs, hb_first)
|
||||||
| hb_map (hb_second)
|
| hb_map (hb_second)
|
||||||
| hb_sink (c->output)
|
| hb_sink (c->output)
|
||||||
;
|
;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||||
|
@ -388,14 +416,28 @@ struct MultipleSubstFormat1
|
||||||
bool intersects (const hb_set_t *glyphs) const
|
bool intersects (const hb_set_t *glyphs) const
|
||||||
{ return (this+coverage).intersects (glyphs); }
|
{ return (this+coverage).intersects (glyphs); }
|
||||||
|
|
||||||
|
bool may_have_non_1to1 () const
|
||||||
|
{ return true; }
|
||||||
|
|
||||||
void closure (hb_closure_context_t *c) const
|
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_zip (this+coverage, sequence)
|
||||||
| hb_filter (*c->glyphs, hb_first)
|
| hb_filter (active_parent_glyphs, hb_first)
|
||||||
| hb_map (hb_second)
|
| hb_map (hb_second)
|
||||||
| hb_map (hb_add (this))
|
| hb_map (hb_add (this))
|
||||||
| hb_apply ([c] (const Sequence &_) { _.closure (c); })
|
| hb_apply ([c] (const Sequence &_) { _.closure (c); })
|
||||||
;
|
;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||||
|
@ -615,14 +657,28 @@ struct AlternateSubstFormat1
|
||||||
bool intersects (const hb_set_t *glyphs) const
|
bool intersects (const hb_set_t *glyphs) const
|
||||||
{ return (this+coverage).intersects (glyphs); }
|
{ return (this+coverage).intersects (glyphs); }
|
||||||
|
|
||||||
|
bool may_have_non_1to1 () const
|
||||||
|
{ return false; }
|
||||||
|
|
||||||
void closure (hb_closure_context_t *c) const
|
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_zip (this+coverage, alternateSet)
|
||||||
| hb_filter (c->glyphs, hb_first)
|
| hb_filter (active_parent_glyphs, hb_first)
|
||||||
| hb_map (hb_second)
|
| hb_map (hb_second)
|
||||||
| hb_map (hb_add (this))
|
| hb_map (hb_add (this))
|
||||||
| hb_apply ([c] (const AlternateSet &_) { _.closure (c); })
|
| hb_apply ([c] (const AlternateSet &_) { _.closure (c); })
|
||||||
;
|
;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
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
|
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_zip (this+coverage, ligatureSet)
|
||||||
| hb_filter (*c->glyphs, hb_first)
|
| hb_filter (active_parent_glyphs, hb_first)
|
||||||
| hb_map (hb_second)
|
| hb_map (hb_second)
|
||||||
| hb_map (hb_add (this))
|
| hb_map (hb_add (this))
|
||||||
| hb_apply ([c] (const LigatureSet &_) { _.closure (c); })
|
| hb_apply ([c] (const LigatureSet &_) { _.closure (c); })
|
||||||
;
|
;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||||
|
@ -1174,15 +1244,27 @@ struct ReverseChainSingleSubstFormat1
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool may_have_non_1to1 () const
|
||||||
|
{ return false; }
|
||||||
|
|
||||||
void closure (hb_closure_context_t *c) const
|
void closure (hb_closure_context_t *c) const
|
||||||
{
|
{
|
||||||
if (!intersects (c->glyphs)) return;
|
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 OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
|
||||||
const ArrayOf<HBGlyphID> &substitute = StructAfter<ArrayOf<HBGlyphID>> (lookahead);
|
const ArrayOf<HBGlyphID> &substitute = StructAfter<ArrayOf<HBGlyphID>> (lookahead);
|
||||||
|
|
||||||
+ hb_zip (this+coverage, substitute)
|
+ hb_zip (this+coverage, substitute)
|
||||||
| hb_filter (*c->glyphs, hb_first)
|
| hb_filter (active_parent_glyphs, hb_first)
|
||||||
| hb_map (hb_second)
|
| hb_map (hb_second)
|
||||||
| hb_sink (c->output)
|
| hb_sink (c->output)
|
||||||
;
|
;
|
||||||
|
@ -1388,6 +1470,12 @@ struct SubstLookup : Lookup
|
||||||
return lookup_type_is_reverse (type);
|
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
|
bool apply (hb_ot_apply_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_APPLY (this);
|
TRACE_APPLY (this);
|
||||||
|
|
|
@ -55,6 +55,15 @@ struct hb_intersects_context_t :
|
||||||
glyphs (glyphs_) {}
|
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 :
|
struct hb_closure_context_t :
|
||||||
hb_dispatch_context_t<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 ();
|
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_face_t *face;
|
||||||
hb_set_t *glyphs;
|
hb_set_t *glyphs;
|
||||||
hb_set_t output[1];
|
hb_set_t output[1];
|
||||||
|
hb_vector_t<hb_set_t *> active_glyphs_stack;
|
||||||
recurse_func_t recurse_func;
|
recurse_func_t recurse_func;
|
||||||
unsigned int nesting_level_left;
|
unsigned int nesting_level_left;
|
||||||
|
|
||||||
|
@ -112,7 +141,9 @@ struct hb_closure_context_t :
|
||||||
nesting_level_left (nesting_level_left_),
|
nesting_level_left (nesting_level_left_),
|
||||||
done_lookups (done_lookups_),
|
done_lookups (done_lookups_),
|
||||||
lookup_count (0)
|
lookup_count (0)
|
||||||
{}
|
{
|
||||||
|
push_cur_active_glyphs (glyphs_);
|
||||||
|
}
|
||||||
|
|
||||||
~hb_closure_context_t () { flush (); }
|
~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_del_range (output, face->get_num_glyphs (), hb_set_get_max (output)); /* Remove invalid glyphs. */
|
||||||
hb_set_union (glyphs, output);
|
hb_set_union (glyphs, output);
|
||||||
hb_set_clear (output);
|
hb_set_clear (output);
|
||||||
|
active_glyphs_stack.pop ();
|
||||||
|
active_glyphs_stack.fini ();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1151,8 +1184,11 @@ static inline void recurse_lookups (context_t *c,
|
||||||
unsigned int lookupCount,
|
unsigned int lookupCount,
|
||||||
const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */)
|
const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */)
|
||||||
{
|
{
|
||||||
|
hb_set_t *chaos = hb_set_create ();
|
||||||
for (unsigned int i = 0; i < lookupCount; i++)
|
for (unsigned int i = 0; i < lookupCount; i++)
|
||||||
c->recurse (lookupRecord[i].lookupListIndex);
|
c->recurse (lookupRecord[i].lookupListIndex);
|
||||||
|
|
||||||
|
hb_set_destroy (chaos);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool apply_lookup (hb_ot_apply_context_t *c,
|
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
|
void closure (hb_closure_context_t *c) const
|
||||||
{
|
{
|
||||||
struct ContextClosureLookupContext lookup_context = {
|
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
|
void closure (hb_closure_context_t *c) const
|
||||||
{
|
{
|
||||||
if (!(this+coverage).intersects (c->glyphs))
|
if (!(this+coverage).intersects (c->glyphs))
|
||||||
|
@ -1949,6 +1991,9 @@ struct ContextFormat3
|
||||||
lookup_context);
|
lookup_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool may_have_non_1to1 () const
|
||||||
|
{ return true; }
|
||||||
|
|
||||||
void closure (hb_closure_context_t *c) const
|
void closure (hb_closure_context_t *c) const
|
||||||
{
|
{
|
||||||
if (!(this+coverageZ[0]).intersects (c->glyphs))
|
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
|
void closure (hb_closure_context_t *c) const
|
||||||
{
|
{
|
||||||
struct ChainContextClosureLookupContext lookup_context = {
|
struct ChainContextClosureLookupContext lookup_context = {
|
||||||
|
@ -2709,6 +2757,10 @@ struct ChainContextFormat2
|
||||||
| hb_any
|
| hb_any
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool may_have_non_1to1 () const
|
||||||
|
{ return true; }
|
||||||
|
|
||||||
void closure (hb_closure_context_t *c) const
|
void closure (hb_closure_context_t *c) const
|
||||||
{
|
{
|
||||||
if (!(this+coverage).intersects (c->glyphs))
|
if (!(this+coverage).intersects (c->glyphs))
|
||||||
|
@ -2941,6 +2993,9 @@ struct ChainContextFormat3
|
||||||
lookup_context);
|
lookup_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool may_have_non_1to1 () const
|
||||||
|
{ return true; }
|
||||||
|
|
||||||
void closure (hb_closure_context_t *c) const
|
void closure (hb_closure_context_t *c) const
|
||||||
{
|
{
|
||||||
const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
|
const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
|
||||||
|
|
Loading…
Reference in New Issue