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