Esempio n. 1
0
        public void Render(SKCanvas canvas, IGeometryVisual geometry, double scale)
        {
            var moist = geometry as IMoist;

            if (moist == null || !moist.IsValid)
            {
                return;
            }
            using (var paint = new SKPaint())
            {
                // Setup common paint parameters
                paint.Color       = moist.ToolSettings.SelectedColor.ToSkiaColor();
                paint.IsAntialias = true;
                paint.IsStroke    = false;
                var text = moist.ToolSettings.SelectedText;
                if (string.IsNullOrEmpty(text))
                {
                    paint.StrokeWidth = (float)(moist.Size * scale);
                    paint.StrokeCap   = SKStrokeCap.Round;
                    canvas.DrawPoint((float)(moist.Point.X * scale), (float)(moist.Point.Y * scale), paint);
                }
                else
                {
                    paint.TextSize = (float)(moist.Size * scale);
                    // Get the path of the text to calibrate the touch point to the middle of the text area
                    var originalTextPath = paint.GetTextPath(text, (float)(moist.Point.X * scale), (float)(moist.Point.Y * scale));
                    // Set the mid of the text area to the touch point
                    var calibratedX = originalTextPath.Bounds.Left - originalTextPath.Bounds.Width / 2;
                    var calibratedY = originalTextPath.Bounds.Bottom + originalTextPath.Bounds.Height / 2;

                    // Set the right text color
                    var textColor = Converter.ContrastColor(moist.ToolSettings.SelectedColor);
                    // Get the path of the calibrated text area and add some padding to the rect
                    var calibratedTextPath = paint.GetTextPath(text, calibratedX, calibratedY);
                    // Rect parameters
                    float left;
                    float top;
                    float right;
                    float bottom;
                    float cornerRadius;

                    var textSizeDependentPadding = paint.TextSize / 4;
                    left         = calibratedTextPath.Bounds.Left - textSizeDependentPadding;
                    top          = calibratedTextPath.Bounds.Top - textSizeDependentPadding;
                    right        = calibratedTextPath.Bounds.Right + textSizeDependentPadding;
                    bottom       = calibratedTextPath.Bounds.Bottom + textSizeDependentPadding;
                    cornerRadius = paint.TextSize / 2;

                    var rect = new SKRect(left, top, right, bottom);
                    // Draw background rect
                    canvas.DrawRoundRect(rect, cornerRadius, cornerRadius, paint);
                    // Draw text
                    paint.Color = textColor.ToSkiaColor();
                    canvas.DrawText(text, calibratedX, calibratedY, paint);
                    // Draw the background border in same color as text
                    paint.IsStroke = true;
                    canvas.DrawRoundRect(rect, cornerRadius, cornerRadius, paint);
                }
            }
        }
Esempio n. 2
0
        public void Render(SKCanvas canvas, IGeometryVisual gemoetry, double scale)
        {
            var text = gemoetry as IText;

            if (text == null || !text.IsValid)
            {
                return;
            }

            using (var paint = new SKPaint())
            {
                // Setup common paint parameters
                paint.IsAntialias = true;
                paint.IsStroke    = false;
                paint.TextSize    = (float)(text.Size * scale);
                paint.Color       = text.Color.ToSkiaColor();

                // Get the path of the text to calibrate the touch point to the middle of the text area
                var originalTextPath = paint.GetTextPath(text.Value, (float)(text.Point.X * scale), (float)(text.Point.Y * scale));
                // Set the mid of the text area to the touch point
                var calibratedX = originalTextPath.Bounds.Left - originalTextPath.Bounds.Width / 2;
                var calibratedY = originalTextPath.Bounds.Bottom + originalTextPath.Bounds.Height / 2;

                if (text.IsFilled)
                {
                    // Set the right text color
                    var textColor = Converter.ContrastColor(text.Color);

                    var calibratedTextPath = paint.GetTextPath(text.Value, calibratedX, calibratedY);
                    // Get the path of the calibrated text area and add some padding to the rect
                    var left   = calibratedTextPath.Bounds.Left - Padding;
                    var top    = calibratedTextPath.Bounds.Top - Padding;
                    var right  = calibratedTextPath.Bounds.Right + Padding;
                    var bottom = calibratedTextPath.Bounds.Bottom + Padding;
                    var rect   = new SKRect(left, top, right, bottom);
                    // Draw background rect
                    canvas.DrawRect(rect, paint);
                    // Draw text
                    paint.Color = textColor.ToSkiaColor();
                    canvas.DrawText(text.Value, calibratedX, calibratedY, paint);
                    // Draw the background border in same color as text
                    paint.IsStroke = true;
                    canvas.DrawRect(rect, paint);
                }
                else
                {
                    // Draw Text
                    canvas.DrawText(text.Value, calibratedX, calibratedY, paint);
                }
            }
        }
