HB-NG w/CoreText backend: Fix clustering of neutral characters

Say you have a string with logical contents "abc ABC, " where
lowercase is LTR and uppercase is RTL. In this case, the UBA
will give "abc " LTR direction, and "ABC, " will get RTL.

However, our itemization currently divides "ABC, " into two
script items: "ABC" and ", ". CoreText will return glyphs in
visual order, so for the first we will get "CBA" and for the
second we will get ", ". But as the ", " item has an adapted
directionality of RTL in the context of the full paragraph, it
should actually be " ," visually.

This caused a mismatch which broke the tst_QComplexText test
with HB-NG using CoreText backend. As a temporary fix for this,
we check whether the directionality of the first run in the text
is different from the directionality expected by HB-NG. If this
happens, it means the order of the glyphs produced by CoreText
will be the reverse order of what is expected by HB-NG, and
we therefore need to reverse it.

Task-number: QTBUG-38113
Change-Id: I9f5a041791e4529a14041a362b2d5dd00490a38b
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
This commit is contained in:
Eskil Abrahamsen Blomfeldt 2014-04-09 14:19:32 +02:00 committed by The Qt Project
parent 000693018b
commit 05cfb6cd09

View File

@ -807,6 +807,9 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
buffer->clear_positions ();
bool bufferRtl = !HB_DIRECTION_IS_FORWARD (buffer->props.direction);
bool runRtl = (CTRunGetStatus(static_cast<CTRunRef>(CFArrayGetValueAtIndex(glyph_runs, 0))) & kCTRunStatusRightToLeft);
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; ++i) {
hb_glyph_info_t *info = &buffer->info[i];
@ -816,6 +819,12 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
pos->x_advance = info->mask;
pos->x_offset = info->var1.u32;
pos->y_offset = info->var2.u32;
if (bufferRtl != runRtl && i < count / 2) {
unsigned int temp = buffer->info[count - i - 1].cluster;
buffer->info[count - i - 1].cluster = info->cluster;
info->cluster = temp;
}
}
/* Fix up clusters so that we never return out-of-order indices;