[Indic] Do Reph repositioning in final reordering like the spec says

This introduced a failure, which we tracked down to a test case like this:

  U+092E,U+094B,U+094D,U+0930

The final character is a Ra that should be put in a syllable of it's
own.  And we do.  But it will interact with the Halant before it.  So
now we finally are convinced that we have to limit features to syllable
boundaries.  That's coming after lunch!
This commit is contained in:
Behdad Esfahbod 2012-05-10 13:45:52 +02:00
parent 4705a70269
commit dbb105883c
2 changed files with 64 additions and 41 deletions

View File

@ -74,8 +74,6 @@ enum indic_position_t {
POS_MATRAS, POS_MATRAS,
POS_REPH,
POS_SMVD POS_SMVD
}; };

View File

@ -332,10 +332,8 @@ initial_reordering_consonant_syllable (const hb_ot_map_t *map, hb_buffer_t *buff
info[base].indic_position() = POS_BASE_C; info[base].indic_position() = POS_BASE_C;
/* Handle beginning Ra */ /* Handle beginning Ra */
if (has_reph) { if (has_reph)
info[start].indic_position() = POS_REPH; info[start].indic_position() = POS_RA_TO_BECOME_REPH;
info[start].mask = mask_array[RPHF];
}
/* For old-style Indic script tags, move the first post-base Halant after /* For old-style Indic script tags, move the first post-base Halant after
* last consonant. */ * last consonant. */
@ -382,6 +380,10 @@ initial_reordering_consonant_syllable (const hb_ot_map_t *map, hb_buffer_t *buff
{ {
hb_mask_t mask; hb_mask_t mask;
/* Reph */
if (has_reph)
info[start].mask = mask_array[RPHF];
/* Pre-base */ /* Pre-base */
mask = mask_array[HALF] | mask_array[AKHN] | mask_array[CJCT]; mask = mask_array[HALF] | mask_array[AKHN] | mask_array[CJCT];
for (i = start; i < base; i++) for (i = start; i < base; i++)
@ -530,8 +532,16 @@ final_reordering_syllable (hb_buffer_t *buffer,
* it will be reordered according to the basic-forms shaping results. * it will be reordered according to the basic-forms shaping results.
* Possible positions for reph, depending on the script, are; after main, * Possible positions for reph, depending on the script, are; after main,
* before post-base consonant forms, and after post-base consonant forms. * before post-base consonant forms, and after post-base consonant forms.
* */
* 1. If reph should be positioned after post-base consonant forms,
/* If there's anything after the Ra that has the REPH pos, it ought to be halant.
* Which means that the font has failed to ligate the Reph. In which case, we
* shouldn't move. */
if (start + 1 < end &&
info[start].indic_position() == POS_RA_TO_BECOME_REPH &&
info[start + 1].indic_position() != POS_RA_TO_BECOME_REPH)
{
/* 1. If reph should be positioned after post-base consonant forms,
* proceed to step 5. * proceed to step 5.
* *
* 2. If the reph repositioning class is not after post-base: target * 2. If the reph repositioning class is not after post-base: target
@ -563,8 +573,23 @@ final_reordering_syllable (hb_buffer_t *buffer,
* post-main position. * post-main position.
* *
* 6. Otherwise, reorder reph to the end of the syllable. * 6. Otherwise, reorder reph to the end of the syllable.
* */
* o Reorder pre-base reordering consonants:
start_of_last_cluster = start; /* Yay, one big cluster! */
/* Now let's go shopping for a position. */
unsigned int new_reph_pos = end - 1;
while (new_reph_pos > start && (FLAG (info[new_reph_pos].indic_position()) & (FLAG (POS_SMVD))))
new_reph_pos--;
/* Move */
hb_glyph_info_t reph = info[start];
memmove (&info[start], &info[start + 1], (new_reph_pos - start) * sizeof (info[0]));
info[new_reph_pos] = reph;
}
/* o Reorder pre-base reordering consonants:
* *
* If a pre-base reordering consonant is found, reorder it according to * If a pre-base reordering consonant is found, reorder it according to
* the following rules: * the following rules: