public void Draw(SKCanvas canvas, Matrix3X3 parentMatrix, byte parentAlpha)
        {
            if (_hidden)
            {
                return;
            }
            LottieLog.BeginSection("FillContent.Draw");
            _paint.Color = _colorAnimation.Value ?? SKColors.White;
            var alpha = (byte)(parentAlpha / 255f * _opacityAnimation.Value / 100f * 255);

            _paint.SetAlpha(alpha);

            if (_colorFilterAnimation != null)
            {
                _paint.ColorFilter = _colorFilterAnimation.Value;
            }

            _path.Reset();
            for (var i = 0; i < _paths.Count; i++)
            {
                var m = parentMatrix.ToSKMatrix();
                _path.AddPath(_paths[i].Path, ref m);
            }

            canvas.DrawPath(_path, _paint);

            LottieLog.EndSection("FillContent.Draw");
        }
Exemple #2
0
        public void CalculateRenderProperties()
        {
            if (_disposed)
            {
                throw new ObjectDisposedException("Folder");
            }

            SKPath path = new SKPath {
                FillType = SKPathFillType.Winding
            };

            foreach (ProfileElement child in Children)
            {
                if (child is RenderProfileElement effectChild && effectChild.Path != null)
                {
                    path.AddPath(effectChild.Path);
                }
            }

            Path = path;

            // Folder render properties are based on child paths and thus require an update
            if (Parent is Folder folder)
            {
                folder.CalculateRenderProperties();
            }

            OnRenderPropertiesUpdated();
        }
Exemple #3
0
        private static SKPath CreateWKBMultiPolygon(BinaryReader reader, WkbByteOrder byteOrder, Func <SKPoint, SKPoint> geoToPixel)
        {
            SKPath gp = new SKPath();

            // Get the number of Polygons.
            int numPolygons = (int)ReadUInt32(reader, byteOrder);

            // Loop on the number of polygons.
            for (int i = 0; i < numPolygons; i++)
            {
                // read polygon header
                reader.ReadByte();
                ReadUInt32(reader, byteOrder);
                var p = CreateWKBPolygon(reader, byteOrder, geoToPixel);

                // TODO: Validate type

                // Create the next polygon and add it to the array.
                if (p != null)
                {
                    gp.AddPath(p, SKPathAddMode.Append);
                }
            }

            //Create and return the MultiPolygon.
            if (gp.PointCount > 0)
            {
                return(gp);
            }
            else
            {
                return(null);
            }
        }
        public static void Draw(IssoCrossSection section, SKCanvas canvas, float ScaleFactor, IssoPoint2D Origin)
        {
            SKPath   secPath   = new SKPath();
            SKMatrix scale     = SKMatrix.MakeScale(ScaleFactor, ScaleFactor);
            SKMatrix translate = SKMatrix.MakeTranslation(-Origin.X * ScaleFactor, -Origin.Y * ScaleFactor);

            secPath.AddPath(section.SectionContour);
            secPath.Transform(scale);
            secPath.Transform(translate);

            canvas.DrawPath(secPath, new SKPaint()
            {
                Style       = SKPaintStyle.StrokeAndFill,
                Color       = Color.DarkBlue.ToSKColor(),
                IsAntialias = true,
                StrokeWidth = 3
            }
                            );

            canvas.DrawPath(secPath, new SKPaint()
            {
                Style       = SKPaintStyle.Stroke,
                Color       = Color.LightSkyBlue.ToSKColor(),
                IsAntialias = true,
                StrokeWidth = 3
            }
                            );
        }
        private SKPath ReadClipPathDefinition(XElement e)
        {
            if (e.Name.LocalName != "clipPath" || !e.HasElements)
            {
                return(null);
            }

            var result = new SKPath();

            foreach (var ce in e.Elements())
            {
                var path = ReadElement(ce);
                if (path != null)
                {
                    result.AddPath(path);
                }

                else
                {
                    LogOrThrow($"SVG element '{ce.Name.LocalName}' is not supported in clipPath.");
                }
            }

            return(result);
        }
 private void AddPaths()
 {
     for (var i = 0; i < _pathContents.Count; i++)
     {
         _path.AddPath(_pathContents[i].Path);
     }
 }
