From 2f02fc79a5018e3348fccf366c470803554e1e58 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 17 Dec 2015 15:21:14 +0000 Subject: [PATCH] Improve ligature-component handling We use three bits for lig_id these days, so we finally got a report of two separate ligatures with the same lig_id happening adjacent to each other, and then the component-handling code was breaking things. Protect against that by ignoring same-lig-id but lig-comp=0 glyphs after a new ligature. Fixes https://github.com/behdad/harfbuzz/issues/198 --- src/hb-ot-layout-gsubgpos-private.hh | 12 ++++-- test/shaping/Makefile.am | 1 + test/shaping/fonts/sha1sum/MANIFEST | 1 + ...8d1f25ea1df1210414f2fe2e0e1e53082bba76.ttf | Bin 0 -> 4064 bytes test/shaping/tests/MANIFEST | 1 + test/shaping/tests/ligature-id.tests | 35 ++++++++++++++++++ 6 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 test/shaping/fonts/sha1sum/c78d1f25ea1df1210414f2fe2e0e1e53082bba76.ttf create mode 100644 test/shaping/tests/ligature-id.tests diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index 2873d0f09..11ad7e5f7 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -845,9 +845,12 @@ static inline bool ligate_input (hb_apply_context_t *c, while (buffer->idx < match_positions[i] && !buffer->in_error) { if (!is_mark_ligature) { + unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->cur()); + if (this_comp == 0) + this_comp = 1; unsigned int new_lig_comp = components_so_far - last_num_components + - MIN (MAX (_hb_glyph_info_get_lig_comp (&buffer->cur()), 1u), last_num_components); - _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp); + MIN (this_comp, last_num_components); + _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp); } buffer->next_glyph (); } @@ -864,8 +867,11 @@ static inline bool ligate_input (hb_apply_context_t *c, /* Re-adjust components for any marks following. */ for (unsigned int i = buffer->idx; i < buffer->len; i++) { if (last_lig_id == _hb_glyph_info_get_lig_id (&buffer->info[i])) { + unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->info[i]); + if (!this_comp) + break; unsigned int new_lig_comp = components_so_far - last_num_components + - MIN (MAX (_hb_glyph_info_get_lig_comp (&buffer->info[i]), 1u), last_num_components); + MIN (this_comp, last_num_components); _hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp); } else break; diff --git a/test/shaping/Makefile.am b/test/shaping/Makefile.am index f381ac5dc..8308bbb67 100644 --- a/test/shaping/Makefile.am +++ b/test/shaping/Makefile.am @@ -52,6 +52,7 @@ TESTS = \ tests/indic-joiner-candrabindu.tests \ tests/indic-old-spec.tests \ tests/indic-pref-blocking.tests \ + tests/ligature-id.tests \ tests/mongolian-variation-selector.tests \ tests/spaces.tests \ tests/simple.tests \ diff --git a/test/shaping/fonts/sha1sum/MANIFEST b/test/shaping/fonts/sha1sum/MANIFEST index 615da3a52..d3e3295ce 100644 --- a/test/shaping/fonts/sha1sum/MANIFEST +++ b/test/shaping/fonts/sha1sum/MANIFEST @@ -30,6 +30,7 @@ b9e2aaa0d75fcef6971ec3a96d806ba4a6b31fe2.ttf bb29ce50df2bdba2d10726427c6b7609bf460e04.ttf bb9473d2403488714043bcfb946c9f78b86ad627.ttf c4e48b0886ef460f532fb49f00047ec92c432ec0.ttf +c78d1f25ea1df1210414f2fe2e0e1e53082bba76.ttf d629e7fedc0b350222d7987345fe61613fa3929a.ttf df768b9c257e0c9c35786c47cae15c46571d56be.ttf e207635780b42f898d58654b65098763e340f5c7.ttf diff --git a/test/shaping/fonts/sha1sum/c78d1f25ea1df1210414f2fe2e0e1e53082bba76.ttf b/test/shaping/fonts/sha1sum/c78d1f25ea1df1210414f2fe2e0e1e53082bba76.ttf new file mode 100644 index 0000000000000000000000000000000000000000..1baff7dc35ffef01aa4663852929c3b0405a6c86 GIT binary patch literal 4064 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 l71Us>{Bh(