Esempio n. 3
0
        private void DrawTooltip(SKCanvas canvas, ChartEntry entry)
        {
            using (var textPaint = new SKPaint
            {
                Style = SKPaintStyle.StrokeAndFill,
                Color = TooltipTextColor,
                TextAlign = SKTextAlign.Center,
                TextSize = TooltipTextSize
            })
            {
                var topBottomMargin      = TooltipTextSize;
                var tooltipTextYPosition = _tooltipPoint.Y - TooltipYOffset - topBottomMargin;
                var textPath             = textPaint.GetTextPath(entry.Label, _tooltipPoint.X, tooltipTextYPosition);
                using (var tooltipBackgroundPaint = new SKPaint
                {
                    Style = SKPaintStyle.StrokeAndFill,
                    Color = TooltipBackgroundColor
                })
                {
                    var leftRightMargin = TooltipTextSize / 2;
                    canvas.DrawRoundRect(new SKRect(textPath.Bounds.Left - leftRightMargin, textPath.Bounds.Top - topBottomMargin, textPath.Bounds.Right + leftRightMargin, textPath.Bounds.Bottom + topBottomMargin), TooltipRadius, TooltipRadius, tooltipBackgroundPaint);
                }

                canvas.DrawText(entry.Label, _tooltipPoint.X, tooltipTextYPosition, textPaint);
            }
        }
Esempio n. 4
0
        private static MemoryStream CreateCallbackImage(City city)
        {
            using var paint = new SKPaint
                  {
                      Color    = new SKColor((byte)Random.Next(0, 256), (byte)Random.Next(0, 256), (byte)Random.Next(0, 256)),
                      Typeface = SKTypeface.FromFamilyName(null, SKFontStyleWeight.Bold, SKFontStyleWidth.Normal,
                                                           SKFontStyleSlant.Upright),
                      TextSize = 20
                  };

            SKRect bounds;

            using (var textPath = paint.GetTextPath(city.Name, 0, 0))
            {
                // Set transform to center and enlarge clip path to window height
                textPath.GetTightBounds(out bounds);
            }

            using (var bitmap = new SKBitmap((int)(bounds.Width + 1), (int)(bounds.Height + 1)))
                using (var canvas = new SKCanvas(bitmap))
                {
                    canvas.Clear();
                    canvas.DrawText(city.Name, -bounds.Left, -bounds.Top, paint);
                    var memStream = new MemoryStream();
                    using (var wStream = new SKManagedWStream(memStream))
                    {
                        bitmap.Encode(wStream, SKEncodedImageFormat.Png, 100);
                    }
                    return(memStream);
                }
        }
Esempio n. 5
0
        public GlobularTextPage()
        {
            Title = "Globular Text";

            canvasView = new SKCanvasView();
            canvasView.PaintSurface += OnCanvasViewPaintSurface;
            Content = canvasView;

            using (SKPaint textPaint = new SKPaint())
            {
                textPaint.Typeface = SKTypeface.FromFamilyName("Times New Roman");
                textPaint.TextSize = 100;

                using (SKPath textPath = textPaint.GetTextPath("HELLO", 0, 0))
                {
                    SKRect textPathBounds;
                    textPath.GetBounds(out textPathBounds);

                    globePath = textPath.CloneWithTransform((SKPoint pt) =>
                    {
                        double longitude = (Math.PI / textPathBounds.Width) * (pt.X - textPathBounds.Left) - Math.PI / 2;
                        double latitude  = (Math.PI / textPathBounds.Height) * (pt.Y - textPathBounds.Top) - Math.PI / 2;

                        longitude *= 0.75;
                        latitude  *= 0.75;

                        float x = (float)(Math.Cos(latitude) * Math.Sin(longitude));
                        float y = (float)Math.Sin(latitude);

                        return(new SKPoint(x, y));
                    });
                }
            }
        }
