|
|
|
@ -319,6 +319,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, |
|
|
|
|
|
|
|
|
|
/* First round, decompose */ |
|
|
|
|
|
|
|
|
|
bool all_simple = true; |
|
|
|
|
buffer->clear_output (); |
|
|
|
|
count = buffer->len; |
|
|
|
|
buffer->idx = 0; |
|
|
|
@ -332,49 +333,53 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, |
|
|
|
|
if (end < count) |
|
|
|
|
end--; /* Leave one base for the marks to cluster with. */ |
|
|
|
|
|
|
|
|
|
/* From i to end are simple clusters. */ |
|
|
|
|
/* From idx to end are simple clusters. */ |
|
|
|
|
while (buffer->idx < end && buffer->successful) |
|
|
|
|
decompose_current_character (&c, might_short_circuit); |
|
|
|
|
|
|
|
|
|
if (buffer->idx == count || !buffer->successful) |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
all_simple = false; |
|
|
|
|
|
|
|
|
|
/* Find all the marks now. */ |
|
|
|
|
for (end = buffer->idx + 1; end < count; end++) |
|
|
|
|
if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end]))) |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
/* idx to end is one non-simple cluster. */ |
|
|
|
|
decompose_multi_char_cluster (&c, end, always_short_circuit); |
|
|
|
|
} |
|
|
|
|
while (buffer->idx < count && buffer->successful); |
|
|
|
|
buffer->swap_buffers (); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Second round, reorder (inplace) */ |
|
|
|
|
|
|
|
|
|
count = buffer->len; |
|
|
|
|
for (unsigned int i = 0; i < count; i++) |
|
|
|
|
if (!all_simple) |
|
|
|
|
{ |
|
|
|
|
if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]) == 0) |
|
|
|
|
continue; |
|
|
|
|
count = buffer->len; |
|
|
|
|
for (unsigned int i = 0; i < count; i++) |
|
|
|
|
{ |
|
|
|
|
if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]) == 0) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
unsigned int end; |
|
|
|
|
for (end = i + 1; end < count; end++) |
|
|
|
|
if (_hb_glyph_info_get_modified_combining_class (&buffer->info[end]) == 0) |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
/* We are going to do a O(n^2). Only do this if the sequence is short. */ |
|
|
|
|
if (end - i > HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS) { |
|
|
|
|
i = end; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
unsigned int end; |
|
|
|
|
for (end = i + 1; end < count; end++) |
|
|
|
|
if (_hb_glyph_info_get_modified_combining_class (&buffer->info[end]) == 0) |
|
|
|
|
break; |
|
|
|
|
buffer->sort (i, end, compare_combining_class); |
|
|
|
|
|
|
|
|
|
if (plan->shaper->reorder_marks) |
|
|
|
|
plan->shaper->reorder_marks (plan, buffer, i, end); |
|
|
|
|
|
|
|
|
|
/* We are going to do a O(n^2). Only do this if the sequence is short. */ |
|
|
|
|
if (end - i > HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS) { |
|
|
|
|
i = end; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
buffer->sort (i, end, compare_combining_class); |
|
|
|
|
|
|
|
|
|
if (plan->shaper->reorder_marks) |
|
|
|
|
plan->shaper->reorder_marks (plan, buffer, i, end); |
|
|
|
|
|
|
|
|
|
i = end; |
|
|
|
|
} |
|
|
|
|
if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_CGJ) |
|
|
|
|
{ |
|
|
|
@ -393,8 +398,9 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, |
|
|
|
|
|
|
|
|
|
/* Third round, recompose */ |
|
|
|
|
|
|
|
|
|
if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS || |
|
|
|
|
mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT) |
|
|
|
|
if (!all_simple && |
|
|
|
|
(mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS || |
|
|
|
|
mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT)) |
|
|
|
|
{ |
|
|
|
|
/* As noted in the comment earlier, we don't try to combine
|
|
|
|
|
* ccc=0 chars with their previous Starter. */ |
|
|
|
|