Example #1
0
        public static IEnumerable <Point> GetPointsFromSVGPathsString(string svgPathsString)
        {
            List <Point> points       = new List <Point>();
            var          svgPaths     = GetSVGCommandsFromSVGPathsString(svgPathsString);
            Point        currentPoint = new Point(0, 0);

            foreach (var command in svgPaths)
            {
                switch (command.SVGCommandType)
                {
                case SVGCommandType.M:
                    currentPoint = new Point(command.XYParams.FirstOrDefault(),
                                             command.XYParams.Skip(1).FirstOrDefault());
                    points.Add(currentPoint);
                    break;

                case SVGCommandType.c:
                case SVGCommandType.C:
                    double dX = (command.SVGCommandType == SVGCommandType.c) ? currentPoint.X : 0;
                    double dY = (command.SVGCommandType == SVGCommandType.c) ? currentPoint.Y : 0;

                    Point p0 = currentPoint;
                    Point p1 = new Point(dX + command.XYParams.FirstOrDefault(),
                                         dY + command.XYParams.Skip(1).FirstOrDefault());
                    Point p2 = new Point(dX + command.XYParams.Skip(2).FirstOrDefault(),
                                         dY + command.XYParams.Skip(3).FirstOrDefault());
                    Point p3 = new Point(dX + command.XYParams.Skip(4).FirstOrDefault(),
                                         dY + command.XYParams.Skip(5).FirstOrDefault());

                    currentPoint = p3;
                    points.AddRange(SVGMath.CalculateCubicBeizer(p0, p1, p2, p3, 100));
                    break;
                }
            }

            return(points);
        }