Esempio n. 6
0
        public void GetTextPathSucceedsForEmtptyString()
        {
            var paint = new SKPaint();

            paint.TextEncoding = SKTextEncoding.Utf8;

            Assert.NotNull(paint.GetTextPath("", 0, 0));
        }
Esempio n. 7
0
        public static void Save(Dictionary <int, ushort> characterToGlyphMap, SKTypeface typeface, float textSize, string fill, string outputDirectory, ZipArchive?zipArchive)
        {
            var skColor = new SKColor(0x00, 0x00, 0x00);

            using var skTextPaint = new SKPaint
                  {
                      IsAntialias   = true,
                      Color         = skColor,
                      Typeface      = typeface,
                      TextEncoding  = SKTextEncoding.Utf32,
                      TextSize      = textSize,
                      TextAlign     = SKTextAlign.Center,
                      LcdRenderText = true,
                      SubpixelText  = true
                  };

            var metrics  = skTextPaint.FontMetrics;
            var mAscent  = metrics.Ascent;
            var mDescent = metrics.Descent;

            foreach (var kvp in characterToGlyphMap)
            {
                var   charCode = kvp.Key;
                var   utf32    = Char.ConvertFromUtf32((int)charCode);
                float x        = 0;
                float y        = (mAscent / 2.0f) - mDescent / 2.0f;

                using var outlinePath = skTextPaint.GetTextPath(utf32, x, y);
                using var fillPath    = skTextPaint.GetFillPath(outlinePath);

                fillPath.Transform(SKMatrix.CreateTranslation(-fillPath.Bounds.Left, -fillPath.Bounds.Top));

                var bounds      = fillPath.Bounds;
                var svgPathData = fillPath.ToSvgPathData();

                var sb = new StringBuilder();

                sb.AppendLine($"<svg viewBox=\"{bounds.Left} {bounds.Top} {bounds.Width} {bounds.Height}\" xmlns=\"http://www.w3.org/2000/svg\">"); // width=\"{bounds.Width}\" height=\"{bounds.Height}\"
                sb.AppendLine($"  <path fill=\"{fill}\" d=\"{svgPathData}\"/>");
                sb.AppendLine($"</svg>");

                var svg = sb.ToString();

                var outputPath = Path.Combine(outputDirectory, $"{charCode.ToString("X2").PadLeft(5, '0')}_{typeface.FamilyName}.svg");

                if (zipArchive != null)
                {
                    var zipArchiveEntry = zipArchive.CreateEntry(outputPath);
                    using var streamWriter = new StreamWriter(zipArchiveEntry.Open());
                    streamWriter.Write(svg);
                }
                else
                {
                    using var streamWriter = File.CreateText(outputPath);
                    streamWriter.Write(svg);
                }
            }
        }
Esempio n. 8
0
        /// <summary>
        /// Returns a font scale value based on the size of the letter X in a given typeface.
        /// </summary>
        /// <param name="typeface">The typeface to measure the scale from.</param>
        /// <returns>A float value typically between 0 and 1. Many common typefaces have values around 0.5.</returns>
        internal static float GetFontScale(SKTypeface typeface)
        {
            var text = "X";

            using var paint = new SKPaint
                  {
                      Typeface = typeface,
                      TextSize = 1
                  };
            var rect = paint.GetTextPath(text, 0, 0).ComputeTightBounds();

            return((rect.Width + rect.Height) / 2);
        }
