diff --git a/src/gen-arabic-table.py b/src/gen-arabic-table.py index 6549cb40f..2d3c88193 100755 --- a/src/gen-arabic-table.py +++ b/src/gen-arabic-table.py @@ -133,11 +133,7 @@ def print_shaping_table(f): print "#define SHAPING_TABLE_LAST 0x%04X" % max_u print - print - print "static const uint16_t ligature_table[][3] =" - print "{" - - ligas = [] + ligas = {} for pair in ligatures.keys (): for shape in ligatures[pair]: c = ligatures[pair][shape] @@ -147,11 +143,27 @@ def print_shaping_table(f): liga = (shapes[pair[0]]['medial'], shapes[pair[1]]['final']) else: raise Exception ("Unexpected shape", shape) - ligas.append (liga + (c,)) - ligas.sort () - for liga in ligas: - value = ', '.join ("0x%04X" % c for c in liga) - print " {%s}, /* U+%04X %s */" % (value, liga[2], names[liga[2]]) + if liga[0] not in ligas: + ligas[liga[0]] = [] + ligas[liga[0]].append ((liga[1], c)) + max_i = max (len (ligas[l]) for l in ligas) + print + print "static const struct {" + print " uint16_t first;" + print " struct {" + print " uint16_t second;" + print " uint16_t ligature;" + print " } ligatures[%d];" % max_i + print "} ligature_table[] =" + print "{" + keys = ligas.keys () + keys.sort () + for first in keys: + + print " { 0x%04X, {" % (first) + for liga in ligas[first]: + print " { 0x%04X, 0x%04X }, /* %s */" % (liga[0], liga[1], names[liga[1]]) + print " }}," print "};" print diff --git a/src/hb-ot-shape-complex-arabic-table.hh b/src/hb-ot-shape-complex-arabic-table.hh index e0b27f8b7..df8508676 100644 --- a/src/hb-ot-shape-complex-arabic-table.hh +++ b/src/hb-ot-shape-complex-arabic-table.hh @@ -914,16 +914,26 @@ static const uint16_t shaping_table[][4] = #define SHAPING_TABLE_LAST 0x06D3 -static const uint16_t ligature_table[][3] = +static const struct { + uint16_t first; + struct { + uint16_t second; + uint16_t ligature; + } ligatures[4]; +} ligature_table[] = { - {0xFEDF, 0xFE82, 0xFEF5}, /* U+FEF5 ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM */ - {0xFEDF, 0xFE84, 0xFEF7}, /* U+FEF7 ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM */ - {0xFEDF, 0xFE88, 0xFEF9}, /* U+FEF9 ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM */ - {0xFEDF, 0xFE8E, 0xFEFB}, /* U+FEFB ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM */ - {0xFEE0, 0xFE82, 0xFEF6}, /* U+FEF6 ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM */ - {0xFEE0, 0xFE84, 0xFEF8}, /* U+FEF8 ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM */ - {0xFEE0, 0xFE88, 0xFEFA}, /* U+FEFA ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM */ - {0xFEE0, 0xFE8E, 0xFEFC}, /* U+FEFC ARABIC LIGATURE LAM WITH ALEF FINAL FORM */ + { 0xFEDF, { + { 0xFE88, 0xFEF9 }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM */ + { 0xFE82, 0xFEF5 }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM */ + { 0xFE8E, 0xFEFB }, /* ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM */ + { 0xFE84, 0xFEF7 }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM */ + }}, + { 0xFEE0, { + { 0xFE88, 0xFEFA }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM */ + { 0xFE82, 0xFEF6 }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM */ + { 0xFE8E, 0xFEFC }, /* ARABIC LIGATURE LAM WITH ALEF FINAL FORM */ + { 0xFE84, 0xFEF8 }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM */ + }}, }; diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc index 991f7cfc2..c44c27c26 100644 --- a/src/hb-ot-shape-complex-arabic.cc +++ b/src/hb-ot-shape-complex-arabic.cc @@ -87,6 +87,16 @@ static hb_codepoint_t get_arabic_shape (hb_codepoint_t u, unsigned int shape) return u; } +static uint16_t get_ligature (hb_codepoint_t first, hb_codepoint_t second) +{ + if (unlikely (!second)) return 0; + for (unsigned i = 0; i < ARRAY_LENGTH (ligature_table); i++) + if (ligature_table[i].first == first) + for (unsigned j = 0; j < ARRAY_LENGTH (ligature_table[i].ligatures); j++) + if (ligature_table[i].ligatures[j].second == second) + return ligature_table[i].ligatures[j].ligature; + return 0; +} static const hb_tag_t arabic_syriac_features[] = { @@ -198,8 +208,29 @@ static void arabic_fallback_shape (hb_buffer_t *buffer) { unsigned int count = buffer->len; + + /* Shape to presentation forms */ for (unsigned int i = 0; i < count; i++) buffer->info[i].codepoint = get_arabic_shape (buffer->info[i].codepoint, buffer->info[i].arabic_shaping_action()); + + /* Mandatory ligatures */ + buffer->clear_output (); + for (buffer->idx = 0; buffer->idx + 1 < count;) { + uint16_t ligature = get_ligature (buffer->info[buffer->idx].codepoint, + buffer->info[buffer->idx + 1].codepoint); + if (likely (!ligature)) { + buffer->next_glyph (); + continue; + } + + buffer->replace_glyphs (2, 1, &ligature); + + /* Technically speaking we can skip marks and stuff, like the GSUB path does. + * But who cares, we're in fallback! */ + } + for (; buffer->idx < count;) + buffer->next_glyph (); + buffer->swap_buffers (); } void diff --git a/src/hb-ot-shape-complex-misc.cc b/src/hb-ot-shape-complex-misc.cc index d893eb3fe..23a5b525f 100644 --- a/src/hb-ot-shape-complex-misc.cc +++ b/src/hb-ot-shape-complex-misc.cc @@ -132,7 +132,7 @@ _hb_ot_shape_complex_setup_masks_thai (hb_ot_map_t *map, hb_buffer_t *buffer) unsigned int count = buffer->len; for (buffer->idx = 0; buffer->idx < count;) { - if (!IS_SARA_AM (buffer->info[buffer->idx].codepoint)) { + if (likely (!IS_SARA_AM (buffer->info[buffer->idx].codepoint))) { buffer->next_glyph (); continue; } @@ -141,7 +141,7 @@ _hb_ot_shape_complex_setup_masks_thai (hb_ot_map_t *map, hb_buffer_t *buffer) uint16_t decomposed[2] = {NIKHAHIT_FROM_SARA_AM (buffer->info[buffer->idx].codepoint), SARA_AA_FROM_SARA_AM (buffer->info[buffer->idx].codepoint)}; buffer->replace_glyphs (1, 2, decomposed); - if (buffer->in_error) + if (unlikely (buffer->in_error)) return; /* Ok, let's see... */