From c8213c6198abff97822e29a6d565722cfbb43832 Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Fri, 29 Nov 2013 19:01:56 -0500 Subject: [PATCH] [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. --- src/hb-coretext.cc | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) 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;