src/hb-ot-layout.cc | 20 +++++++-- src/hb-ot-layout.h | 3 - src/hb-ot-map-private.hh | 4 + src/hb-ot-map.cc | 2 src/hb-ot-shape-complex-indic.cc | 85 +++++++++++++++++++++++++++++++++------ test/test-shape-complex.c | 29 ++++++------- 6 files changed, 111 insertions(+), 32 deletions(-)
New commits: commit 07cedd81f48907b2e372cd2e963716bbded9ce29 Author: Behdad Esfahbod <[email protected]> Date: Sat Jul 30 21:16:51 2011 -0400 Minor diff --git a/test/test-shape-complex.c b/test/test-shape-complex.c index 6707acd..1963b5e 100644 --- a/test/test-shape-complex.c +++ b/test/test-shape-complex.c @@ -1030,6 +1030,7 @@ test_shape_complex (ft_fixture_t *f, gconstpointer user_data) unsigned int i, len, expected_len; hb_glyph_info_t *glyphs; hb_bool_t fail; + GString *str; g_assert (f->font); @@ -1054,17 +1055,17 @@ test_shape_complex (ft_fixture_t *f, gconstpointer user_data) break; } - if (fail) { - GString *str = g_string_new (""); - for (i = 0; i < len; i++) - g_string_append_printf (str, " %4d", glyphs[i].codepoint); - g_test_message ("Received glyphs: %s", str->str); - g_string_truncate (str, 0); - for (i = 0; i < expected_len; i++) - g_string_append_printf (str, " %4d", data->glyphs[i]); - g_test_message ("Expected glyphs: %s", str->str); - g_string_free (str, TRUE); + str = g_string_new (""); + for (i = 0; i < len; i++) + g_string_append_printf (str, " %4d", glyphs[i].codepoint); + g_test_message ("Received glyphs: %s", str->str); + g_string_truncate (str, 0); + for (i = 0; i < expected_len; i++) + g_string_append_printf (str, " %4d", data->glyphs[i]); + g_test_message ("Expected glyphs: %s", str->str); + g_string_free (str, TRUE); + if (fail) { g_test_message ("FAIL"); /* The glib test framework is useless, lets not fail for now, * we can grep for FAIL/PASS and count manually. Sigh... */ commit ba7e85c104e68b4685c1b3b5c9a260fe0f6879df Author: Behdad Esfahbod <[email protected]> Date: Sat Jul 30 21:11:53 2011 -0400 Cosmetic diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index cc51b9c..abfc633 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -433,6 +433,7 @@ found_consonant_syllable (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t i--; /* -> until a consonant is found */ if (info[i].indic_category() == OT_C) + //if ((FLAG (info[i].indic_category()) & (FLAG (OT_C) | FLAG (OT_Ra)))) { /* -> that does not have a below-base or post-base form * (post-base forms have to follow below-base forms), */ commit f5bc2725cb892264ba223e0a49f7fd2c622a0730 Author: Behdad Esfahbod <[email protected]> Date: Sat Jul 30 21:08:10 2011 -0400 [Indic] For old-style Indic tables, move Halant around In old-style Indic OT standards, the post-base Halants are moved after their base. Emulate that by moving first post-base Halant to post-last-consonant. Brings test-shape-complex failures down from 88 to 54. Getting there! diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh index 2327e04..5e6aca3 100644 --- a/src/hb-ot-map-private.hh +++ b/src/hb-ot-map-private.hh @@ -60,6 +60,9 @@ struct hb_ot_map_t return map ? map->_1_mask : 0; } + inline hb_tag_t get_chosen_script (unsigned int table_index) const + { return chosen_script[table_index]; } + inline void substitute (hb_face_t *face, hb_buffer_t *buffer) const { apply (0, (hb_ot_map_t::apply_lookup_func_t) hb_ot_layout_substitute_lookup, face, buffer); } inline void position (hb_font_t *font, hb_buffer_t *buffer) const diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index d51b508..cc51b9c 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -506,6 +506,26 @@ found_consonant_syllable (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t info[start].mask = mask_array[RPHF]; } + /* For old-style Indic script tags, move the first post-base Halant after + * last consonant. */ + if ((map->get_chosen_script (0) & 0x000000FF) != '2') { + /* We should only do this for Indic scripts which have a version two I guess. */ + for (i = base + 1; i < end; i++) + if (info[i].indic_category() == OT_H) { + unsigned int j; + for (j = end - 1; j > i; j--) + if ((FLAG (info[j].indic_category()) & (FLAG (OT_C) | FLAG (OT_Ra)))) + break; + if (j > i) { + /* Move Halant to after last consonant. */ + hb_glyph_info_t t = info[i]; + memmove (&info[i], &info[i + 1], (j - i) * sizeof (info[0])); + info[j] = t; + } + break; + } + } + /* Attach ZWJ, ZWNJ, nukta, and halant to previous char to move with them. */ for (i = start + 1; i < end; i++) if ((FLAG (info[i].indic_category()) & commit c47a31fb4793b825f4be57e9cb1b10db352b9512 Author: Behdad Esfahbod <[email protected]> Date: Sat Jul 30 20:57:01 2011 -0400 [OT] Save chosen script tag diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 5e2d6ac..e7a1f98 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -264,27 +264,39 @@ hb_bool_t hb_ot_layout_table_choose_script (hb_face_t *face, hb_tag_t table_tag, const hb_tag_t *script_tags, - unsigned int *script_index) + unsigned int *script_index, + hb_tag_t *chosen_script) { ASSERT_STATIC (Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX); const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); while (*script_tags) { - if (g.find_script_index (*script_tags, script_index)) + if (g.find_script_index (*script_tags, script_index)) { + if (chosen_script) + *chosen_script = *script_tags; return TRUE; + } script_tags++; } /* try finding 'DFLT' */ - if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index)) + if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index)) { + if (chosen_script) + *chosen_script = HB_OT_TAG_DEFAULT_SCRIPT; return FALSE; + } /* try with 'dflt'; MS site has had typos and many fonts use it now :( */ - if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index)) + if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index)) { + if (chosen_script) + *chosen_script = HB_OT_TAG_DEFAULT_LANGUAGE; return FALSE; + } if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX; + if (chosen_script) + *chosen_script = HB_OT_LAYOUT_NO_SCRIPT_INDEX; return FALSE; } diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index 6320437..447e35d 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -92,7 +92,8 @@ hb_bool_t hb_ot_layout_table_choose_script (hb_face_t *face, hb_tag_t table_tag, const hb_tag_t *script_tags, - unsigned int *script_index); + unsigned int *script_index, + hb_tag_t *chosen_script); unsigned int hb_ot_layout_table_get_feature_tags (hb_face_t *face, diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh index 84b4ccf..2327e04 100644 --- a/src/hb-ot-map-private.hh +++ b/src/hb-ot-map-private.hh @@ -123,6 +123,7 @@ struct hb_ot_map_t hb_mask_t global_mask; + hb_tag_t chosen_script[2]; hb_prealloced_array_t<feature_map_t, 8> features; hb_prealloced_array_t<lookup_map_t, 32> lookups[2]; /* GSUB/GPOS */ hb_prealloced_array_t<pause_map_t, 1> pauses[2]; /* GSUB/GPOS */ diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc index 67035ba..ad1290f 100644 --- a/src/hb-ot-map.cc +++ b/src/hb-ot-map.cc @@ -134,7 +134,7 @@ hb_ot_map_builder_t::compile (hb_face_t *face, unsigned int script_index[2], language_index[2]; for (unsigned int table_index = 0; table_index < 2; table_index++) { hb_tag_t table_tag = table_tags[table_index]; - hb_ot_layout_table_choose_script (face, table_tag, script_tags, &script_index[table_index]); + hb_ot_layout_table_choose_script (face, table_tag, script_tags, &script_index[table_index], &m.chosen_script[table_index]); hb_ot_layout_script_find_language (face, table_tag, script_index[table_index], language_tag, &language_index[table_index]); } commit 3a9b14dfdfc278b432890e1537672a4ca141a3b0 Author: Behdad Esfahbod <[email protected]> Date: Sat Jul 30 20:23:55 2011 -0400 Minor diff --git a/test/test-shape-complex.c b/test/test-shape-complex.c index bbb47df..6707acd 100644 --- a/test/test-shape-complex.c +++ b/test/test-shape-complex.c @@ -1056,13 +1056,13 @@ test_shape_complex (ft_fixture_t *f, gconstpointer user_data) if (fail) { GString *str = g_string_new (""); - for (i = 0; i < expected_len; i++) - g_string_append_printf (str, " %4d", data->glyphs[i]); - g_test_message ("Expected glyphs: %s", str->str); - g_string_truncate (str, 0); for (i = 0; i < len; i++) g_string_append_printf (str, " %4d", glyphs[i].codepoint); g_test_message ("Received glyphs: %s", str->str); + g_string_truncate (str, 0); + for (i = 0; i < expected_len; i++) + g_string_append_printf (str, " %4d", data->glyphs[i]); + g_test_message ("Expected glyphs: %s", str->str); g_string_free (str, TRUE); g_test_message ("FAIL"); commit 8613193bbf28fe8951c900b68c4418a6fb929626 Author: Behdad Esfahbod <[email protected]> Date: Sat Jul 30 20:21:40 2011 -0400 [test] Fix problem with N'ko test direction Old HarfBuzz test suite always shaped as left-to-right and hence had wrong 0x14db, direction expected glyphstring for N'ko. Doh! Failures down from 92 to 88. diff --git a/test/test-shape-complex.c b/test/test-shape-complex.c index 6e22fa5..bbb47df 100644 --- a/test/test-shape-complex.c +++ b/test/test-shape-complex.c @@ -956,19 +956,19 @@ static const test_set_t tests_nko = { }, { "", { 0x7ca, 0x7ca, 0 }, - { 0x14db, 0x14d9, 0 } + { 0x14d9, 0x14db, 0 } }, { "", { 0x7ca, 0x7fa, 0x7ca, 0 }, - { 0x14db, 0x5ec, 0x14d9, 0 } + { 0x14d9, 0x5ec, 0x14db, 0 } }, { "", { 0x7ca, 0x7f3, 0x7ca, 0 }, - { 0x14db, 0x5e7, 0x14d9, 0 } + { 0x14d9, 0x5e7, 0x14db, 0 } }, { "", { 0x7ca, 0x7f3, 0x7fa, 0x7ca, 0 }, - { 0x14db, 0x5e7, 0x5ec, 0x14d9, 0 } + { 0x14d9, 0x5ec, 0x5e7, 0x14db, 0 } }, {{0}} } commit fd06bf56110e73826b3d5c73ac964e2609450d46 Author: Behdad Esfahbod <[email protected]> Date: Sat Jul 30 20:14:44 2011 -0400 [Indic] Handle initial Ra+Halant in scripts that support Reph Brings test-shape-complex failures down from 104 to 92. Way to go! diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index f054a07..d51b508 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -496,6 +496,16 @@ found_consonant_syllable (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t info[i].indic_position() = POS_PRE; info[base].indic_position() = POS_BASE; + + /* Handle beginning Ra */ + if (start + 2 <= end && + info[start].indic_category() == OT_Ra && + info[start + 1].indic_category() == OT_H) + { + info[start].indic_position() = POS_POST; + info[start].mask = mask_array[RPHF]; + } + /* Attach ZWJ, ZWNJ, nukta, and halant to previous char to move with them. */ for (i = start + 1; i < end; i++) if ((FLAG (info[i].indic_category()) & commit ee58f3bc75d2d071a71b94063bf12205a5871acb Author: Behdad Esfahbod <[email protected]> Date: Sat Jul 30 19:15:53 2011 -0400 Minor diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 4376e7f..f054a07 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -406,6 +406,7 @@ found_consonant_syllable (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t unsigned int start, unsigned int end) { unsigned int i; + hb_glyph_info_t *info = buffer->info; /* Comments from: * https://www.microsoft.com/typography/otfntdev/devanot/shaping.aspx */ @@ -431,12 +432,12 @@ found_consonant_syllable (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t do { i--; /* -> until a consonant is found */ - if (buffer->info[i].indic_category() == OT_C) + if (info[i].indic_category() == OT_C) { /* -> that does not have a below-base or post-base form * (post-base forms have to follow below-base forms), */ - if (buffer->info[i].indic_position() != POS_BELOW && - buffer->info[i].indic_position() != POS_POST) + if (info[i].indic_position() != POS_BELOW && + info[i].indic_position() != POS_POST) { base = i; break; @@ -492,32 +493,32 @@ found_consonant_syllable (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t /* Reorder characters */ for (i = start; i < base; i++) - buffer->info[i].indic_position() = POS_PRE; - buffer->info[base].indic_position() = POS_BASE; + info[i].indic_position() = POS_PRE; + info[base].indic_position() = POS_BASE; /* Attach ZWJ, ZWNJ, nukta, and halant to previous char to move with them. */ for (i = start + 1; i < end; i++) - if ((FLAG (buffer->info[i].indic_category()) & + if ((FLAG (info[i].indic_category()) & (FLAG (OT_ZWNJ) | FLAG (OT_ZWJ) | FLAG (OT_N) | FLAG (OT_H)))) - buffer->info[i].indic_position() = buffer->info[i - 1].indic_position(); + info[i].indic_position() = info[i - 1].indic_position(); /* We do bubble-sort, skip malicious clusters attempts */ if (end - start > 20) return; /* Sit tight, rock 'n roll! */ - hb_bubble_sort (buffer->info + start, end - start, compare_indic_order); + hb_bubble_sort (info + start, end - start, compare_indic_order); /* Setup masks now */ /* Pre-base */ for (i = start; i < base; i++) - buffer->info[i].mask |= mask_array[HALF] | mask_array[AKHN]; + info[i].mask |= mask_array[HALF] | mask_array[AKHN]; /* Base */ - buffer->info[base].mask |= mask_array[AKHN]; + info[base].mask |= mask_array[AKHN]; /* Post-base */ for (i = base + 1; i < end; i++) - buffer->info[i].mask |= mask_array[BLWF] | mask_array[PSTF]; + info[i].mask |= mask_array[BLWF] | mask_array[PSTF]; } commit 352372ae5ea0998e40cf9fe43c22b6b610a5764e Author: Behdad Esfahbod <[email protected]> Date: Sat Jul 30 19:04:02 2011 -0400 [Indic] Categorize Ra in scripts that have Reph Is the categorization correct? I don't know. diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 95f3f1f..4376e7f 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -234,6 +234,23 @@ static const struct consonant_position_t { {0x0D35, POS_POST}, }; +/* XXX + * This is a hack for now. We should move this data into the main Indic table. + */ +static const hb_codepoint_t ra_chars[] = { + 0x0930, /* Devanagari */ + 0x09B0, /* Bengali */ + 0x09F0, /* Bengali */ + 0x09F1, /* Bengali */ +//0x0A30, /* Gurmukhi */ + 0x0AB0, /* Gujarati */ + 0x0B30, /* Oriya */ +//0x0BB0, /* Tamil */ +//0x0C30, /* Telugu */ + 0x0CB0, /* Kannada */ +//0x0D30, /* Malayalam */ +}; + static int compare_codepoint (const void *pa, const void *pb) { @@ -256,6 +273,15 @@ consonant_position (hb_codepoint_t u) return record ? record->position : POS_BASE; } +static bool +is_ra (hb_codepoint_t u) +{ + return !!bsearch (&u, ra_chars, + ARRAY_LENGTH (ra_chars), + sizeof (ra_chars[0]), + compare_codepoint); +} + static const struct { hb_tag_t tag; @@ -358,8 +384,11 @@ _hb_ot_shape_complex_setup_masks_indic (hb_ot_map_t *map, hb_buffer_t *buffer) buffer->info[i].indic_category() = type & 0x0F; buffer->info[i].indic_position() = type >> 4; - if (buffer->info[i].indic_category() == OT_C) + if (buffer->info[i].indic_category() == OT_C) { buffer->info[i].indic_position() = consonant_position (buffer->info[i].codepoint); + if (is_ra (buffer->info[i].codepoint)) + buffer->info[i].indic_category() = OT_Ra; + } } } _______________________________________________ HarfBuzz mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/harfbuzz