Exemple #7
0
 private void MakeCommonPath()
 {
     SectionContour = new SKPath();
     for (int i = 0; i < SectionElements.Count; i++)
     {
         SectionContour.AddPath(SectionElements[i].contour);
     }
 }
        private void OpFirstPathWithRest(SKPathOp op)
        {
            _remainderPath.Reset();
            _firstPath.Reset();

            for (var i = _pathContents.Count - 1; i >= 1; i--)
            {
                var content = _pathContents[i];

                if (content is ContentGroup contentGroup)
                {
                    var pathList = contentGroup.PathList;
                    for (var j = pathList.Count - 1; j >= 0; j--)
                    {
                        var path = pathList[j].Path;
                        path.Transform(contentGroup.TransformationMatrix.ToSKMatrix());
                        _remainderPath.AddPath(path);
                    }
                }
                else
                {
                    _remainderPath.AddPath(content.Path);
                }
            }

            var lastContent = _pathContents[0];

            if (lastContent is ContentGroup group)
            {
                var pathList = group.PathList;
                for (var j = 0; j < pathList.Count; j++)
                {
                    var path = pathList[j].Path;
                    path.Transform(group.TransformationMatrix.ToSKMatrix());
                    _firstPath.AddPath(path);
                }
            }
            else
            {
                _firstPath = lastContent.Path;
            }

            _firstPath.Op(_remainderPath, op, _firstPath);
        }
        private static void AddX(SKPath p)
        {
            SKPath XPath = new SKPath();

            AddY(XPath);
            SKMatrix rmatrix = SKMatrix.MakeRotationDegrees(-90, 0, 0);

            XPath.Transform(rmatrix);
            p.AddPath(XPath);
        }
        public void Draw(SKCanvas canvas, Matrix3X3 parentMatrix, byte parentAlpha)
        {
            if (_hidden)
            {
                return;
            }
            LottieLog.BeginSection("GradientFillContent.Draw");
            _path.Reset();
            for (var i = 0; i < _paths.Count; i++)
            {
                var m = parentMatrix.ToSKMatrix();
                _path.AddPath(_paths[i].Path, ref m);
            }

            //_path.ComputeBounds(out _boundsRect);

            SKShader shader;

            if (_type == GradientType.Linear)
            {
                shader = LinearGradient;
            }
            else
            {
                shader = RadialGradient;
            }
            _shaderMatrix.Set(parentMatrix);
            shader        = SKShader.CreateLocalMatrix(shader, _shaderMatrix.ToSKMatrix());
            _paint.Shader = shader;

            if (_colorFilterAnimation != null)
            {
                _paint.ColorFilter = _colorFilterAnimation.Value;
            }

            var alpha = (byte)(parentAlpha / 255f * _opacityAnimation.Value / 100f * 255);

            _paint.SetAlpha(alpha);

            canvas.DrawPath(_path, _paint);
            LottieLog.EndSection("GradientFillContent.Draw");
        }
Exemple #11
0
        public static SKPath ToSKPath(this PathGeometry path)
        {
            SKPath sk = new SKPath();

            foreach (var figure in path.Figures)
            {
                sk.AddPath(figure.ToSKPath(), SKPathAddMode.Append);
            }

            return(sk);
        }
Exemple #12
0
        internal override SKPath GetSKPath()
        {
            var path = new SKPath();

            foreach (var geometry in Children)
            {
                var geometryPath = geometry.GetSKPath();
                path.AddPath(geometryPath);
            }

            path.FillType = FillRule.ToSkiaFillType();
            return(path);
        }
Exemple #13
0
        private SkiaGeometrySource2D ToGeometrySource2D(GeometryGroup geometryGroup)
        {
            var path = new SKPath();

            foreach (var geometry in geometryGroup.Children)
            {
                var geometryPath = GetSkiaGeometry(geometry);
                path.AddPath(geometryPath.Geometry);
            }

            path.FillType = geometryGroup.FillRule.ToSkiaFillType();

            return(new SkiaGeometrySource2D(path));
        }
Exemple #14
0
        static SKPath MakePath(GeometryGroup geometryGroup)
        {
            var path = new SKPath();

            path.FillType = geometryGroup.FillRule == FillRule.Nonzero ? SKPathFillType.Winding : SKPathFillType.EvenOdd;

            foreach (Geometry child in geometryGroup.Children)
            {
                SKPath childPath = MakePath((dynamic)child);
                path.AddPath(childPath);
            }

            return(path);
        }
