[coretext] Avoid font fallback with CoreText shaper

CoreText does automatic font fallback (AKA "cascading") for  characters
not supported by the requested font, and provides no way to turn it off,
so detect if the returned run uses a font other than the requested one
and fill in the buffer with .notdef glyphs instead of random indices
glyph from a different font.
This commit is contained in:
Khaled Hosny 2013-11-29 19:01:56 -05:00 committed by Behdad Esfahbod
parent 63bae73aef
commit c8213c6198
1 changed files with 35 additions and 0 deletions

View File

@ -651,6 +651,41 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
for (unsigned int i = 0; i < num_runs; i++) {
CTRunRef run = (CTRunRef) CFArrayGetValueAtIndex (glyph_runs, i);
/* CoreText does automatic font fallback (AKA "cascading") for characters
* not supported by the requested font, and provides no way to turn it off,
* so we detect if the returned run uses a font other than the requested
* one and fill in the buffer with .notdef glyphs instead of random glyph
* indices from a different font.
*/
CFRange range = CTRunGetStringRange (run);
CFDictionaryRef attributes = CTRunGetAttributes (run);
CTFontRef run_ct_font = static_cast<CTFontRef>(CFDictionaryGetValue (attributes, kCTFontAttributeName));
CGFontRef run_cg_font = CTFontCopyGraphicsFont (run_ct_font, 0);
CGFontRef cg_font = CTFontCopyGraphicsFont (font_data->ct_font, 0);
if (!CFEqual (run_cg_font, cg_font)) {
CFRelease (run_cg_font);
CFRelease (cg_font);
for (CFIndex j = 0; j < range.length; j++) {
CGGlyph notdef = 0;
double advance = CTFontGetAdvancesForGlyphs (font_data->ct_font, kCTFontHorizontalOrientation, &notdef, NULL, 1);
hb_glyph_info_t *info = &buffer->info[buffer->len];
info->codepoint = notdef;
info->cluster = range.location + j;
info->mask = advance;
info->var1.u32 = 0;
info->var2.u32 = 0;
buffer->len++;
}
continue;
}
CFRelease (run_cg_font);
CFRelease (cg_font);
unsigned int num_glyphs = CTRunGetGlyphCount (run);
if (num_glyphs == 0)
continue;