예제 #1
0
        void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e)
        {
            var canvas = e.Surface.Canvas;

            _drawableBounds = e.Info.Rect;
            canvas.Clear();

            if (_skPath == null)
            {
                return;
            }

            SKMatrix transformMatrix   = CreateMatrix();
            SKPath   transformedSkPath = new SKPath();

            _skPath.Transform(transformMatrix, transformedSkPath);
            SKRect fillBounds = transformMatrix.MapRect(_pathFillBounds);
            SKRect strokeBounds;

            using (SKPath strokePath = new SKPath())
            {
                _skPaint.GetFillPath(transformedSkPath, strokePath);
                strokeBounds = strokePath.Bounds;
            }

            if (_fill != null)
            {
                _skPaint.Style = SKPaintStyle.Fill;

                if (_fill is GradientBrush fillGradientBrush)
                {
                    _skPaint.Shader = fillGradientBrush.CreateShader(fillBounds);
                }
                else if (_fill is SolidColorBrush fillSolidColorBrush)
                {
                    _skPaint.Color = fillSolidColorBrush.ToSolidColor();
                }

                canvas.DrawPath(transformedSkPath, _skPaint);
                _skPaint.Shader = null;
            }

            if (_stroke != null)
            {
                _skPaint.Style = SKPaintStyle.Stroke;

                if (_stroke is GradientBrush strokeGradientBrush)
                {
                    UpdatePathStrokeBounds();
                    _skPaint.Shader = strokeGradientBrush.CreateShader(strokeBounds);
                }
                else if (_stroke is SolidColorBrush strokeSolidColorBrush)
                {
                    _skPaint.Color = strokeSolidColorBrush.ToSolidColor();
                }

                canvas.DrawPath(transformedSkPath, _skPaint);
                _skPaint.Shader = null;
            }
        }
예제 #2
0
        public void GetFillPathIsWorkingWithLine()
        {
            var paint = new SKPaint();

            var thinRect = SKRect.Create(20, 10, 0, 20);
            var rect     = SKRect.Create(10, 10, 20, 20);

            var path = new SKPath();

            path.MoveTo(20, 10);
            path.LineTo(20, 30);

            var fillPath = new SKPath();
            var isFilled = paint.GetFillPath(path, fillPath);

            Assert.True(isFilled);
            Assert.Equal(thinRect, fillPath.Bounds);
            Assert.Equal(2, fillPath.PointCount);

            paint.StrokeWidth = 20;
            paint.IsStroke    = true;
            isFilled          = paint.GetFillPath(path, fillPath);

            Assert.True(isFilled);
            Assert.Equal(rect, fillPath.Bounds);
            Assert.Equal(4 + 1, fillPath.PointCount);             // +1 becuase the last point is the same as the first
            Assert.Equal(4, fillPath.Points.Distinct().Count());
        }
예제 #3
0
        void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
        {
            SKImageInfo info    = args.Info;
            SKSurface   surface = args.Surface;
            SKCanvas    canvas  = surface.Canvas;

            canvas.Clear();

            using (SKPath circlePath = new SKPath())
            {
                circlePath.AddCircle(info.Width / 2, info.Height / 2,
                                     Math.Min(info.Width / 2, info.Height / 2) -
                                     redThickStroke.StrokeWidth);

                if (!outlineThePath)
                {
                    canvas.DrawPath(circlePath, blueFill);
                    canvas.DrawPath(circlePath, redThickStroke);
                }
                else
                {
                    using (SKPath outlinePath = new SKPath())
                    {
                        redThickStroke.GetFillPath(circlePath, outlinePath);

                        canvas.DrawPath(outlinePath, blueFill);
                        canvas.DrawPath(outlinePath, redThinStroke);
                    }
                }
            }
        }
예제 #4
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);
                }
            }
        }
        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);
                        }
                    }
                }
            }
        }
예제 #6
0
        public void GetFillPathIsWorking()
        {
            var paint = new SKPaint();

            var rect = new SKRect(10, 10, 30, 30);

            var path = new SKPath();

            path.AddRect(rect);

            var fillPath = new SKPath();
            var isFilled = paint.GetFillPath(path, fillPath);

            Assert.True(isFilled);
            Assert.Equal(rect, fillPath.Bounds);
            Assert.Equal(4, fillPath.PointCount);
        }
        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>");
        }
예제 #8
0
        public bool HitTest(Point p, IShape shape)
        {
            var stroke = shape.Stroke;

            if (stroke is not null && stroke.Width < 4)
            {
                stroke = new Stroke(color: stroke.Color, width: 4);
            }
            using var path = new SKPath();
            path.AddOval(shape.Bounds.ToSk());

            using var paint = new SKPaint()
                              .SetStroke(stroke)
                              .SetFill(shape.Fill)
                              .SetPaintStyle(stroke, shape.Fill);

            using var fillPath = paint.GetFillPath(path);
            using var region   = new SKRegion(fillPath);
            return(region.Contains((int)p.X, (int)p.Y));
        }
예제 #9
0
        /// <inheritdoc/>
        public IPathShape ToStrokePathShape(IBaseShape shape)
        {
            var path = PathGeometryConverter.ToSKPath(shape, 0.0, 0.0, (value) => (float)value);

            if (path == null)
            {
                return(null);
            }
            var factory = _serviceProvider.GetService <IFactory>();
            var style   = shape.Style != null ?
                          (IShapeStyle)shape.Style?.Copy(null) :
                          factory.CreateShapeStyle(ProjectEditorConfiguration.DefaulStyleName);
            var stroke = (IColor)style.Stroke.Copy(null);
            var fill   = (IColor)style.Fill.Copy(null);

            style.Stroke  = fill;
            style.Fill    = stroke;
            using var pen = new SKPaint();
            SkiaSharpRenderer.ToSKPaintPen(style, (value) => (float)value, 96.0, 96.0, true, pen);
            var result = pen.GetFillPath(path, 1.0f);

            if (result != null)
            {
                if (result.IsEmpty)
                {
                    result.Dispose();
                    return(null);
                }
                var geometry  = PathGeometryConverter.ToPathGeometry(result, 0.0, 0.0, factory);
                var pathShape = factory.CreatePathShape(
                    "Path",
                    style,
                    geometry,
                    true,
                    false);
                result.Dispose();
                return(pathShape);
            }
            return(null);
        }
예제 #10
0
        /// <summary>
        /// Update path cache for given stroke width.
        /// </summary>
        /// <param name="strokeWidth">Stroke width.</param>
        private void UpdatePathCache(float strokeWidth)
        {
            var strokePath = new SKPath();

            // For stroke widths close to 0 simply use empty path. Render bounds are cached from fill path.
            if (Math.Abs(strokeWidth) < float.Epsilon)
            {
                _pathCache.Cache(strokePath, strokeWidth, Bounds);
            }
            else
            {
                using (var paint = new SKPaint())
                {
                    paint.IsStroke    = true;
                    paint.StrokeWidth = strokeWidth;

                    paint.GetFillPath(EffectivePath, strokePath);

                    _pathCache.Cache(strokePath, strokeWidth, strokePath.TightBounds.ToAvaloniaRect());
                }
            }
        }
        public CatsInFramePage()
        {
            Title = "Cats in Frame";

            SKCanvasView canvasView = new SKCanvasView();

            canvasView.PaintSurface += OnCanvasViewPaintSurface;
            Content = canvasView;

            // Move (0, 0) point to center of cat path
            catPath.Transform(SKMatrix.MakeTranslation(-240, -175));

            // Now catPath is 400 by 250
            // Scale it down to 160 by 100
            catPath.Transform(SKMatrix.MakeScale(0.40f, 0.40f));

            // Get the outlines of the contours of the cat path
            SKPath outlinedCatPath = new SKPath();

            catStroke.GetFillPath(catPath, outlinedCatPath);

            // Create a 2D path effect from those outlines
            SKPathEffect fillEffect = SKPathEffect.Create2DPath(
                new SKMatrix {
                ScaleX = 170, ScaleY = 110,
                TransX = 75, TransY = 80,
                Persp2 = 1
            },
                outlinedCatPath);

            // Create a 1D path effect from the scallop path
            SKPathEffect strokeEffect =
                SKPathEffect.Create1DPath(scallopPath, 75, 0, SKPath1DPathEffectStyle.Rotate);

            // Set the sum the effects to frame paint
            framePaint.PathEffect = SKPathEffect.CreateSum(fillEffect, strokeEffect);
        }
예제 #12
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);
                                            }
                })
            });
        }