Exemple #15
0
        public static SKPath CreatePiePath(IEnumerable <float> sectorSizes, float outerRadius, float innerRadius = 0.0f, float spacing = 0.0f, float explodeDistance = 0.0f, SKPathDirection direction = SKPathDirection.Clockwise)
        {
            var path = new SKPath();

            float cursor = 0;
            var   sum    = sectorSizes.Sum();

            foreach (var sectorSize in sectorSizes)
            {
                var sector = CreateSectorPath(cursor, cursor + sectorSize, outerRadius, innerRadius, spacing / 2f, explodeDistance, direction);

                cursor += sectorSize;

                path.AddPath(sector, SKPath.AddMode.Append);
            }

            return(path);
        }
        public IGeometryImpl BuildGlyphRunGeometry(GlyphRun glyphRun)
        {
            if (glyphRun.GlyphTypeface.PlatformImpl is not GlyphTypefaceImpl glyphTypeface)
            {
                throw new InvalidOperationException("PlatformImpl can't be null.");
            }

            var fontRenderingEmSize = (float)glyphRun.FontRenderingEmSize;
            var skFont = new SKFont(glyphTypeface.Typeface, fontRenderingEmSize)
            {
                Size          = fontRenderingEmSize,
                Edging        = SKFontEdging.Antialias,
                Hinting       = SKFontHinting.None,
                LinearMetrics = true
            };

            SKPath path = new SKPath();

            var(currentX, currentY) = glyphRun.BaselineOrigin;

            for (var i = 0; i < glyphRun.GlyphIndices.Count; i++)
            {
                var glyph     = glyphRun.GlyphIndices[i];
                var glyphPath = skFont.GetGlyphPath(glyph);

                if (!glyphPath.IsEmpty)
                {
                    path.AddPath(glyphPath, (float)currentX, (float)currentY);
                }

                if (glyphRun.GlyphAdvances != null)
                {
                    currentX += glyphRun.GlyphAdvances[i];
                }
                else
                {
                    currentX += glyphPath.Bounds.Right;
                }
            }

            return(new StreamGeometryImpl(path));
        }
        public GeometryGroupImpl(FillRule fillRule, IReadOnlyList <Geometry> children)
        {
            var path = new SKPath
            {
                FillType = fillRule == FillRule.NonZero ? SKPathFillType.Winding : SKPathFillType.EvenOdd,
            };

            var count = children.Count;

            for (var i = 0; i < count; ++i)
            {
                if (children[i]?.PlatformImpl is GeometryImpl child)
                {
                    path.AddPath(child.EffectivePath);
                }
            }

            EffectivePath = path;
            Bounds        = path.Bounds.ToAvaloniaRect();
        }
Exemple #18
0
        private static SKPath GetEquallyDistributed(ComponentLoad load, float scaleFactor, IssoPoint2D origin, float ViewHeight)
        {
            SKPath p      = new SKPath();
            float  Angle  = load.Direction * (float)Math.PI / 180f;
            float  length = IssoDist.PointDst(load.AppNodes[0].Location, load.AppNodes[1].Location);
            float  dx     = (load.AppNodes[1].Location.X - load.AppNodes[0].Location.X) * scaleFactor;
            float  dy     = -(load.AppNodes[1].Location.Y - load.AppNodes[0].Location.Y) * scaleFactor;

            float ArrawHeight = ViewHeight / 30;
            float step        = ViewHeight / 70;

            int     stepcnt = Math.Max((int)Math.Round(length * scaleFactor / step, 0), 1);
            SKPoint start   = IssoConvert.IssoPoint2DToSkPoint(load.AppNodes[0].Location, scaleFactor, origin, ViewHeight);

            dx = dx / stepcnt;
            dy = dy / stepcnt;

            SKMatrix rotate = SKMatrix.MakeRotation(-Angle);

            for (int i = 0; i < stepcnt + 1; i++)
            {
                SKPath arrow = GetDistibutedArrow((load.Value > 0) || (load.isOrthogonal && load.isReverse));

                arrow.Transform(SKMatrix.MakeScale(ArrawHeight, ArrawHeight));
                arrow.Transform(rotate);

                p.AddPath(arrow, start.X, start.Y);

                start.X += dx;
                start.Y += dy;
            }
            start = IssoConvert.IssoPoint2DToSkPoint(load.AppNodes[0].Location, scaleFactor, origin, ViewHeight);
            SKPoint end = IssoConvert.IssoPoint2DToSkPoint(load.AppNodes[1].Location, scaleFactor, origin, ViewHeight);

            p.MoveTo(start.X + ArrawHeight * (float)Math.Cos(Angle),
                     start.Y - ArrawHeight * (float)Math.Sin(Angle));
            p.LineTo(end.X + ArrawHeight * (float)Math.Cos(Angle),
                     end.Y - ArrawHeight * (float)Math.Sin(Angle));

            return(p);
        }
 public static void Set(this SKPath sKPath, SKPath path)
 {
     sKPath.Reset();
     sKPath.FillType = path.FillType;
     sKPath.AddPath(path);
 }
