Implement the Unicode Canonical Composition algorithm

Fallback normalization is complete and working now!
This commit is contained in:
Behdad Esfahbod 2011-07-22 20:22:49 -04:00
parent dcdc51cdc0
commit 5389ff4dbc
1 changed files with 46 additions and 3 deletions

View File

@ -154,11 +154,16 @@ _hb_ot_shape_normalize (hb_ot_shape_context_t *c)
bool has_multichar_clusters = FALSE; bool has_multichar_clusters = FALSE;
unsigned int count; 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 */ /* First round, decompose */
buffer->clear_output ();
count = buffer->len; count = buffer->len;
for (buffer->idx = 0; buffer->idx < count;) 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 /* Technically speaking, two characters with ccc=0 may combine. But all
* those cases are in languages that the indic module handles (which expects * those cases are in languages that the indic module handles (which expects
* decomposed), or in Hangul jamo, which again, we want decomposed anyway. * 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) if (!has_multichar_clusters)
return; /* Done! */ return; /* Done! */
@ -231,13 +239,48 @@ _hb_ot_shape_normalize (hb_ot_shape_context_t *c)
} }
if (!recompose)
return;
/* Third round, recompose */ /* 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 ();
} }
HB_END_DECLS HB_END_DECLS