Skiasharp: SKCanvas.DrawText does not render Unicode characters

Created on 4 Feb 2017  ยท  9Comments  ยท  Source: mono/SkiaSharp

Original source: https://bugzilla.xamarin.com/show_bug.cgi?id=48844

SKCanvas.DrawText should draw a string, "Unicode: [ ๅนด ๆœˆ ]" to a View.

RESULT:
The Japanese characters (ๅนด, ๆœˆ) are missing, and the string that appears is "Unicode: [ ]".

EXPECTED:
The Japanese characters should appear inline along with the rest of the string.

I tried various different typefaces, and even set the language on the device to 'ja-JP', to no avail.
The Japanese characters are not garbled, or wrong, or wacky looking, they just plain aren't there.

Most helpful comment

The C++ code can be "translated" into this C# code after the commit: https://github.com/mono/SkiaSharp/commit/485ef83acda0bb309efafedf1d4a357a5d451dee

// get the character code
// either:
var emojiChar = StringUtilities.GetUnicodeCharacterCode("๐Ÿš€", SKTextEncoding.Utf32);
// or:
var emojiChar = 0x1F680;

// ask the font manager for a font with that character
var fontManager = SKFontManager.Default;
var emojiTypeface = fontManager.MatchCharacter(emojiChar);

// draw it
var paint = new SKPaint { Typeface = emoji };
canvas.DrawText("๐ŸŒ ๐Ÿช ๐Ÿ• ๐Ÿš€", 20, 40, paint);

All 9 comments

The real answer lies here: https://groups.google.com/forum/#!topic/skia-discuss/Hdm0KrbXOKE

You need a set typeface on the SkPaint that has that character. C++ code:

    canvas->clear(SK_ColorWHITE);
    sk_sp<SkFontMgr> mgr(SkFontMgr::RefDefault());
    uint32_t utf32string[] = { 0x1F310 };
    sk_sp<SkTypeface> tf(
            mgr->matchFamilyStyleCharacter(
                    nullptr, SkFontStyle(), nullptr, 0, utf32string[0]));
    if (tf) {
    SkPaint paint;
    paint.setTextSize(64.0f);
        paint.setAntiAlias(true);
    paint.setColor(0xff4281A4);
    paint.setStyle(SkPaint::kFill_Style);
        paint.setTypeface(tf);
        paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
        canvas->drawText(utf32string, sizeof(utf32string), 0.0f, 64.0f, paint);
    }

The C++ code can be "translated" into this C# code after the commit: https://github.com/mono/SkiaSharp/commit/485ef83acda0bb309efafedf1d4a357a5d451dee

// get the character code
// either:
var emojiChar = StringUtilities.GetUnicodeCharacterCode("๐Ÿš€", SKTextEncoding.Utf32);
// or:
var emojiChar = 0x1F680;

// ask the font manager for a font with that character
var fontManager = SKFontManager.Default;
var emojiTypeface = fontManager.MatchCharacter(emojiChar);

// draw it
var paint = new SKPaint { Typeface = emoji };
canvas.DrawText("๐ŸŒ ๐Ÿช ๐Ÿ• ๐Ÿš€", 20, 40, paint);

The real issue is that Skia does not support character fallbacks. If the typeface does not contain the character, it will print a block.

Here is a relevant topic: https://groups.google.com/forum/#!topic/skia-discuss/O4ClH4ziwVo

This is more likely to do with font fallback. In previous versions of Skia font fallback (font chaining) was implicit. Basically, every font was 'extended' with all of the characters/glyphs in all of the fallback fonts. This became unsupportable (as the number of glyphs became too large and meant that fallback could not be controlled in a app locale dependent manner). As a result, you'll need to use SkTypeface::matchFamilyStyleCharacter to discover a font to use with glyphs which cannot be mapped.

I am closing this because this is not a bug, it is just not a automatic feature. The solution to removing those blocks is to first find a typeface that has those characters.

If any of ubiquitous library that worked cross platform with able to check the typeface contain the characters code? Kinda start experiment font rendering

The C++ code can be "translated" into this C# code after the commit: 485ef83

// get the character code
// either:
var emojiChar = StringUtilities.GetUnicodeCharacterCode("๐Ÿš€", SKTextEncoding.Utf32);
// or:
var emojiChar = 0x1F680;

// ask the font manager for a font with that character
var fontManager = SKFontManager.Default;
var emojiTypeface = fontManager.MatchCharacter(emojiChar);

// draw it
var paint = new SKPaint { Typeface = emoji };
canvas.DrawText("๐ŸŒ ๐Ÿช ๐Ÿ• ๐Ÿš€", 20, 40, paint);

@mattleibow When emoji is included, the pdf obtained by SKDocument.CreatePdf is 135M, this is too big.

@inbreaks Could you open a new issue so we don't lose this?

@inbreaks Could you open a new issue so we don't lose this?

@mattleibow https://github.com/mono/SkiaSharp/issues/982

Microcharts.Entry can't show Chinese #165

Was this page helpful?
0 / 5 - 0 ratings

Related issues

AwsomeCode picture AwsomeCode  ยท  4Comments

alanricker picture alanricker  ยท  3Comments

PieroCastillo picture PieroCastillo  ยท  3Comments

ReactorScram picture ReactorScram  ยท  3Comments

NotOfficer picture NotOfficer  ยท  3Comments