In hb_ot_collect_glyphs(), don't recurse to a lookup more than once

Otherwise, we might process a lookup thousands of times, with no
benefit.  This pathological case was hit by Noto Nastaliq Urdu Draft
in Firefox's code to determine whether space glyph is involved in
any GSUB/GPOS rules.  A test page is at http://behdad.org/urdu

See:
https://bugzilla.mozilla.org/show_bug.cgi?id=1090869
This commit is contained in:
Behdad Esfahbod 2014-10-29 11:23:08 -07:00
parent 5a5640d850
commit fde3e4a423
1 changed files with 16 additions and 1 deletions

View File

@ -168,6 +168,10 @@ struct hb_collect_glyphs_context_t
if (output == hb_set_get_empty ()) if (output == hb_set_get_empty ())
return HB_VOID; return HB_VOID;
/* Return if new lookup was recursed to before. */
if (recursed_lookups.has (lookup_index))
return HB_VOID;
hb_set_t *old_before = before; hb_set_t *old_before = before;
hb_set_t *old_input = input; hb_set_t *old_input = input;
hb_set_t *old_after = after; hb_set_t *old_after = after;
@ -181,6 +185,8 @@ struct hb_collect_glyphs_context_t
input = old_input; input = old_input;
after = old_after; after = old_after;
recursed_lookups.add (lookup_index);
return HB_VOID; return HB_VOID;
} }
@ -190,6 +196,7 @@ struct hb_collect_glyphs_context_t
hb_set_t *after; hb_set_t *after;
hb_set_t *output; hb_set_t *output;
recurse_func_t recurse_func; recurse_func_t recurse_func;
hb_set_t recursed_lookups;
unsigned int nesting_level_left; unsigned int nesting_level_left;
unsigned int debug_depth; unsigned int debug_depth;
@ -205,8 +212,16 @@ struct hb_collect_glyphs_context_t
after (glyphs_after ? glyphs_after : hb_set_get_empty ()), after (glyphs_after ? glyphs_after : hb_set_get_empty ()),
output (glyphs_output ? glyphs_output : hb_set_get_empty ()), output (glyphs_output ? glyphs_output : hb_set_get_empty ()),
recurse_func (NULL), recurse_func (NULL),
recursed_lookups (),
nesting_level_left (nesting_level_left_), nesting_level_left (nesting_level_left_),
debug_depth (0) {} debug_depth (0)
{
recursed_lookups.init ();
}
~hb_collect_glyphs_context_t (void)
{
recursed_lookups.fini ();
}
void set_recurse_func (recurse_func_t func) { recurse_func = func; } void set_recurse_func (recurse_func_t func) { recurse_func = func; }
}; };