Example #2
0
        /// <summary>
        /// Returns a list of XY coordinates for an SVG path string.
        ///
        /// Drawing lines between these coordinates will allow you to draw the SVG image (although you lose fill/colour/line thickness
        /// information).
        /// </summary>
        /// <param name="svgPathsString">SVG Path string</param>
        /// <param name="pointsPerBeizerCommand">Number of points to use for Beizer commands</param>
        /// <returns>Enumerable list of Points</returns>
        public static SVGPathData GetPointsFromSVGPathsString(string svgPathsString, int pointsPerBeizerCommand = 100)
        {
            SVGPathData  pathData     = new SVGPathData();
            List <Point> points       = new List <Point>();
            var          svgPaths     = GetSVGCommandsFromSVGPathsString(svgPathsString);
            Point        currentPoint = new Point(0, 0);
            Point?       p0           = null;
            Point?       p1           = null;
            Point?       p2           = null;
            Point?       p3           = null;
            Point?       q0           = null;
            Point?       q1           = null;
            Point?       q2           = null;

            foreach (var command in svgPaths)
            {
                // if lower case use delta values instead of absolute
                double dX          = (char.IsLower(command.SVGCommandType.ToString().FirstOrDefault())) ? currentPoint.X : 0;
                double dY          = (char.IsLower(command.SVGCommandType.ToString().FirstOrDefault())) ? currentPoint.Y : 0;
                bool   keepQValues = false;
                bool   keepPValues = false;

                // Handle commands
                switch (command.SVGCommandType)
                {
                // Fix move, this needs to return an array of SVGPathData if multiple move commands
                case SVGCommandType.m:
                case SVGCommandType.M:
                case SVGCommandType.l:
                case SVGCommandType.L:
                    for (int i = 0; i < command.XYParams.Count(); i += 2)
                    {
                        currentPoint = new Point(dX + command.XYParams[i],
                                                 dY + command.XYParams[i + 1]);

                        points.Add(currentPoint);
                    }
                    break;

                case SVGCommandType.h:
                case SVGCommandType.H:
                    for (int i = 0; i < command.XYParams.Count(); i++)
                    {
                        currentPoint = new Point(dX + command.XYParams[i],
                                                 currentPoint.Y);

                        points.Add(currentPoint);
                    }
                    break;

                case SVGCommandType.v:
                case SVGCommandType.V:
                    for (int i = 0; i < command.XYParams.Count(); i++)
                    {
                        currentPoint = new Point(currentPoint.X,
                                                 dX + command.XYParams[i]);

                        points.Add(currentPoint);
                    }
                    break;

                case SVGCommandType.c:
                case SVGCommandType.C:
                    keepPValues = true;

                    for (int i = 0; i < command.XYParams.Count(); i += 6)
                    {
                        p0 = currentPoint;
                        p1 = new Point(dX + command.XYParams[i + 0],
                                       dY + command.XYParams[i + 1]);
                        p2 = new Point(dX + command.XYParams[i + 2],
                                       dY + command.XYParams[i + 3]);
                        p3 = new Point(dX + command.XYParams[i + 4],
                                       dY + command.XYParams[i + 5]);

                        currentPoint = p3.Value;
                        points.AddRange(SVGMath.CalculateCubicBeizer(p0.Value, p1.Value, p2.Value, p3.Value, pointsPerBeizerCommand));
                    }
                    break;

                case SVGCommandType.s:
                case SVGCommandType.S:
                    keepPValues = true;

                    for (int i = 0; i < command.XYParams.Count(); i += 4)
                    {
                        p0 = currentPoint;
                        // P1 is calculatd based off of the parameters for the previous curve
                        p1 = !p2.HasValue ? currentPoint
                                              : new Point((p3.Value.X * 2) - p2.Value.X,
                                                          (p3.Value.Y * 2) - p2.Value.Y);
                        p2 = new Point(dX + command.XYParams[i + 0],
                                       dY + command.XYParams[i + 1]);
                        p3 = new Point(dX + command.XYParams[i + 2],
                                       dY + command.XYParams[i + 3]);

                        currentPoint = p3.Value;
                        points.AddRange(SVGMath.CalculateCubicBeizer(p0.Value, p1.Value, p2.Value, p3.Value, pointsPerBeizerCommand));
                    }
                    break;

                case SVGCommandType.q:
                case SVGCommandType.Q:
                    keepQValues = true;

                    for (int i = 0; i < command.XYParams.Count(); i += 4)
                    {
                        q0 = currentPoint;
                        q1 = new Point(dX + command.XYParams[i + 0],
                                       dY + command.XYParams[i + 1]);
                        q2 = new Point(dX + command.XYParams[i + 2],
                                       dY + command.XYParams[i + 3]);

                        currentPoint = q2.Value;
                        points.AddRange(SVGMath.CalculateQuadraticBeizer(q0.Value, q1.Value, q2.Value, pointsPerBeizerCommand));
                    }
                    break;

                case SVGCommandType.t:
                case SVGCommandType.T:
                    keepQValues = true;

                    for (int i = 0; i < command.XYParams.Count(); i += 2)
                    {
                        q0 = currentPoint;
                        q1 = !q2.HasValue ? currentPoint
                                              : new Point((q2.Value.X * 2) - q1.Value.X,
                                                          (q2.Value.Y * 2) - q1.Value.Y);
                        q2 = new Point(dX + command.XYParams[i + 0],
                                       dY + command.XYParams[i + 1]);

                        currentPoint = q2.Value;
                        points.AddRange(SVGMath.CalculateQuadraticBeizer(q0.Value, q1.Value, q2.Value, pointsPerBeizerCommand));
                    }
                    break;

                case SVGCommandType.z:
                case SVGCommandType.Z:
                    pathData.IsClosed = true;
                    break;

                case SVGCommandType.invalid:
                    throw new InvalidOperationException($"Invalid SVG Command {command.SVGCommandString}");
                }

                // Get rid of Q values if there is a non quadratic beizer command run in between quadratic beizer commands
                if (!keepQValues)
                {
                    q0 = null;
                    q1 = null;
                    q2 = null;
                }

                // Get rid of P values if there is a non cubic beizer command run in between cubic beizer commands
                if (!keepPValues)
                {
                    p0 = null;
                    p1 = null;
                    p2 = null;
                    p3 = null;
                }
            }

            pathData.Points = points;

            return(pathData);
        }