Exemple #20
0
 public void AddPath(GraphicsPath other, bool connect)
 {
     skPath.AddPath(other.skPath, SKPathAddMode.Append);
 }
Exemple #21
0
        /// <summary>
        /// Draws a 3D surface connecting the two specified points in 2D space.
        /// Used to draw Line based charts.
        /// </summary>
        /// <param name="area">Chart area reference.</param>
        /// <param name="graph">Chart graphics.</param>
        /// <param name="matrix">Coordinates transformation matrix.</param>
        /// <param name="lightStyle">LightStyle style (None, Simplistic, Realistic).</param>
        /// <param name="prevDataPointEx">Previous data point object.</param>
        /// <param name="positionZ">Z position of the back side of the 3D surface.</param>
        /// <param name="depth">Depth of the 3D surface.</param>
        /// <param name="points">Array of points.</param>
        /// <param name="pointIndex">Index of point to draw.</param>
        /// <param name="pointLoopIndex">Index of points loop.</param>
        /// <param name="tension">Line tension.</param>
        /// <param name="operationType">AxisName of operation Drawing, Calculating Path or Both</param>
        /// <param name="topDarkening">Darkenning scale for top surface. 0 - None.</param>
        /// <param name="bottomDarkening">Darkenning scale for bottom surface. 0 - None.</param>
        /// <param name="thirdPointPosition">Position where the third point is actually located or float.NaN if same as in "firstPoint".</param>
        /// <param name="fourthPointPosition">Position where the fourth point is actually located or float.NaN if same as in "secondPoint".</param>
        /// <param name="clippedSegment">Indicates that drawn segment is 3D clipped. Only top/bottom should be drawn.</param>
        /// <returns>Returns elemnt shape path if operationType parameter is set to CalcElementPath, otherwise Null.</returns>
        protected override SKPath Draw3DSurface(
            ChartArea area,
            ChartGraphics graph,
            Matrix3D matrix,
            LightStyle lightStyle,
            DataPoint3D prevDataPointEx,
            float positionZ,
            float depth,
            ArrayList points,
            int pointIndex,
            int pointLoopIndex,
            float tension,
            DrawingOperationTypes operationType,
            float topDarkening,
            float bottomDarkening,
            SKPoint thirdPointPosition,
            SKPoint fourthPointPosition,
            bool clippedSegment)
        {
            // Create graphics path for selection
            SKPath resultPath = ((operationType & DrawingOperationTypes.CalcElementPath) == DrawingOperationTypes.CalcElementPath)
                ? new SKPath() : null;

            // Check if points are drawn from sides to center (do only once)
            if (centerPointIndex == int.MaxValue)
            {
                centerPointIndex = GetCenterPointIndex(points);
            }

            //************************************************************
            //** Find line first & second points
            //************************************************************
            DataPoint3D secondPoint     = (DataPoint3D)points[pointIndex];
            int         pointArrayIndex = pointIndex;
            DataPoint3D firstPoint      = ChartGraphics.FindPointByIndex(
                points,
                secondPoint.index - 1,
                (multiSeries) ? secondPoint : null,
                ref pointArrayIndex);

            // Fint point with line properties
            DataPoint3D pointAttr = secondPoint;

            if (prevDataPointEx.dataPoint.IsEmpty)
            {
                pointAttr = prevDataPointEx;
            }
            else if (firstPoint.index > secondPoint.index)
            {
                pointAttr = firstPoint;
            }

            // Adjust point visual properties
            SKColor        color     = (useBorderColor) ? pointAttr.dataPoint.BorderColor : pointAttr.dataPoint.Color;
            ChartDashStyle dashStyle = pointAttr.dataPoint.BorderDashStyle;

            if (pointAttr.dataPoint.IsEmpty && pointAttr.dataPoint.Color == SKColor.Empty)
            {
                color = SKColors.Gray;
            }
            if (pointAttr.dataPoint.IsEmpty && pointAttr.dataPoint.BorderDashStyle == ChartDashStyle.NotSet)
            {
                dashStyle = ChartDashStyle.Solid;
            }

            //************************************************************
            //** Create "middle" point
            //************************************************************
            DataPoint3D middlePoint = new();

            middlePoint.xPosition = secondPoint.xPosition;
            middlePoint.yPosition = firstPoint.yPosition;

            // Check if reversed drawing order required
            bool originalDrawOrder = true;

            if ((pointIndex + 1) < points.Count)
            {
                DataPoint3D p = (DataPoint3D)points[pointIndex + 1];
                if (p.index == firstPoint.index)
                {
                    originalDrawOrder = false;
                }
            }

            // Check in which order vertical & horizontal lines segments should be drawn
            if (centerPointIndex != int.MaxValue && pointIndex >= centerPointIndex)
            {
                originalDrawOrder = false;
            }

            // Draw two segments of the step line
            SKPath resultPathLine1, resultPathLine2;

            if (originalDrawOrder)
            {
                // Draw first line
                middlePoint.dataPoint = secondPoint.dataPoint;
                resultPathLine1       = graph.Draw3DSurface(
                    area, matrix, lightStyle, SurfaceNames.Top, positionZ, depth, color,
                    pointAttr.dataPoint.BorderColor, pointAttr.dataPoint.BorderWidth, dashStyle,
                    firstPoint, middlePoint,
                    points, pointIndex, 0f, operationType, LineSegmentType.First,
                    showPointLines, false,
                    area.ReverseSeriesOrder,
                    multiSeries, 0, true);

                // No second draw of the prev. front line required
                graph.frontLinePen = null;

                // Draw second line
                middlePoint.dataPoint = firstPoint.dataPoint;
                resultPathLine2       = graph.Draw3DSurface(
                    area, matrix, lightStyle, SurfaceNames.Top, positionZ, depth, color,
                    pointAttr.dataPoint.BorderColor, pointAttr.dataPoint.BorderWidth, dashStyle,
                    middlePoint, secondPoint,
                    points, pointIndex, 0f, operationType, LineSegmentType.Last,
                    showPointLines, false,
                    area.ReverseSeriesOrder,
                    multiSeries, 0, true);

                // No second draw of the prev. front line required
                graph.frontLinePen = null;
            }
            else
            {
                // Draw second line
                middlePoint.dataPoint = firstPoint.dataPoint;
                resultPathLine2       = graph.Draw3DSurface(
                    area, matrix, lightStyle, SurfaceNames.Top, positionZ, depth, color,
                    pointAttr.dataPoint.BorderColor, pointAttr.dataPoint.BorderWidth, dashStyle,
                    middlePoint, secondPoint,
                    points, pointIndex, 0f, operationType, LineSegmentType.Last,
                    showPointLines, false,
                    area.ReverseSeriesOrder,
                    multiSeries, 0, true);

                // No second draw of the prev. front line required
                graph.frontLinePen = null;

                // Draw first line
                middlePoint.dataPoint = secondPoint.dataPoint;
                resultPathLine1       = graph.Draw3DSurface(
                    area, matrix, lightStyle, SurfaceNames.Top, positionZ, depth, color,
                    pointAttr.dataPoint.BorderColor, pointAttr.dataPoint.BorderWidth, dashStyle,
                    firstPoint, middlePoint,
                    points, pointIndex, 0f, operationType, LineSegmentType.First,
                    showPointLines, false,
                    area.ReverseSeriesOrder,
                    multiSeries, 0, true);

                // No second draw of the prev. front line required
                graph.frontLinePen = null;
            }

            if (resultPath != null)
            {
                if (area.Common.ProcessModeRegions && resultPathLine1 != null && resultPathLine1.PointCount > 0)
                {
                    area.Common.HotRegionsList.AddHotRegion(
                        resultPathLine1,
                        false,
                        prevDataPointEx.dataPoint,
                        prevDataPointEx.dataPoint.series.Name,
                        prevDataPointEx.index - 1);
                }

                if (resultPathLine2 != null && resultPathLine2.PointCount > 0)
                {
                    resultPath.AddPath(resultPathLine2);
                }
            }
            return(resultPath);
        }
