[indic] Fix cluster-merging logic with cluster-level=1

Was producing non-monotonic cluster numbers because our faulty logic
was not merging clusters if something from before base and after base
had switched positions.

Fixes https://github.com/harfbuzz/harfbuzz/issues/2272
This commit is contained in:
Behdad Esfahbod 2021-03-02 16:21:17 -07:00
parent 2902529b92
commit fd489433a8
3 changed files with 26 additions and 3 deletions

View File

@ -752,7 +752,28 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
* We could use buffer->sort() for this, if there was no special
* reordering of pre-base stuff happening later...
* We don't want to merge_clusters all of that, which buffer->sort()
* would.
* would. Here's a concrete example:
*
* Assume there's a pre-base consonant and explicit Halant before base,
* followed by a prebase-reordering (left) Matra:
*
* C,H,ZWNJ,B,M
*
* At this point in reordering we would have:
*
* M,C,H,ZWNJ,B
*
* whereas in final reordering we will bring the Matra closer to Base:
*
* C,H,ZWNJ,M,B
*
* That's why we don't want to merge-clusters anything before the Base
* at this point. But if something moved from after Base to before it,
* we should merge clusters from base to them. In final-reordering, we
* only move things around before base, and merge-clusters up to base.
* These two merge-clusters from the two sides of base will interlock
* to merge things correctly. See:
* https://github.com/harfbuzz/harfbuzz/issues/2272
*/
if (indic_plan->is_old_spec || end - start > 127)
buffer->merge_clusters (base, end);
@ -762,17 +783,18 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
for (unsigned int i = base; i < end; i++)
if (info[i].syllable() != 255)
{
unsigned int min = i;
unsigned int max = i;
unsigned int j = start + info[i].syllable();
while (j != i)
{
min = hb_min (min, j);
max = hb_max (max, j);
unsigned int next = start + info[j].syllable();
info[j].syllable() = 255; /* So we don't process j later again. */
j = next;
}
if (i != max)
buffer->merge_clusters (i, max + 1);
buffer->merge_clusters (hb_max (base, min), max + 1);
}
}

View File

@ -1,2 +1,3 @@
../fonts/4fac3929fc3332834e93673780ec0fe94342d193.ttf:--cluster-level=2:U+0078,U+030A,U+0058,U+030A:[gid2=0+1083|gid3=1@-1132,-8+0|gid1=2+1200|gid3=3@-1190,349+0]
../fonts/43ef465752be9af900745f72fe29cb853a1401a5.ttf:--cluster-level=1:U+05D4,U+05B7,U+05E9,U+05BC,U+05C1,U+05B8,U+05DE,U+05B4,U+05DD:[uni05DD=8+1359|uni05B4=7@111,0+0|uni05DE=6+1391|uni05B8=5+0|uni05BC=3+0|uni05C1=3+0|uni05E9=2+1451|uni05B7=1@28,0+0|uni05D4=0+1338]
../fonts/6f36d056bad6d478fc0bf7397bd52dc3bd197d5f.ttf:--cluster-level=1:U+099B,U+09CB,U+09C8,U+09C2,U+09CB,U+098C:[evowelsigninibeng=0+346|aivowelsignbeng=0+346|evowelsignbeng=0+346|chabeng=0+687|uuvowelsignlongbeng=0@-96,0+0|aavowelsignbeng=0+266|aavowelsignbeng=4+266|lvocalicbeng=5+639]