diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index ba8013604..951fc82eb 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -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(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, ¬def, 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;