Exemple #22
0
        internal static void ApplyTrimPathIfNeeded(ref SKPath path, float startValue, float endValue, float offsetValue)
        {
            LottieLog.BeginSection("applyTrimPathIfNeeded");
            SKPath tempPath = null;

            using (var pathMeasure = new SKPathMeasure(path))
            {
                var length = pathMeasure.Length;
                if (startValue == 1f && endValue == 0f)
                {
                    LottieLog.EndSection("applyTrimPathIfNeeded");
                    return;
                }
                if (length < 1f || Math.Abs(endValue - startValue - 1) < .01)
                {
                    LottieLog.EndSection("applyTrimPathIfNeeded");
                    return;
                }
                var start    = length * startValue;
                var end      = length * endValue;
                var newStart = Math.Min(start, end);
                var newEnd   = Math.Max(start, end);

                var offset = offsetValue * length;
                newStart += offset;
                newEnd   += offset;

                // If the trim path has rotated around the path, we need to shift it back.
                if (newStart >= length && newEnd >= length)
                {
                    newStart = MiscUtils.FloorMod(newStart, length);
                    newEnd   = MiscUtils.FloorMod(newEnd, length);
                }

                if (newStart < 0)
                {
                    newStart = MiscUtils.FloorMod(newStart, length);
                }
                if (newEnd < 0)
                {
                    newEnd = MiscUtils.FloorMod(newEnd, length);
                }

                // If the start and end are equals, return an empty path.
                if (newStart == newEnd)
                {
                    path.Reset();
                    LottieLog.EndSection("applyTrimPathIfNeeded");
                    return;
                }

                if (newStart >= newEnd)
                {
                    newStart -= length;
                }

                tempPath = new SKPath();
                pathMeasure.GetSegment(newStart, newEnd, tempPath, true);

                if (newEnd > length)
                {
                    var tempPath2 = new SKPath();
                    tempPath2.Reset();
                    pathMeasure.GetSegment(0, newEnd % length, tempPath2, true);
                    tempPath.AddPath(tempPath2);
                }
                else if (newStart < 0)
                {
                    var tempPath2 = new SKPath();
                    tempPath2.Reset();
                    pathMeasure.GetSegment(length + newStart, length, tempPath2, true);
                    tempPath.AddPath(tempPath2);
                }
            }
            path = tempPath;
            LottieLog.EndSection("applyTrimPathIfNeeded");
        }
