From 5389ff4dbc46c76c9483e3c95f22524b60e21166 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 22 Jul 2011 20:22:49 -0400 Subject: [PATCH] Implement the Unicode Canonical Composition algorithm Fallback normalization is complete and working now! --- src/hb-ot-shape-normalize.cc | 49 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc index 66afaa6..6f8abb8 100644 --- a/src/hb-ot-shape-normalize.cc +++ b/src/hb-ot-shape-normalize.cc @@ -154,11 +154,16 @@ _hb_ot_shape_normalize (hb_ot_shape_context_t *c) bool has_multichar_clusters = FALSE; unsigned int count; - buffer->clear_output (); + /* We do a farily 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;) { @@ -180,7 +185,10 @@ _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! */ @@ -231,12 +239,47 @@ _hb_ot_shape_normalize (hb_ot_shape_context_t *c) } + 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 (); } -- 2.7.4