X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fhb-ot-shape-normalize.cc;h=e2fd91c4e4c1cbcf6ce31ce83c79d805beb08c80;hb=45d6f29f15f1d2323bcaa2498aed23ff0c8a1567;hp=040371f398eedca60581f907ed1dd05f1c59b362;hpb=34c22f816808d061a980cffca12de03beb437fa0;p=profile%2Fivi%2Forg.tizen.video-player.git diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc index 040371f..e2fd91c 100644 --- a/src/hb-ot-shape-normalize.cc +++ b/src/hb-ot-shape-normalize.cc @@ -63,6 +63,15 @@ HB_BEGIN_DECLS * matra for the Indic shaper. */ +static void +output_glyph (hb_ot_shape_context_t *c, + hb_codepoint_t glyph) +{ + hb_buffer_t *buffer = c->buffer; + + buffer->output_glyph (glyph); + hb_glyph_info_set_unicode_props (&buffer->out_info[buffer->out_len - 1], buffer->unicode); +} static bool decompose (hb_ot_shape_context_t *c, @@ -72,46 +81,45 @@ decompose (hb_ot_shape_context_t *c, hb_codepoint_t a, b, glyph; if (!hb_unicode_decompose (c->buffer->unicode, ab, &a, &b) || - !hb_font_get_glyph (c->font, b, 0, &glyph)) + (b && !hb_font_get_glyph (c->font, b, 0, &glyph))) return FALSE; - /* XXX handle singleton decompositions */ bool has_a = hb_font_get_glyph (c->font, a, 0, &glyph); if (shortest && has_a) { /* Output a and b */ - c->buffer->output_glyph (a); - c->buffer->output_glyph (b); + output_glyph (c, a); + if (b) + output_glyph (c, b); return TRUE; } if (decompose (c, shortest, a)) { - c->buffer->output_glyph (b); + if (b) + output_glyph (c, b); return TRUE; } if (has_a) { - c->buffer->output_glyph (a); - c->buffer->output_glyph (b); + output_glyph (c, a); + if (b) + output_glyph (c, b); return TRUE; } return FALSE; } -static bool +static void decompose_current_glyph (hb_ot_shape_context_t *c, bool shortest) { - if (decompose (c, shortest, c->buffer->info[c->buffer->idx].codepoint)) { + if (decompose (c, shortest, c->buffer->info[c->buffer->idx].codepoint)) c->buffer->skip_glyph (); - return TRUE; - } else { + else c->buffer->next_glyph (); - return FALSE; - } } -static bool +static void decompose_single_char_cluster (hb_ot_shape_context_t *c, bool will_recompose) { @@ -120,27 +128,32 @@ decompose_single_char_cluster (hb_ot_shape_context_t *c, /* If recomposing and font supports this, we're good to go */ if (will_recompose && hb_font_get_glyph (c->font, c->buffer->info[c->buffer->idx].codepoint, 0, &glyph)) { c->buffer->next_glyph (); - return FALSE; + return; } - return decompose_current_glyph (c, will_recompose); + decompose_current_glyph (c, will_recompose); } -static bool +static void decompose_multi_char_cluster (hb_ot_shape_context_t *c, unsigned int end) { - bool changed = FALSE; - /* TODO Currently if there's a variation-selector we give-up, it's just too hard. */ for (unsigned int i = c->buffer->idx; i < end; i++) if (unlikely (is_variation_selector (c->buffer->info[i].codepoint))) - return changed; + return; while (c->buffer->idx < end) - changed |= decompose_current_glyph (c, FALSE); + decompose_current_glyph (c, FALSE); +} + +static int +compare_combining_class (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb) +{ + unsigned int a = pa->combining_class(); + unsigned int b = pb->combining_class(); - return changed; + return a < b ? -1 : a == b ? 0 : +1; } void @@ -148,15 +161,19 @@ _hb_ot_shape_normalize (hb_ot_shape_context_t *c) { hb_buffer_t *buffer = c->buffer; bool recompose = !hb_ot_shape_complex_prefer_decomposed (c->plan->shaper); - bool changed = FALSE; bool has_multichar_clusters = FALSE; unsigned int count; - buffer->clear_output (); + /* We do a fairly straightforward yet custom normalization process in three + * separate rounds: decompose, reorder, recompose (if desired). Currently + * this makes two buffer swaps. We can make it faster by moving the last + * two rounds into the inner loop for the first round, but it's more readable + * this way. */ /* First round, decompose */ + buffer->clear_output (); count = buffer->len; for (buffer->idx = 0; buffer->idx < count;) { @@ -166,9 +183,9 @@ _hb_ot_shape_normalize (hb_ot_shape_context_t *c) break; if (buffer->idx + 1 == end) - changed |= decompose_single_char_cluster (c, recompose); + decompose_single_char_cluster (c, recompose); else { - changed |= decompose_multi_char_cluster (c, end); + decompose_multi_char_cluster (c, end); has_multichar_clusters = TRUE; } } @@ -178,14 +195,14 @@ _hb_ot_shape_normalize (hb_ot_shape_context_t *c) /* Technically speaking, two characters with ccc=0 may combine. But all * those cases are in languages that the indic module handles (which expects * decomposed), or in Hangul jamo, which again, we want decomposed anyway. - * So we don't bother combining across cluster boundaries. */ + * So we don't bother combining across cluster boundaries. + * + * TODO: Am I right about Hangul? If I am, we should add a Hangul module + * that requests decomposed. */ if (!has_multichar_clusters) return; /* Done! */ - if (changed) - _hb_set_unicode_props (c->buffer); /* BUFFER: Set general_category and combining_class in var1 */ - /* Second round, reorder (inplace) */ @@ -208,33 +225,53 @@ _hb_ot_shape_normalize (hb_ot_shape_context_t *c) continue; } - unsigned int k = end - i - 1; - do { - hb_glyph_info_t *pinfo = buffer->info + i; - unsigned int new_k = 0; - - for (unsigned int j = 0; j < k; j++) - if (pinfo[j].combining_class() > pinfo[j+1].combining_class()) { - hb_glyph_info_t t; - t = pinfo[j]; - pinfo[j] = pinfo[j + 1]; - pinfo[j + 1] = t; - - new_k = j; - } - k = new_k; - } while (k); + hb_bubble_sort (buffer->info + i, end - i, compare_combining_class); i = end; } + if (!recompose) + return; + /* Third round, recompose */ - if (recompose) { + /* As noted in the comment earlier, we don't try to combine + * ccc=0 chars with their previous Starter. */ + buffer->clear_output (); + count = buffer->len; + unsigned int starter = 0; + buffer->next_glyph (); + while (buffer->idx < count) + { + if (buffer->info[buffer->idx].combining_class() == 0) { + starter = buffer->out_len; + buffer->next_glyph (); + continue; + } + hb_codepoint_t composed, glyph; + if ((buffer->out_info[buffer->out_len - 1].combining_class() >= + buffer->info[buffer->idx].combining_class()) || + !hb_unicode_compose (c->buffer->unicode, + buffer->out_info[starter].codepoint, + buffer->info[buffer->idx].codepoint, + &composed) || + !hb_font_get_glyph (c->font, composed, 0, &glyph)) + { + /* Blocked, or doesn't compose. */ + buffer->next_glyph (); + continue; + } + + /* Composes. Modify starter and carry on. */ + buffer->out_info[starter].codepoint = composed; + hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer->unicode); + + buffer->skip_glyph (); } + buffer->swap_buffers (); }