BreakText returns incorrect number of characters if text contains cyrillic characters

ConstantinConstantin RUMember ✭✭
edited November 2017 in SkiaSharp

Hello, Hello!

Try execute this code:

        private void C_PaintSurface(object sender, SKPaintGLSurfaceEventArgs e)
        {
            var canvas = e.Surface.Canvas;
            var textPaint = new SKPaint() { Color = SKColors.White };
            var linePaint = new SKPaint() { Color = SKColors.Red };

            var lat = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
            var cyr = "АБВГДEЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЯЭЮЯ";

            var x = 10f;
            var y = 0f;
            var xx = 120f;
            foreach (var ch in lat)
            {
                var t = ch.ToString();
                var lw = textPaint.MeasureText(t);
                float mw;
                textPaint.BreakText(t, 1000f, out mw);
                canvas.DrawText($"{ch} ({lw} = {mw})", x, y += textPaint.FontSpacing, textPaint);
            }

            y = 0f; x += xx;
            foreach (var ch in lat.ToLower())
            {
                var t = ch.ToString();
                var lw = textPaint.MeasureText(t);
                float mw;
                textPaint.BreakText(t, 1000f, out mw);
                canvas.DrawText($"{ch} ({lw} = {mw})", x, y += textPaint.FontSpacing, textPaint);
            }

            y = 0f; x += xx;
            foreach (var ch in cyr)
            {
                var t = ch.ToString();
                var lw = textPaint.MeasureText(t);
                float mw;
                textPaint.BreakText(t, 1000f, out mw);
                canvas.DrawText($"{ch} ({lw} = {mw})", x, y += textPaint.FontSpacing, textPaint);
            }

            y = 0f; x += xx;
            foreach (var ch in cyr.ToLower())
            {
                var t = ch.ToString();
                var lw = textPaint.MeasureText(t);
                float mw;
                textPaint.BreakText(t, 1000f, out mw);
                canvas.DrawText($"{ch} ({lw} = {mw})", x, y += textPaint.FontSpacing, textPaint);
            }

            y = 0f; x += xx;

            for (var maxw = 50f; maxw <= 150f; maxw += 50f)
            {
                canvas.DrawText($"maxWidth = {maxw}", x, y += textPaint.FontSpacing, textPaint);

                {
                    var t = lat;
                    float mw;
                    var l = textPaint.BreakText(t, maxw, out mw);
                    if (l < t.Length) t = t.Remove((int)l);
                    var lw = textPaint.MeasureText(t);
                    canvas.DrawText($"{t} ({lw} = {mw})", x, y += textPaint.FontSpacing, textPaint);
                }

                {
                    var t = cyr;
                    float mw;
                    var l = textPaint.BreakText(t, maxw, out mw);
                    if (l < t.Length) t = t.Remove((int)l);
                    var lw = textPaint.MeasureText(t);
                    canvas.DrawText($"{t} ({lw} = {mw})", x, y += textPaint.FontSpacing, textPaint);
                }

                canvas.DrawLine(x, y + 5, x + maxw, y +5, linePaint);
                y += textPaint.FontSpacing;
            }
        }

Posts

  • mattleibowmattleibow ZAXamarin Team Xamurai

    Moving this to the GitHub issue as this is a "bug" with both the docs and the managed perception, but still is functioning as designed: https://github.com/mono/SkiaSharp/issues/381

  • ConstantinConstantin RUMember ✭✭

    Matthew, thank you!
    "The return value is actually the NUMBER OF BYTES in the string, that is why you see the larger numbers."
    This code can work and that's Ok:

        textPaint.TextEncoding = SKTextEncoding.Utf16;
        ...
        var l = textPaint.BreakText(t, maxw, out mw) >> 1;
    
Sign In or Register to comment.