|
|
@ -608,80 +608,59 @@ struct InsertionSubtable |
|
|
|
hb_buffer_t *buffer = driver->buffer; |
|
|
|
hb_buffer_t *buffer = driver->buffer; |
|
|
|
unsigned int flags = entry->flags; |
|
|
|
unsigned int flags = entry->flags; |
|
|
|
|
|
|
|
|
|
|
|
if (0) |
|
|
|
if (entry->data.markedInsertIndex != 0xFFFF) |
|
|
|
c->sanitizer.check_range (nullptr, 0); |
|
|
|
|
|
|
|
#if 0 |
|
|
|
|
|
|
|
if (flags & SetComponent) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
if (unlikely (match_length >= ARRAY_LENGTH (match_positions))) |
|
|
|
unsigned int count = (entry->flags & MarkedInsertCount); |
|
|
|
return false; |
|
|
|
unsigned int start = entry->data.markedInsertIndex; |
|
|
|
|
|
|
|
const GlyphID *glyphs = &insertionAction[start]; |
|
|
|
|
|
|
|
if (unlikely (!c->sanitizer.check_array (glyphs, count))) return false; |
|
|
|
|
|
|
|
|
|
|
|
/* Never mark same index twice, in case DontAdvance was used... */ |
|
|
|
bool before = entry->flags & MarkedInsertBefore; |
|
|
|
if (match_length && match_positions[match_length - 1] == buffer->out_len) |
|
|
|
|
|
|
|
match_length--; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
match_positions[match_length++] = buffer->out_len; |
|
|
|
if (unlikely (!mark_set)) return false; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (flags & PerformAction) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
unsigned int end = buffer->out_len; |
|
|
|
unsigned int end = buffer->out_len; |
|
|
|
unsigned int action_idx = entry->data.ligActionIndex; |
|
|
|
buffer->move_to (mark); |
|
|
|
unsigned int action; |
|
|
|
|
|
|
|
unsigned int ligature_idx = 0; |
|
|
|
|
|
|
|
do |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (unlikely (!match_length)) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
buffer->move_to (match_positions[--match_length]); |
|
|
|
if (!before) |
|
|
|
|
|
|
|
buffer->copy_glyph (); |
|
|
|
|
|
|
|
/* TODO We ignore KashidaLike setting. */ |
|
|
|
|
|
|
|
for (unsigned int i = 0; i < count; i++) |
|
|
|
|
|
|
|
buffer->output_glyph (glyphs[i]); |
|
|
|
|
|
|
|
if (!before) |
|
|
|
|
|
|
|
buffer->skip_glyph (); |
|
|
|
|
|
|
|
|
|
|
|
const HBUINT32 &actionData = ligAction[action_idx]; |
|
|
|
buffer->move_to (end + count); |
|
|
|
if (unlikely (!actionData.sanitize (&c->sanitizer))) return false; |
|
|
|
} |
|
|
|
action = actionData; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t uoffset = action & LigActionOffset; |
|
|
|
|
|
|
|
if (uoffset & 0x20000000) |
|
|
|
|
|
|
|
uoffset += 0xC0000000; |
|
|
|
|
|
|
|
int32_t offset = (int32_t) uoffset; |
|
|
|
|
|
|
|
unsigned int component_idx = buffer->cur().codepoint + offset; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const HBUINT16 &componentData = component[component_idx]; |
|
|
|
if (entry->data.currentInsertIndex != 0xFFFF) |
|
|
|
if (unlikely (!componentData.sanitize (&c->sanitizer))) return false; |
|
|
|
{ |
|
|
|
ligature_idx += componentData; |
|
|
|
unsigned int count = (entry->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 (action & (LigActionStore | LigActionLast)) |
|
|
|
bool before = entry->flags & CurrentInsertBefore; |
|
|
|
{ |
|
|
|
|
|
|
|
const GlyphID &ligatureData = ligature[ligature_idx]; |
|
|
|
|
|
|
|
if (unlikely (!ligatureData.sanitize (&c->sanitizer))) return false; |
|
|
|
|
|
|
|
hb_codepoint_t lig = ligatureData; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
match_positions[match_length++] = buffer->out_len; |
|
|
|
unsigned int end = buffer->out_len; |
|
|
|
buffer->replace_glyph (lig); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//ligature_idx = 0; // XXX Yes or no?
|
|
|
|
if (!before) |
|
|
|
} |
|
|
|
buffer->copy_glyph (); |
|
|
|
else |
|
|
|
/* TODO We ignore KashidaLike setting. */ |
|
|
|
{ |
|
|
|
for (unsigned int i = 0; i < count; i++) |
|
|
|
buffer->skip_glyph (); |
|
|
|
buffer->output_glyph (glyphs[i]); |
|
|
|
end--; |
|
|
|
if (!before) |
|
|
|
} |
|
|
|
buffer->skip_glyph (); |
|
|
|
/* TODO merge_clusters / unsafe_to_break */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
action_idx++; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
while (!(action & LigActionLast)); |
|
|
|
|
|
|
|
buffer->move_to (end); |
|
|
|
buffer->move_to (end); |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (flags & SetMark) |
|
|
|
if (flags & SetMark) |
|
|
|
{ |
|
|
|
{ |
|
|
|
mark_set = true; |
|
|
|
mark_set = true; |
|
|
|
mark = buffer->idx; |
|
|
|
mark = buffer->out_len; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|