Esempio n. 9
0
        private void DrawShadow(SKCanvas canvas, SKTypeface font, string text = "Xamarin", int x = 0, int y    = 0, int fontsize = 200, int strokewidth = 2,
                                string shadowcolor = "#AAffff00", string shadowg1 = "#ff0000", string shadowg2 = "#cccccc")
        {
            using (SKPaint measurepaint = new SKPaint())
            {
                measurepaint.Style       = SKPaintStyle.Fill;
                measurepaint.IsAntialias = true;
                measurepaint.Typeface    = font;
                measurepaint.TextSize    = (float)fontsize;

                using (SKPath textPath = measurepaint.GetTextPath(text, (float)x, (float)y + (float)fontsize))
                {
                    using (SKPaint paint2 = new SKPaint())
                    {
                        paint2.IsAntialias = true;
                        paint2.StrokeMiter = 1000;
                        paint2.StrokeCap   = SKStrokeCap.Round;
                        paint2.StrokeJoin  = SKStrokeJoin.Round;
                        paint2.Style       = SKPaintStyle.StrokeAndFill;
                        paint2.StrokeWidth = (float)strokewidth;


                        if (Gradient)
                        {
                            paint2.Color = FromString(shadowcolor);
                        }
                        else
                        {
                            paint2.Color = FromString(shadowg1);
                        }

                        paint2.Typeface = font;
                        paint2.TextSize = (float)fontsize;

                        SKRect textBounds = textPath.Bounds;
                        if (Gradient)
                        {
                            paint2.Shader = SKShader.CreateLinearGradient(
                                new SKPoint(textBounds.Left + textBounds.Width * 0.5f, textBounds.Top),
                                new SKPoint(textBounds.Left + textBounds.Width * 0.5f, textBounds.Bottom),
                                new SKColor[] { FromString(shadowg1), FromString(shadowg2) }, null,
                                SKShaderTileMode.Clamp);
                        }

                        paint2.ImageFilter = SKImageFilter.CreateDropShadow(8, 8, 4, 4, FromString(shadowcolor), SKDropShadowImageFilterShadowMode.DrawShadowOnly);

                        canvas.DrawPath(textPath, paint2);
                    }
                }
            }
        }