Exemple #23
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);
                                            }
                })
            });
        }
Exemple #24
0
    public static SKPath ToSKPath(this IEnumerable <BaseShapeViewModel> shapes)
    {
        var path = new SKPath
        {
            FillType = SKPathFillType.Winding
        };
        var previous = default(PointShapeViewModel);

        foreach (var shape in shapes)
        {
            switch (shape)
            {
            case LineShapeViewModel lineShape:
            {
                if (previous is null || previous != lineShape.Start)
                {
                    path.MoveTo(
                        (float)(lineShape.Start.X),
                        (float)(lineShape.Start.Y));
                }
                path.LineTo(
                    (float)(lineShape.End.X),
                    (float)(lineShape.End.Y));
                previous = lineShape.End;
            }
            break;

            case RectangleShapeViewModel rectangleShape:
            {
                path.AddRect(
                    SkiaSharpDrawUtil.CreateRect(rectangleShape.TopLeft, rectangleShape.BottomRight),
                    SKPathDirection.Clockwise);
            }
            break;

            case EllipseShapeViewModel ellipseShape:
            {
                path.AddOval(
                    SkiaSharpDrawUtil.CreateRect(ellipseShape.TopLeft, ellipseShape.BottomRight),
                    SKPathDirection.Clockwise);
            }
            break;

            case ArcShapeViewModel arcShape:
            {
                var a = new GdiArc(
                    Point2.FromXY(arcShape.Point1.X, arcShape.Point1.Y),
                    Point2.FromXY(arcShape.Point2.X, arcShape.Point2.Y),
                    Point2.FromXY(arcShape.Point3.X, arcShape.Point3.Y),
                    Point2.FromXY(arcShape.Point4.X, arcShape.Point4.Y));
                var rect = new SKRect(
                    (float)(a.X),
                    (float)(a.Y),
                    (float)(a.X + a.Width),
                    (float)(a.Y + a.Height));
                path.AddArc(rect, (float)a.StartAngle, (float)a.SweepAngle);
            }
            break;

            case CubicBezierShapeViewModel cubicBezierShape:
            {
                if (previous is null || previous != cubicBezierShape.Point1)
                {
                    path.MoveTo(
                        (float)(cubicBezierShape.Point1.X),
                        (float)(cubicBezierShape.Point1.Y));
                }
                path.CubicTo(
                    (float)(cubicBezierShape.Point2.X),
                    (float)(cubicBezierShape.Point2.Y),
                    (float)(cubicBezierShape.Point3.X),
                    (float)(cubicBezierShape.Point3.Y),
                    (float)(cubicBezierShape.Point4.X),
                    (float)(cubicBezierShape.Point4.Y));
                previous = cubicBezierShape.Point4;
            }
            break;

            case QuadraticBezierShapeViewModel quadraticBezierShape:
            {
                if (previous is null || previous != quadraticBezierShape.Point1)
                {
                    path.MoveTo(
                        (float)(quadraticBezierShape.Point1.X),
                        (float)(quadraticBezierShape.Point1.Y));
                }
                path.QuadTo(
                    (float)(quadraticBezierShape.Point2.X),
                    (float)(quadraticBezierShape.Point2.Y),
                    (float)(quadraticBezierShape.Point3.X),
                    (float)(quadraticBezierShape.Point3.Y));
                previous = quadraticBezierShape.Point3;
            }
            break;

            case TextShapeViewModel textShape:
            {
                var resultPath = ToSKPath(textShape);
                if (resultPath is { } && !resultPath.IsEmpty)
                {
                    path.AddPath(resultPath, SKPathAddMode.Append);
                }
            }
            break;
        public static SKPath ToSKPath(this IEnumerable <IBaseShape> shapes, double dx, double dy, Func <double, float> scale)
        {
            var path = new SKPath
            {
                FillType = SKPathFillType.Winding
            };
            var previous = default(IPointShape);

            foreach (var shape in shapes)
            {
                switch (shape)
                {
                case ILineShape lineShape:
                {
                    if (previous == null || previous != lineShape.Start)
                    {
                        path.MoveTo(
                            scale(lineShape.Start.X + dx),
                            scale(lineShape.Start.Y + dy));
                    }
                    path.LineTo(
                        scale(lineShape.End.X + dx),
                        scale(lineShape.End.Y + dy));
                    previous = lineShape.End;
                }
                break;

                case IRectangleShape rectangleShape:
                {
                    path.AddRect(
                        SkiaSharpRenderer.CreateRect(rectangleShape.TopLeft, rectangleShape.BottomRight, dx, dy, scale),
                        SKPathDirection.Clockwise);
                }
                break;

                case IEllipseShape ellipseShape:
                {
                    path.AddOval(
                        SkiaSharpRenderer.CreateRect(ellipseShape.TopLeft, ellipseShape.BottomRight, dx, dy, scale),
                        SKPathDirection.Clockwise);
                }
                break;

                case IArcShape arcShape:
                {
                    var a = new GdiArc(
                        Point2.FromXY(arcShape.Point1.X, arcShape.Point1.Y),
                        Point2.FromXY(arcShape.Point2.X, arcShape.Point2.Y),
                        Point2.FromXY(arcShape.Point3.X, arcShape.Point3.Y),
                        Point2.FromXY(arcShape.Point4.X, arcShape.Point4.Y));
                    var rect = new SKRect(
                        scale(a.X + dx),
                        scale(a.Y + dy),
                        scale(a.X + dx + a.Width),
                        scale(a.Y + dy + a.Height));
                    path.AddArc(rect, (float)a.StartAngle, (float)a.SweepAngle);
                }
                break;

                case ICubicBezierShape cubicBezierShape:
                {
                    if (previous == null || previous != cubicBezierShape.Point1)
                    {
                        path.MoveTo(
                            scale(cubicBezierShape.Point1.X + dx),
                            scale(cubicBezierShape.Point1.Y + dy));
                    }
                    path.CubicTo(
                        scale(cubicBezierShape.Point2.X + dx),
                        scale(cubicBezierShape.Point2.Y + dy),
                        scale(cubicBezierShape.Point3.X + dx),
                        scale(cubicBezierShape.Point3.Y + dy),
                        scale(cubicBezierShape.Point4.X + dx),
                        scale(cubicBezierShape.Point4.Y + dy));
                    previous = cubicBezierShape.Point4;
                }
                break;

                case IQuadraticBezierShape quadraticBezierShape:
                {
                    if (previous == null || previous != quadraticBezierShape.Point1)
                    {
                        path.MoveTo(
                            scale(quadraticBezierShape.Point1.X + dx),
                            scale(quadraticBezierShape.Point1.Y + dy));
                    }
                    path.QuadTo(
                        scale(quadraticBezierShape.Point2.X + dx),
                        scale(quadraticBezierShape.Point2.Y + dy),
                        scale(quadraticBezierShape.Point3.X + dx),
                        scale(quadraticBezierShape.Point3.Y + dy));
                    previous = quadraticBezierShape.Point3;
                }
                break;

                case ITextShape textShape:
                {
                    var resultPath = ToSKPath(textShape, dx, dy, scale);
                    if (resultPath != null && !resultPath.IsEmpty)
                    {
                        path.AddPath(resultPath, SKPathAddMode.Append);
                    }
                }
                break;

                case IPathShape pathShape:
                {
                    var resultPath = ToSKPath(pathShape, dx, dy, scale);
                    if (resultPath != null && !resultPath.IsEmpty)
                    {
                        path.AddPath(resultPath, SKPathAddMode.Append);
                    }
                }
                break;

                case IGroupShape groupShape:
                {
                    var resultPath = ToSKPath(groupShape.Shapes, dx, dy, scale);
                    if (resultPath != null && !resultPath.IsEmpty)
                    {
                        path.AddPath(resultPath, SKPathAddMode.Append);
                    }
                }
                break;
                }
            }
            return(path);
        }
Exemple #26
0
        internal static void AddText(IToolContext context, Text text, IPointShape startPoint, IPointShape point, TextStyle style, double dx, double dy, SKPath geometry)
        {
            using (var typeface = ToSKTypeface(style.Typeface))
                using (var paint = ToSKPaintBrush(style))
                {
                    paint.Typeface     = typeface;
                    paint.TextEncoding = SKTextEncoding.Utf16;
                    paint.TextSize     = (float)style.FontSize;

                    switch (style.HAlign)
                    {
                    default:
                    case HAlign.Left:
                        paint.TextAlign = SKTextAlign.Left;
                        break;

                    case HAlign.Center:
                        paint.TextAlign = SKTextAlign.Center;
                        break;

                    case HAlign.Right:
                        paint.TextAlign = SKTextAlign.Right;
                        break;
                    }

                    var   metrics  = paint.FontMetrics;
                    var   mAscent  = metrics.Ascent;
                    var   mDescent = metrics.Descent;
                    var   rect     = ToSKRect(startPoint, point, dx, dy);
                    float x        = rect.Left;
                    float y        = rect.Top;
                    float width    = rect.Width;
                    float height   = rect.Height;

                    switch (style.VAlign)
                    {
                    default:
                    case VAlign.Top:
                        y -= mAscent;
                        break;

                    case VAlign.Center:
                        y += (height / 2.0f) - (mAscent / 2.0f) - mDescent / 2.0f;
                        break;

                    case VAlign.Bottom:
                        y += height - mDescent;
                        break;
                    }

                    switch (style.HAlign)
                    {
                    default:
                    case HAlign.Left:
                        // x = x;
                        break;

                    case HAlign.Center:
                        x += width / 2.0f;
                        break;

                    case HAlign.Right:
                        x += width;
                        break;
                    }

                    using (var outlineGeometry = paint.GetTextPath(text.Value, x, y))
                        using (var fillGeometry = paint.GetFillPath(outlineGeometry))
                        {
                            geometry.AddPath(fillGeometry, SKPathAddMode.Append);
                        }
                }
        }