HB-NG on Mac: Fix PDF in end of string

The CoreText engine will remove the PDF token from the end of
the string (instead of producing a zero-width glyph for it),
thus the output will be different from the OpenType backend
and Qt will get confused. To fix this, we emulate the expected
behavior by molding the output in a special case.

This is a port of e45c4387ae16627d61e30a58ae901d888d375aa7 from
Qt 4.

Task-number: QTBUG-38113
Change-Id: Ia0a078e3a60317981d4d5a4ee7e575a1714a1d75
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
bb10
Eskil Abrahamsen Blomfeldt 2014-04-07 13:22:12 +02:00 committed by The Qt Project
parent 30e6d442ff
commit 118494aeda
1 changed files with 22 additions and 2 deletions

View File

@ -691,11 +691,12 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
CFDictionaryRef attributes = CTRunGetAttributes (run);
CTFontRef run_ct_font = static_cast<CTFontRef>(CFDictionaryGetValue (attributes, kCTFontAttributeName));
CGFontRef run_cg_font = CTFontCopyGraphicsFont (run_ct_font, 0);
CFRange range = CTRunGetStringRange (run);
if (!CFEqual (run_cg_font, face_data->cg_font))
{
CFRelease (run_cg_font);
CFRange range = CTRunGetStringRange (run);
buffer->ensure (buffer->len + range.length);
if (buffer->in_error)
FAIL ("Buffer resize failed");
@ -732,11 +733,16 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
}
CFRelease (run_cg_font);
/* CoreText throws away the PDF token, while the OpenType backend will add a zero-advance
* glyph for this. We need to make sure the two produce the same output. */
UniChar endGlyph = CFStringGetCharacterAtIndex(string_ref, range.location + range.length - 1);
bool endWithPDF = endGlyph == 0x202c;
unsigned int num_glyphs = CTRunGetGlyphCount (run);
if (num_glyphs == 0)
continue;
buffer->ensure (buffer->len + num_glyphs);
buffer->ensure (buffer->len + num_glyphs + (endWithPDF ? 1 : 0));
scratch = buffer->get_scratch_buffer (&scratch_size);
@ -783,6 +789,20 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
buffer->len++;
}
if (endWithPDF) {
hb_glyph_info_t *info = &buffer->info[buffer->len];
info->codepoint = 0xffff;
info->cluster = range.location + range.length - 1;
/* Currently, we do all x-positioning by setting the advance, we never use x-offset. */
info->mask = 0;
info->var1.u32 = 0;
info->var2.u32 = 0;
buffer->len++;
}
}
buffer->clear_positions ();