Esempio n. 10
0
        public static void Test(string outputDirectory)
        {
            int width  = 500;
            int height = 500;


            SKRect svgBounds = SKRect.Create(0, 0, 100, 100);

            outputDirectory = System.IO.Path.Combine(outputDirectory, "SkiaTestFile.svg");

            using (SKFileWStream stream = new SKFileWStream(outputDirectory)) // there are a few types of streams
            {
                using (SKCanvas canvas = SKSvgCanvas.Create(svgBounds, stream))

                // SKBitmap bitmap = new SKBitmap(width, height);
                // using (SKCanvas canvas = new SKCanvas(bitmap))
                {
                    using (SKPaint paint = new SKPaint())
                    {
                        paint.Typeface = SKTypeface.FromFamilyName(null, SKTypefaceStyle.Bold);
                        paint.TextSize = 10;

                        // paint.Style = SKPaintStyle.Stroke;
                        // paint.StrokeWidth = 1;
                        // paint.Color = SKColors.Red;

                        using (SKPath textPath = paint.GetTextPath("CODE", 0, 0))
                        {
                            // Set transform to center and enlarge clip path to window height
                            SKRect bounds;
                            textPath.GetTightBounds(out bounds);

                            // canvas.Translate(width / 2, height/ 2);
                            // canvas.Scale(width / bounds.Width, height / bounds.Height);
                            // canvas.Translate(-bounds.MidX, -bounds.MidY);

                            canvas.Translate(-bounds.Left, -bounds.Top);

                            // Set the clip path
                            // canvas.ClipPath(textPath);
                            canvas.DrawPath(textPath, paint);
                        } // End Using textPath
                    }     // End Using paint
                }         // End Using canvas
            }             // End Using stream

            // string foo = bitmap.ToString();
            //System.Console.WriteLine(foo);
            System.Console.WriteLine("text");
        }
        void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
        {
            SKImageInfo info    = args.Info;
            SKSurface   surface = args.Surface;
            SKCanvas    canvas  = surface.Canvas;

            canvas.Clear();

            using (SKPaint textPaint = new SKPaint())
            {
                // Set Style for the character outlines
                textPaint.Style = SKPaintStyle.Stroke;

                // Set TextSize based on screen size
                textPaint.TextSize = Math.Min(info.Width, info.Height);

                // Measure the text
                SKRect textBounds;
                textPaint.MeasureText("@", ref textBounds);

                // Coordinates to center text on screen
                float xText = info.Width / 2 - textBounds.MidX;
                float yText = info.Height / 2 - textBounds.MidY;

                // Get the path for the character outlines
                using (SKPath textPath = textPaint.GetTextPath("@", xText, yText))
                {
                    // Create a new path for the outlines of the path
                    using (SKPath outlinePath = new SKPath())
                    {
                        // Convert the path to the outlines of the stroked path
                        textPaint.StrokeWidth = 25;
                        textPaint.GetFillPath(textPath, outlinePath);

                        // Stroke that new path
                        using (SKPaint outlinePaint = new SKPaint())
                        {
                            outlinePaint.Style       = SKPaintStyle.Stroke;
                            outlinePaint.StrokeWidth = 5;
                            outlinePaint.Color       = SKColors.Red;

                            canvas.DrawPath(outlinePath, outlinePaint);
                        }
                    }
                }
            }
        }
        public static void Save(Dictionary <int, ushort> characterToGlyphMap, SKTypeface typeface, float textSize, string brush, StreamWriter streamWriter)
        {
            var skColor = new SKColor(0x00, 0x00, 0x00);

            using var skTextPaint = new SKPaint
                  {
                      IsAntialias   = true,
                      Color         = skColor,
                      Typeface      = typeface,
                      TextEncoding  = SKTextEncoding.Utf32,
                      TextSize      = textSize,
                      TextAlign     = SKTextAlign.Center,
                      LcdRenderText = true,
                      SubpixelText  = true
                  };

            var metrics  = skTextPaint.FontMetrics;
            var mAscent  = metrics.Ascent;
            var mDescent = metrics.Descent;

            streamWriter.WriteLine("<Styles xmlns=\"https://github.com/avaloniaui\"");
            streamWriter.WriteLine("        xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">");
            streamWriter.WriteLine("    <Style>");
            streamWriter.WriteLine("        <Style.Resources>");

            foreach (var kvp in characterToGlyphMap)
            {
                var   charCode = kvp.Key;
                var   utf32    = Char.ConvertFromUtf32(charCode);
                float x        = 0;
                float y        = (mAscent / 2.0f) - mDescent / 2.0f;

                using var outlinePath = skTextPaint.GetTextPath(utf32, x, y);
                using var fillPath    = skTextPaint.GetFillPath(outlinePath);

                fillPath.Transform(SKMatrix.CreateTranslation(-fillPath.Bounds.Left, -fillPath.Bounds.Top));

                var svgPathData = fillPath.ToSvgPathData();

                streamWriter.WriteLine($"            <GeometryDrawing x:Key=\"{charCode.ToString("X2").PadLeft(5, '0')}\" Brush=\"{brush}\" Geometry=\"{svgPathData}\"/>"); //  x:Key=\"{key}\"
            }

            streamWriter.WriteLine("        </Style.Resources>");
            streamWriter.WriteLine("    </Style>");
            streamWriter.WriteLine("</Styles>");
        }
Esempio n. 13
0
        public unsafe void TextInterceptsAreFoundCorrectly()
        {
            var text = "|";

            var paint = new SKPaint();

            paint.TextSize = 100;

            var widths = paint.GetTextIntercepts(text, 50, 100, 0, 100);

            Assert.Equal(2, widths.Length);

            var diff = widths[1] - widths[0];

            var textPath  = paint.GetTextPath(text, 0, 0);
            var pathWidth = textPath.TightBounds.Width;

            Assert.Equal(pathWidth, diff, 2);
        }
Esempio n. 14
0
        public static SKCanvas ClippingText(this SKCanvas canvas, SKImageInfo info, string text, SKPaint paint)
        {
            using (SKPath textPath = paint.GetTextPath(text, 0, 0))
            {
                // Set transform to center and enlarge clip path to window height
                SKRect bounds;
                textPath.GetTightBounds(out bounds);
                textPath.FillType = SKPathFillType.InverseWinding;
                canvas.Translate(info.Width / 2, info.Height / 2);
                canvas.Scale((info.Width / bounds.Width) * 0.9f, (info.Height / bounds.Height) * 0.9f);
                canvas.Translate(-bounds.MidX, -bounds.MidY);

                // Set the clip path
                canvas.ClipPath(textPath);
            }

            // Reset transforms
            canvas.ResetMatrix();
            return(canvas);
        }
        public TextPathEffectPage()
        {
            Title = "Text Path Effect";

            SKCanvasView canvasView = new SKCanvasView();

            canvasView.PaintSurface += OnCanvasViewPaintSurface;
            Content = canvasView;

            // Get the bounds of textPathPaint
            SKRect textPathPaintBounds;

            textPathPaint.MeasureText(character, ref textPathPaintBounds);

            // Create textPath centered around (0, 0)
            SKPath textPath = textPathPaint.GetTextPath(character,
                                                        -textPathPaintBounds.MidX,
                                                        -textPathPaintBounds.MidY);

            // Create the path effect
            pathEffect = SKPathEffect.Create1DPath(textPath, littleSize, 0,
                                                   SKPath1DPathEffectStyle.Translate);
        }
        void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
        {
            SKImageInfo info    = args.Info;
            SKSurface   surface = args.Surface;
            SKCanvas    canvas  = surface.Canvas;

            canvas.Clear(SKColors.Blue);

            using (SKPaint paint = new SKPaint())
            {
                paint.Typeface = SKTypeface.FromFamilyName(null, SKTypefaceStyle.Bold);
                paint.TextSize = 10;

                using (SKPath textPath = paint.GetTextPath("CODE", 0, 0))
                {
                    // Set transform to center and enlarge clip path to window height
                    SKRect bounds;
                    textPath.GetTightBounds(out bounds);

                    canvas.Translate(info.Width / 2, info.Height / 2);
                    canvas.Scale(info.Width / bounds.Width, info.Height / bounds.Height);
                    canvas.Translate(-bounds.MidX, -bounds.MidY);

                    // Set the clip path
                    canvas.ClipPath(textPath);
                }
            }

            // Reset transforms
            canvas.ResetMatrix();

            // Display bitmap to fill window but maintain aspect ratio
            SKRect rect = new SKRect(0, 0, info.Width, info.Height);

            canvas.DrawBitmap(bitmap,
                              rect.AspectFill(new SKSize(bitmap.Width, bitmap.Height)));
        }
Esempio n. 17
0
        private SkiaHelper CreateSkiaHelper()
        {
            return(new SkiaHelper()
            {
                Size = new Components.RawSize
                {
                    Width = this.Width,
                    Height = this.Height
                },
                PostChain = new SkiaHelper.CanvasDelegate((SKCanvas canvas) =>
                {
                    using (var rectPaint = new SKPaint
                    {
                        StrokeWidth = 0,
                        StrokeMiter = 0,
                        StrokeJoin = SKStrokeJoin.Round,
                        StrokeCap = SKStrokeCap.Round,
                        Style = SKPaintStyle.Stroke,
                        Color = SKColor.Parse("666"),
                        TextSize = 32,
                        IsAntialias = true
                    })

                        using (var bgPaint = new SKPaint
                        {
                            StrokeWidth = 0,
                            StrokeMiter = 0,
                            StrokeJoin = SKStrokeJoin.Round,
                            StrokeCap = SKStrokeCap.Round,
                            Style = SKPaintStyle.Fill,
                            Color = SKColor.Parse("33fff9a3"),
                            TextSize = 32,
                            IsAntialias = true
                        })

                            using (var textPaint = new SKPaint
                            {
                                Typeface = SKFontManager.Default.MatchCharacter('가'),
                                StrokeWidth = 0,
                                StrokeMiter = 0,
                                StrokeJoin = SKStrokeJoin.Round,
                                StrokeCap = SKStrokeCap.Round,
                                Style = SKPaintStyle.StrokeAndFill,
                                Color = SKColor.Parse("FFFFFFFF"),
                                TextSize = 32,
                                IsAntialias = true
                            })
                                using (var outlinePaint = new SKPaint
                                {
                                    Style = textPaint.Style,
                                    Typeface = textPaint.Typeface,
                                    TextSize = textPaint.TextSize,
                                    StrokeCap = textPaint.StrokeCap,
                                    StrokeJoin = textPaint.StrokeJoin,
                                    StrokeMiter = textPaint.StrokeMiter,
                                    IsAntialias = textPaint.IsAntialias,

                                    StrokeWidth = 3,
                                    Color = SKColor.Parse("FF4374D9"),
                                })
                                    using (var outline2Paint = new SKPaint
                                    {
                                        Style = textPaint.Style,
                                        Typeface = textPaint.Typeface,
                                        TextSize = textPaint.TextSize,
                                        StrokeCap = textPaint.StrokeCap,
                                        StrokeJoin = textPaint.StrokeJoin,
                                        StrokeMiter = textPaint.StrokeMiter,
                                        IsAntialias = textPaint.IsAntialias,

                                        StrokeWidth = 6,
                                        Color = SKColor.Parse("FF5CD1E5")
                                    })
                                        using (SKPaint preventPaint = new SKPaint
                                        {
                                            IsAntialias = true,
                                            StrokeWidth = 10,
                                            Style = SKPaintStyle.StrokeAndFill,
                                            Color = SKColors.Black
                                        })
                                            using (SKPath frameTextPath = new SKPath())
                                            {
                                                SKHelper.Skia_Canvas.Clear(SKColors.Transparent);

                                                float x = 10.0f;
                                                float y = 5.0f;
                                                float measuredWidth = 0;

                                                string str = SKHelper.ContentText;
                                                while (str != null && str.Length != 0)
                                                {
                                                    SKRect bounds = new SKRect();

                                                    int textLength = (int)textPaint.BreakText(str, Size.Width - 24, out measuredWidth);
                                                    outline2Paint.MeasureText(str, ref bounds);

                                                    var b = Encoding.UTF8.GetBytes(str);
                                                    var s = Encoding.UTF8.GetString(b, 0, textLength);
                                                    if (bounds.Width > this.Width)
                                                    {
                                                        textLength -= Encoding.UTF8.GetByteCount($"{s[s.Length - 1]}");
                                                    }

                                                    s = Encoding.UTF8.GetString(b, textLength, b.Length - textLength);

                                                    // 띄어쓰기가 짤리면 줄 위로 올린다
                                                    for (int i = 0; i < s.Length; i++)
                                                    {
                                                        if (s[i] == ' ')
                                                        {
                                                            textLength++;
                                                        }
                                                        else
                                                        {
                                                            break;
                                                        }
                                                    }

                                                    y += (int)bounds.Height + 2;

                                                    using (SKPath textPath = textPaint.GetTextPath(Encoding.UTF8.GetString(b, 0, textLength), x, y))
                                                        using (SKPath outlinePath = new SKPath())
                                                        {
                                                            using (SKPaint tempPaint = new SKPaint
                                                            {
                                                                IsAntialias = true,
                                                                Color = SKColors.Black
                                                            })
                                                            {
                                                                tempPaint.GetFillPath(textPath, outlinePath);
                                                                frameTextPath.AddPath(textPath, SKPathAddMode.Append);
                                                            }
                                                        }
                                                    str = Encoding.UTF8.GetString(b, (int)textLength, b.Length - (int)textLength);
                                                }

                                                SKHelper.Skia_Canvas.DrawRect(new SKRect(0, 0, Size.Width, Size.Height), bgPaint);
                                                SKHelper.Skia_Canvas.DrawRect(new SKRect(0, 0, Size.Width, Size.Height), rectPaint);

                                                SKHelper.Skia_Canvas.DrawPath(frameTextPath, outline2Paint);
                                                SKHelper.Skia_Canvas.DrawPath(frameTextPath, outlinePaint);
                                                SKHelper.Skia_Canvas.DrawPath(frameTextPath, textPaint);
                                            }
                })
            });
        }