[AAT] Handle transition errors during machine operation
Before we used to give up. Now, just ignore error and continue processing. Fixes https://github.com/harfbuzz/harfbuzz/issues/1531
This commit is contained in:
parent
e234bb6a42
commit
b976940243
|
@ -777,8 +777,7 @@ struct StateTableDriver
|
|||
buffer->unsafe_to_break (buffer->idx, buffer->idx + 2);
|
||||
}
|
||||
|
||||
if (unlikely (!c->transition (this, entry)))
|
||||
;//break; Ignore error.
|
||||
c->transition (this, entry);
|
||||
|
||||
state = machine.new_state (entry.newState);
|
||||
DEBUG_MSG (APPLY, nullptr, "s%d", state);
|
||||
|
|
|
@ -232,7 +232,7 @@ struct KerxSubTableFormat1
|
|||
{
|
||||
return Format1EntryT::performAction (entry);
|
||||
}
|
||||
bool transition (StateTableDriver<Types, EntryData> *driver,
|
||||
void transition (StateTableDriver<Types, EntryData> *driver,
|
||||
const Entry<EntryData> &entry)
|
||||
{
|
||||
hb_buffer_t *buffer = driver->buffer;
|
||||
|
@ -259,7 +259,7 @@ struct KerxSubTableFormat1
|
|||
if (!c->sanitizer.check_array (actions, depth, tuple_count))
|
||||
{
|
||||
depth = 0;
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
hb_mask_t kern_mask = c->plan->kern_mask;
|
||||
|
@ -334,8 +334,6 @@ struct KerxSubTableFormat1
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -502,7 +500,7 @@ struct KerxSubTableFormat4
|
|||
{
|
||||
return entry.data.ankrActionIndex != 0xFFFF;
|
||||
}
|
||||
bool transition (StateTableDriver<Types, EntryData> *driver,
|
||||
void transition (StateTableDriver<Types, EntryData> *driver,
|
||||
const Entry<EntryData> &entry)
|
||||
{
|
||||
hb_buffer_t *buffer = driver->buffer;
|
||||
|
@ -516,8 +514,7 @@ struct KerxSubTableFormat4
|
|||
{
|
||||
/* indexed into glyph outline. */
|
||||
const HBUINT16 *data = &ankrData[entry.data.ankrActionIndex];
|
||||
if (!c->sanitizer.check_array (data, 2))
|
||||
return false;
|
||||
if (!c->sanitizer.check_array (data, 2)) return;
|
||||
HB_UNUSED unsigned int markControlPoint = *data++;
|
||||
HB_UNUSED unsigned int currControlPoint = *data++;
|
||||
hb_position_t markX = 0;
|
||||
|
@ -532,7 +529,7 @@ struct KerxSubTableFormat4
|
|||
currControlPoint,
|
||||
HB_DIRECTION_LTR /*XXX*/,
|
||||
&currX, &currY))
|
||||
return true; /* True, such that the machine continues. */
|
||||
return;
|
||||
|
||||
o.x_offset = markX - currX;
|
||||
o.y_offset = markY - currY;
|
||||
|
@ -543,8 +540,7 @@ struct KerxSubTableFormat4
|
|||
{
|
||||
/* Indexed into 'ankr' table. */
|
||||
const HBUINT16 *data = &ankrData[entry.data.ankrActionIndex];
|
||||
if (!c->sanitizer.check_array (data, 2))
|
||||
return false;
|
||||
if (!c->sanitizer.check_array (data, 2)) return;
|
||||
unsigned int markAnchorPoint = *data++;
|
||||
unsigned int currAnchorPoint = *data++;
|
||||
const Anchor &markAnchor = c->ankr_table->get_anchor (c->buffer->info[mark].codepoint,
|
||||
|
@ -562,8 +558,7 @@ struct KerxSubTableFormat4
|
|||
case 2: /* Control Point Coordinate Actions. */
|
||||
{
|
||||
const FWORD *data = (const FWORD *) &ankrData[entry.data.ankrActionIndex];
|
||||
if (!c->sanitizer.check_array (data, 4))
|
||||
return false;
|
||||
if (!c->sanitizer.check_array (data, 4)) return;
|
||||
int markX = *data++;
|
||||
int markY = *data++;
|
||||
int currX = *data++;
|
||||
|
@ -584,8 +579,6 @@ struct KerxSubTableFormat4
|
|||
mark_set = true;
|
||||
mark = buffer->idx;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -78,7 +78,7 @@ struct RearrangementSubtable
|
|||
{
|
||||
return (entry.flags & Verb) && start < end;
|
||||
}
|
||||
bool transition (StateTableDriver<Types, EntryData> *driver,
|
||||
void transition (StateTableDriver<Types, EntryData> *driver,
|
||||
const Entry<EntryData> &entry)
|
||||
{
|
||||
hb_buffer_t *buffer = driver->buffer;
|
||||
|
@ -152,8 +152,6 @@ struct RearrangementSubtable
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -232,7 +230,7 @@ struct ContextualSubtable
|
|||
|
||||
return entry.data.markIndex != 0xFFFF || entry.data.currentIndex != 0xFFFF;
|
||||
}
|
||||
bool transition (StateTableDriver<Types, EntryData> *driver,
|
||||
void transition (StateTableDriver<Types, EntryData> *driver,
|
||||
const Entry<EntryData> &entry)
|
||||
{
|
||||
hb_buffer_t *buffer = driver->buffer;
|
||||
|
@ -240,7 +238,7 @@ struct ContextualSubtable
|
|||
/* Looks like CoreText applies neither mark nor current substitution for
|
||||
* end-of-text if mark was not explicitly set. */
|
||||
if (buffer->idx == buffer->len && !mark_set)
|
||||
return true;
|
||||
return;
|
||||
|
||||
const GlyphID *replacement;
|
||||
|
||||
|
@ -297,8 +295,6 @@ struct ContextualSubtable
|
|||
mark_set = true;
|
||||
mark = buffer->idx;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -457,7 +453,7 @@ struct LigatureSubtable
|
|||
{
|
||||
return LigatureEntryT::performAction (entry);
|
||||
}
|
||||
bool transition (StateTableDriver<Types, EntryData> *driver,
|
||||
void transition (StateTableDriver<Types, EntryData> *driver,
|
||||
const Entry<EntryData> &entry)
|
||||
{
|
||||
hb_buffer_t *buffer = driver->buffer;
|
||||
|
@ -466,7 +462,7 @@ struct LigatureSubtable
|
|||
if (entry.flags & LigatureEntryT::SetComponent)
|
||||
{
|
||||
if (unlikely (match_length >= ARRAY_LENGTH (match_positions)))
|
||||
return false;
|
||||
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)
|
||||
|
@ -482,10 +478,10 @@ struct LigatureSubtable
|
|||
unsigned int end = buffer->out_len;
|
||||
|
||||
if (unlikely (!match_length))
|
||||
return true;
|
||||
return;
|
||||
|
||||
if (buffer->idx >= buffer->len)
|
||||
return false; // TODO Work on previous instead?
|
||||
return; // TODO Work on previous instead?
|
||||
|
||||
unsigned int cursor = match_length;
|
||||
|
||||
|
@ -508,7 +504,7 @@ struct LigatureSubtable
|
|||
DEBUG_MSG (APPLY, nullptr, "Moving to stack position %u", cursor - 1);
|
||||
buffer->move_to (match_positions[--cursor]);
|
||||
|
||||
if (unlikely (!actionData->sanitize (&c->sanitizer))) return false;
|
||||
if (unlikely (!actionData->sanitize (&c->sanitizer))) break;
|
||||
action = *actionData;
|
||||
|
||||
uint32_t uoffset = action & LigActionOffset;
|
||||
|
@ -518,7 +514,7 @@ struct LigatureSubtable
|
|||
unsigned int component_idx = buffer->cur().codepoint + offset;
|
||||
component_idx = Types::wordOffsetToIndex (component_idx, table, component.arrayZ);
|
||||
const HBUINT16 &componentData = component[component_idx];
|
||||
if (unlikely (!componentData.sanitize (&c->sanitizer))) return false;
|
||||
if (unlikely (!componentData.sanitize (&c->sanitizer))) break;
|
||||
ligature_idx += componentData;
|
||||
|
||||
DEBUG_MSG (APPLY, nullptr, "Action store %u last %u",
|
||||
|
@ -528,7 +524,7 @@ struct LigatureSubtable
|
|||
{
|
||||
ligature_idx = Types::offsetToIndex (ligature_idx, table, ligature.arrayZ);
|
||||
const GlyphID &ligatureData = ligature[ligature_idx];
|
||||
if (unlikely (!ligatureData.sanitize (&c->sanitizer))) return false;
|
||||
if (unlikely (!ligatureData.sanitize (&c->sanitizer))) break;
|
||||
hb_codepoint_t lig = ligatureData;
|
||||
|
||||
DEBUG_MSG (APPLY, nullptr, "Produced ligature %u", lig);
|
||||
|
@ -552,8 +548,6 @@ struct LigatureSubtable
|
|||
while (!(action & LigActionLast));
|
||||
buffer->move_to (end);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -723,7 +717,7 @@ struct InsertionSubtable
|
|||
return (entry.flags & (CurrentInsertCount | MarkedInsertCount)) &&
|
||||
(entry.data.currentInsertIndex != 0xFFFF ||entry.data.markedInsertIndex != 0xFFFF);
|
||||
}
|
||||
bool transition (StateTableDriver<Types, EntryData> *driver,
|
||||
void transition (StateTableDriver<Types, EntryData> *driver,
|
||||
const Entry<EntryData> &entry)
|
||||
{
|
||||
hb_buffer_t *buffer = driver->buffer;
|
||||
|
@ -736,7 +730,7 @@ struct InsertionSubtable
|
|||
unsigned int count = (flags & MarkedInsertCount);
|
||||
unsigned int start = entry.data.markedInsertIndex;
|
||||
const GlyphID *glyphs = &insertionAction[start];
|
||||
if (unlikely (!c->sanitizer.check_array (glyphs, count))) return false;
|
||||
if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0;
|
||||
|
||||
bool before = flags & MarkedInsertBefore;
|
||||
|
||||
|
@ -764,7 +758,7 @@ struct InsertionSubtable
|
|||
unsigned int count = (flags & CurrentInsertCount) >> 5;
|
||||
unsigned int start = entry.data.currentInsertIndex;
|
||||
const GlyphID *glyphs = &insertionAction[start];
|
||||
if (unlikely (!c->sanitizer.check_array (glyphs, count))) return false;
|
||||
if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0;
|
||||
|
||||
bool before = flags & CurrentInsertBefore;
|
||||
|
||||
|
@ -795,8 +789,6 @@ struct InsertionSubtable
|
|||
*/
|
||||
buffer->move_to ((flags & DontAdvance) ? end : end + count);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
Loading…
Reference in New Issue