[AAT] Use a ring buffer for ligature stack

I think Apple does very similarly, but probably with a stack size of 16.
We do it with a stack size that is currently set to 64.

Fixes https://github.com/harfbuzz/harfbuzz/issues/1531
This commit is contained in:
Behdad Esfahbod 2019-01-24 18:12:25 +01:00
parent 7886b1578f
commit a371a28cda
1 changed files with 6 additions and 9 deletions

View File

@ -461,14 +461,11 @@ struct LigatureSubtable
DEBUG_MSG (APPLY, nullptr, "Ligature transition at %u", buffer->idx);
if (entry.flags & LigatureEntryT::SetComponent)
{
if (unlikely (match_length >= ARRAY_LENGTH (match_positions)))
match_length = 0; /* TODO Use a ring buffer instead. */
/* Never mark same index twice, in case DontAdvance was used... */
if (match_length && match_positions[match_length - 1] == buffer->out_len)
if (match_length && match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] == buffer->out_len)
match_length--;
match_positions[match_length++] = buffer->out_len;
match_positions[match_length++ % ARRAY_LENGTH (match_positions)] = buffer->out_len;
DEBUG_MSG (APPLY, nullptr, "Set component at %u", buffer->out_len);
}
@ -502,7 +499,7 @@ struct LigatureSubtable
}
DEBUG_MSG (APPLY, nullptr, "Moving to stack position %u", cursor - 1);
buffer->move_to (match_positions[--cursor]);
buffer->move_to (match_positions[--cursor % ARRAY_LENGTH (match_positions)]);
if (unlikely (!actionData->sanitize (&c->sanitizer))) break;
action = *actionData;
@ -530,17 +527,17 @@ struct LigatureSubtable
DEBUG_MSG (APPLY, nullptr, "Produced ligature %u", lig);
buffer->replace_glyph (lig);
unsigned int lig_end = match_positions[match_length - 1] + 1;
unsigned int lig_end = match_positions[(match_length - 1) % ARRAY_LENGTH (match_positions)] + 1;
/* Now go and delete all subsequent components. */
while (match_length - 1 > cursor)
{
DEBUG_MSG (APPLY, nullptr, "Skipping ligature component");
buffer->move_to (match_positions[--match_length]);
buffer->move_to (match_positions[--match_length % ARRAY_LENGTH (match_positions)]);
buffer->replace_glyph (DELETED_GLYPH);
}
buffer->move_to (lig_end);
buffer->merge_out_clusters (match_positions[cursor], buffer->out_len);
buffer->merge_out_clusters (match_positions[cursor % ARRAY_LENGTH (match_positions)], buffer->out_len);
}
actionData++;