示例#1
0
        /// <summary>
        /// Compiles the stroke to the necessary triangles to draw it.
        /// </summary>
        /// <param name="path">The path to be compiled.</param>
        /// <param name="width">The width of the stroke.</param>
        /// <param name="lineCap">The line cap method for the stroke's ends.</param>
        /// <param name="lineJoin">The line join method for the stroke's midpoints</param>
        /// <param name="miterLimit">The miter limit value.</param>
        public static CompiledDrawing CompileStroke(SvgPathSegmentList path, double width,
                                                    SvgStrokeLineCap lineCap   = SvgStrokeLineCap.Butt,
                                                    SvgStrokeLineJoin lineJoin = SvgStrokeLineJoin.Bevel,
                                                    double miterLimit          = double.PositiveInfinity)
        {
            // Return empty if stroke width == 0
            if (width == 0)
            {
                return(CompiledDrawing.Empty);
            }

            // Divide the width by 2 to cope with the SVG documentation
            var halfWidth = width / 2;

            var curves = new List <Curve>();

            // Convert each split path to a fill
            foreach (var data in path.SplitCurves())
            {
                curves.AddRange(StrokeUtils.ConvertToFill(data, halfWidth, lineCap, lineJoin, miterLimit));
            }

            // And compile
            return(CompileCurves(curves, SvgFillRule.NonZero));
        }
示例#2
0
        public static DoubleMatrix BoundingBoxMatrix(this SvgPathSegmentList path)
        {
            var bbox = path.BoundingBox();

            return(new DoubleMatrix(1 / bbox.Width, 0, 0, 1 / bbox.Height,
                                    -bbox.X / bbox.Width, -bbox.Y / bbox.Height));
        }
示例#3
0
        /// <summary>
        /// Parses the specified string into a collection of path segments.
        /// </summary>
        /// <param name="path">A <see cref="string"/> containing path data.</param>
        public static SvgPathSegmentList Parse(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException("path");
            }

            var segments = new SvgPathSegmentList();

            try {
                char command;
                bool isRelative;

                foreach (var commandSet in SplitCommands(path.TrimEnd(null)))
                {
                    command    = commandSet[0];
                    isRelative = char.IsLower(command);
                    // http://www.w3.org/TR/SVG11/paths.html#PathDataGeneralInformation

                    CreatePathSegment(command, segments, new CoordinateParser(commandSet.Trim()), isRelative);
                }
            }
            catch (Exception exc) {
                Trace.TraceError("Error parsing path \"{0}\": {1}", path, exc.Message);
                //OSS:Fix:Tell us there was a problem
                //segments.Clear();
            }

            return(segments);
        }
示例#4
0
        public void DrawPath(IEnumerable <IEnumerable <Point> > points, bool winding, GraphicsContext context,
                             DeviceDescription description)
        {
            var svgContext = _mapper.MapGraphicsContextToSvg(context);

            foreach (var point in points)
            {
                var vertices = point.ToList();
                var list     = new SvgPathSegmentList();
                var first    = vertices.First();
                list.Add(new SvgMoveToSegment(new PointF((float)first.X, (float)first.Y)));

                foreach (var vertex in vertices.Skip(1))
                {
                    list.Add(new SvgLineSegment(new PointF((float)first.X, (float)first.Y),
                                                new PointF((float)vertex.X, (float)vertex.Y)));
                    first = vertex;
                }

                list.Add(new SvgClosePathSegment());
                AddChild(new SvgPath
                {
                    Fill            = svgContext.Fill,
                    FillOpacity     = svgContext.Opacity,
                    PathData        = list,
                    Stroke          = svgContext.Pen.Stroke,
                    StrokeDashArray = svgContext.Pen.StrokeDashArray,
                    StrokeLineCap   = svgContext.Pen.StrokeLineCap,
                    StrokeLineJoin  = svgContext.Pen.StrokeLineJoin,
                    StrokeWidth     = svgContext.Pen.StrokeWidth
                });
            }
        }
示例#5
0
        /// <summary>
        /// Parses the specified string into a collection of path segments.
        /// </summary>
        /// <param name="path">A <see cref="string"/> containing path data.</param>
        public static SvgPathSegmentList Parse(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException("path");
            }

            var segments = new SvgPathSegmentList();

            try
            {
                List<float> coords;
                char command;
                bool isRelative;

                foreach (var commandSet in SplitCommands(path.TrimEnd(null)))
                {
                    coords = new List<float>(ParseCoordinates(commandSet.Trim()));
                    command = commandSet[0];
                    isRelative = char.IsLower(command);
                    // http://www.w3.org/TR/SVG11/paths.html#PathDataGeneralInformation

                    CreatePathSegment(command, segments, coords, isRelative);
                }
            }
            catch (Exception exc)
            {
                Trace.TraceError("Error parsing path \"{0}\": {1}", path, exc.Message);
            }

            return segments;
        }
示例#6
0
        /// <summary>
        ///     Parses the specified string into a collection of path segments.
        /// </summary>
        /// <param name="path">A <see cref="string" /> containing path data.</param>
        public static void Parse(Path path, string pathString)
        {
            if (string.IsNullOrEmpty(pathString))
            {
                throw new ArgumentNullException("pathString");
            }

            var segments = new SvgPathSegmentList();

            try
            {
                char command;
                bool isRelative;

                foreach (var commandSet in SplitCommands(pathString.TrimEnd(null)))
                {
                    command    = commandSet[0];
                    isRelative = char.IsLower(command);
                    // http://www.w3.org/TR/SVG11/paths.html#PathDataGeneralInformation

                    CreatePathSegment(command, segments, new CoordinateParser(commandSet.Trim()), isRelative);
                }

                foreach (var segment in segments)
                {
                    segment.AddToPath(path);
                }
            }
            catch (Exception exc)
            {
                throw new Exception(string.Format("Error parsing path \"{0}\": {1}", path, exc.Message));
            }

            //return segments;
        }
示例#7
0
        private static SvgPath ConvertArc(Arc arc)
        {
            SvgPath svgPath = new SvgPath();

            SvgPathSegmentList svgPathSegmentList = new SvgPathSegmentList();

            svgPathSegmentList.Add(new SvgMoveToSegment(arc.GetEndPoint(0).ConvertToPointF()));

            XYZ a = arc.GetEndPoint(0) - arc.Center;
            XYZ b = arc.GetEndPoint(1) - arc.Center;

            double angleAboutAxis = a.AngleOnPlaneTo(b, arc.Normal);


            SvgArcSweep svgArcSweep = SvgArcSweep.Positive;

            if (angleAboutAxis >= 180)
            {
                svgArcSweep = SvgArcSweep.Negative;
            }

            SvgArcSize svgArcSize = SvgArcSize.Small;

            SvgArcSegment svgArcSegment = new SvgArcSegment(svgPathSegmentList.Last.End, (float)arc.Radius, (float)arc.Radius, (float)angleAboutAxis, svgArcSize, svgArcSweep, arc.GetEndPoint(1).ConvertToPointF());

            svgPathSegmentList.Add(svgArcSegment);
            svgPath.PathData = svgPathSegmentList;

            return(svgPath);
        }
示例#8
0
        /// <summary>
        /// Creates point with absolute coorindates.
        /// </summary>
        /// <param name="x">Raw X-coordinate value.</param>
        /// <param name="y">Raw Y-coordinate value.</param>
        /// <param name="segments">Current path segments.</param>
        /// <param name="isRelativeX"><b>true</b> if <paramref name="x"/> contains relative coordinate value, otherwise <b>false</b>.</param>
        /// <param name="isRelativeY"><b>true</b> if <paramref name="y"/> contains relative coordinate value, otherwise <b>false</b>.</param>
        /// <returns><see cref="PointF"/> that contains absolute coordinates.</returns>
        private static PointF ToAbsolute(float x, float y, SvgPathSegmentList segments, bool isRelativeX, bool isRelativeY)
        {
            var point = new PointF(x, y);

            if ((isRelativeX || isRelativeY) && segments.Count > 0)
            {
                var lastSegment = segments.Last;

                // if the last element is a SvgClosePathSegment the position of the previous element should be used because the position of SvgClosePathSegment is 0,0
                if (lastSegment is SvgClosePathSegment && segments.Count > 0)
                {
                    for (int i = segments.Count - 1; i >= 0; i--)
                    {
                        if (segments[i] is SvgMoveToSegment moveToSegment)
                        {
                            lastSegment = moveToSegment;
                            break;
                        }
                    }
                }

                if (isRelativeX)
                {
                    point.X += lastSegment.End.X;
                }

                if (isRelativeY)
                {
                    point.Y += lastSegment.End.Y;
                }
            }

            return(point);
        }
示例#9
0
文件: SvgPath.cs 项目: spencarik/SVG
        /// <summary>
        /// Initializes a new instance of the <see cref="SvgPath"/> class.
        /// </summary>
        public SvgPath()
        {
            var pathData = new SvgPathSegmentList();

            this.Attributes["d"] = pathData;
            pathData._owner      = this;
        }
示例#10
0
        /// <summary>
        /// Creates point with absolute coorindates.
        /// </summary>
        /// <param name="x">Raw X-coordinate value.</param>
        /// <param name="y">Raw Y-coordinate value.</param>
        /// <param name="segments">Current path segments.</param>
        /// <param name="isRelativeX"><b>true</b> if <paramref name="x"/> contains relative coordinate value, otherwise <b>false</b>.</param>
        /// <param name="isRelativeY"><b>true</b> if <paramref name="y"/> contains relative coordinate value, otherwise <b>false</b>.</param>
        /// <returns><see cref="PointF"/> that contains absolute coordinates.</returns>
        private static PointF ToAbsolute(float x, float y, SvgPathSegmentList segments, bool isRelativeX, bool isRelativeY)
        {
            var point = new PointF(x, y);

            if ((isRelativeX || isRelativeY) && segments.Count > 0)
            {
                var lastSegment = segments.Last;

                // if the last element is a SvgClosePathSegment the position of the previous element should be used because the position of SvgClosePathSegment is 0,0
                if (lastSegment is SvgClosePathSegment)
                {
                    lastSegment = segments.Reverse().OfType <SvgMoveToSegment>().First();
                }

                if (isRelativeX)
                {
                    point.X += lastSegment.End.X;
                }

                if (isRelativeY)
                {
                    point.Y += lastSegment.End.Y;
                }
            }

            return(point);
        }
示例#11
0
        /// <summary>
        ///     Parses the specified string into a collection of path segments.
        /// </summary>
        /// <param name="path">A <see cref="string" /> containing path data.</param>
        public static void Parse(Path path, string pathString)
        {
            if (string.IsNullOrEmpty(pathString))
            {
                throw new ArgumentNullException("pathString");
            }

            var segments = new SvgPathSegmentList();

            try
            {
                char command;
                bool isRelative;

                foreach (var commandSet in SplitCommands(pathString.TrimEnd(null)))
                {
                    command = commandSet[0];
                    isRelative = char.IsLower(command);
                    // http://www.w3.org/TR/SVG11/paths.html#PathDataGeneralInformation

                    CreatePathSegment(command, segments, new CoordinateParser(commandSet.Trim()), isRelative);
                }

                foreach (var segment in segments)
                {
                    segment.AddToPath(path);
                }
            }
            catch (Exception exc)
            {
                throw new Exception(string.Format("Error parsing path \"{0}\": {1}", path, exc.Message));
            }

            //return segments;
        }
示例#12
0
        /// <summary>
        /// Parses the specified string into a collection of path segments.
        /// </summary>
        /// <param name="path">A <see cref="string"/> containing path data.</param>
        public static SvgPathSegmentList Parse(string path)
        {
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }

            var segments = new SvgPathSegmentList();

            try
            {
                foreach (var commandSet in SplitCommands(path.TrimEnd(null)))
                {
                    var command    = commandSet[0];
                    var isRelative = char.IsLower(command);
                    // http://www.w3.org/TR/SVG11/paths.html#PathDataGeneralInformation

                    CreatePathSegment(command, segments, new CoordinateParser(commandSet.Trim()), isRelative);
                }
            }
            catch (Exception exc)
            {
                Trace.TraceError("Error parsing path \"{0}\": {1}", path, exc.Message);
            }

            return(segments);
        }
示例#13
0
        /// <summary>
        /// Parses the specified string into a collection of path segments.
        /// </summary>
        /// <param name="path">A <see cref="string"/> containing path data.</param>
        public static SvgPathSegmentList Parse(ReadOnlySpan <char> path)
        {
            var segments = new SvgPathSegmentList();

            try
            {
                var pathTrimmed  = path.TrimEnd();
                var commandStart = 0;
                var pathLength   = pathTrimmed.Length;

                for (var i = 0; i < pathLength; ++i)
                {
                    var currentChar = pathTrimmed[i];
                    if (char.IsLetter(currentChar) && currentChar != 'e' && currentChar != 'E') // e is used in scientific notiation. but not svg path
                    {
                        var start   = commandStart;
                        var length  = i - commandStart;
                        var command = pathTrimmed.Slice(start, length).Trim();
                        commandStart = i;

                        if (command.Length > 0)
                        {
                            var commandSetTrimmed = pathTrimmed.Slice(start, length).Trim();
                            var state             = new CoordinateParserState(ref commandSetTrimmed);
                            CreatePathSegment(commandSetTrimmed[0], segments, ref state, ref commandSetTrimmed);
                        }

                        if (pathLength == i + 1)
                        {
                            var commandSetTrimmed = pathTrimmed.Slice(i, 1).Trim();
                            var state             = new CoordinateParserState(ref commandSetTrimmed);
                            CreatePathSegment(commandSetTrimmed[0], segments, ref state, ref commandSetTrimmed);
                        }
                    }
                    else if (pathLength == i + 1)
                    {
                        var start   = commandStart;
                        var length  = i - commandStart + 1;
                        var command = pathTrimmed.Slice(start, length).Trim();

                        if (command.Length > 0)
                        {
                            var commandSetTrimmed = pathTrimmed.Slice(start, length).Trim();
                            var state             = new CoordinateParserState(ref commandSetTrimmed);
                            CreatePathSegment(commandSetTrimmed[0], segments, ref state, ref commandSetTrimmed);
                        }
                    }
                }
            }
            catch (Exception exc)
            {
                Trace.TraceError("Error parsing path \"{0}\": {1}", path.ToString(), exc.Message);
            }

            return(segments);
        }
示例#14
0
文件: SvgGlyph.cs 项目: shoff/SVG
        public override SvgElement DeepCopy <T>()
        {
            var newObj = base.DeepCopy <T>() as SvgGlyph;

            if (PathData != null)
            {
                var pathData = new SvgPathSegmentList();
                foreach (var segment in PathData)
                {
                    pathData.Add(segment.Clone());
                }
                newObj.PathData = pathData;
            }
            return(newObj);
        }
示例#15
0
        private static SvgPath ConvertLine(Line line)
        {
            SvgPath svgPath = new SvgPath();

            SvgPathSegmentList svgPathSegmentList = new SvgPathSegmentList();

            svgPathSegmentList.Add(new SvgMoveToSegment(line.GetEndPoint(0).ConvertToPointF()));

            SvgLineSegment svgLineSegment = new SvgLineSegment(svgPathSegmentList.Last.End, line.GetEndPoint(1).ConvertToPointF());

            svgPathSegmentList.Add(svgLineSegment);
            svgPath.PathData = svgPathSegmentList;


            return(svgPath);
        }
示例#16
0
        private static SvgPath ConverPolyCurve(List <Curve> curves)
        {
            SvgPath svgPath = new SvgPath();

            SvgPathSegmentList svgPathSegmentList = new SvgPathSegmentList();

            svgPathSegmentList.Add(new SvgMoveToSegment(curves[0].GetEndPoint(0).ConvertToPointF()));

            foreach (Curve curve in curves)
            {
                if (curve is Arc)
                {
                    Arc arc = (Arc)curve;

                    XYZ a = arc.GetEndPoint(0) - arc.Center;
                    XYZ b = arc.GetEndPoint(1) - arc.Center;

                    double angleAboutAxis = a.AngleOnPlaneTo(b, arc.Normal);

                    SvgArcSweep svgArcSweep = SvgArcSweep.Positive;

                    if (angleAboutAxis >= 180)
                    {
                        svgArcSweep = SvgArcSweep.Negative;
                    }

                    SvgArcSize svgArcSize = SvgArcSize.Small;

                    SvgArcSegment svgArcSegment = new SvgArcSegment(svgPathSegmentList.Last.End, (float)arc.Radius, (float)arc.Radius, (float)angleAboutAxis, svgArcSize, svgArcSweep, arc.GetEndPoint(1).ConvertToPointF());

                    svgPathSegmentList.Add(svgArcSegment);
                }
                else if (curve is Line)
                {
                    SvgLineSegment svgLineSegment = new SvgLineSegment(svgPathSegmentList.Last.End, ((Line)curve).GetEndPoint(1).ConvertToPointF());

                    svgPathSegmentList.Add(svgLineSegment);
                }
            }


            svgPath.PathData = svgPathSegmentList;

            return(svgPath);
        }
示例#17
0
        public override SvgElement DeepCopy <T>()
        {
            var newObj = base.DeepCopy <T>() as SvgPath;

            if (PathData != null)
            {
                var pathData = new SvgPathSegmentList();
                foreach (var segment in PathData)
                {
                    pathData.Add(segment.Clone());
                }
                newObj.PathData = pathData;
            }
            newObj.PathLength  = this.PathLength;
            newObj.MarkerStart = this.MarkerStart;
            newObj.MarkerEnd   = this.MarkerEnd;
            return(newObj);
        }
示例#18
0
        /// <summary>
        /// Creates point with absolute coorindates.
        /// </summary>
        /// <param name="x">Raw X-coordinate value.</param>
        /// <param name="y">Raw Y-coordinate value.</param>
        /// <param name="segments">Current path segments.</param>
        /// <param name="isRelativeX"><b>true</b> if <paramref name="x"/> contains relative coordinate value, otherwise <b>false</b>.</param>
        /// <param name="isRelativeY"><b>true</b> if <paramref name="y"/> contains relative coordinate value, otherwise <b>false</b>.</param>
        /// <returns><see cref="PointF"/> that contains absolute coordinates.</returns>
        private static PointF ToAbsolute(float x, float y, SvgPathSegmentList segments, bool isRelativeX, bool isRelativeY)
        {
            var point = new PointF(x, y);

            if ((isRelativeX || isRelativeY) && segments.Count > 0)
            {
                SvgPathSegment lastSegment = segments.Last;


                // if the last element is a SvgClosePathSegment
                // the position of the previous element should be used
                // because the position of SvgClosePathSegment is 0,0
                if (lastSegment is SvgClosePathSegment)
                {
                    SvgMoveToSegment lastMoveSegment = null;

                    for (int i = segments.Count - 1; i >= 0; --i)
                    {
                        if (segments[i] is SvgMoveToSegment)
                        {
                            lastMoveSegment = (SvgMoveToSegment)segments[i];
                            break;
                        }
                    } // Next i

                    lastSegment = lastMoveSegment; // segments.Reverse().OfType<SvgMoveToSegment>().First();
                } // End if (lastSegment is SvgClosePathSegment)

                if (isRelativeX)
                {
                    point.X += lastSegment.End.X;
                }

                if (isRelativeY)
                {
                    point.Y += lastSegment.End.Y;
                }
            }

            return(point);
        }
示例#19
0
        /// <summary>
        /// Creates point with absolute coorindates.
        /// </summary>
        /// <param name="x">Raw X-coordinate value.</param>
        /// <param name="y">Raw Y-coordinate value.</param>
        /// <param name="segments">Current path segments.</param>
        /// <param name="isRelativeX"><b>true</b> if <paramref name="x"/> contains relative coordinate value, otherwise <b>false</b>.</param>
        /// <param name="isRelativeY"><b>true</b> if <paramref name="y"/> contains relative coordinate value, otherwise <b>false</b>.</param>
        /// <returns><see cref="PointF"/> that contains absolute coordinates.</returns>
        private static PointF ToAbsolute(float x, float y, SvgPathSegmentList segments, bool isRelativeX, bool isRelativeY)
        {
            var point = new PointF(x, y);

            if ((isRelativeX || isRelativeY) && segments.Count > 0)
            {
                var lastSegment = segments.Last;

                if (isRelativeX)
                {
                    point.X += lastSegment.End.X;
                }

                if (isRelativeY)
                {
                    point.Y += lastSegment.End.Y;
                }
            }

            return(point);
        }
示例#20
0
        /// <summary>
        /// Determine the filled simple segments of a path, splitting lines and curves appropriately.
        /// </summary>
        /// <param name="path">The path that is supposed to be compiled.</param>
        /// <param name="fillRule">The fill rule used to determine the filled components</param>
        /// <returns>The set of simple path components.</returns>
        public static CompiledDrawing CompileFill(SvgPathSegmentList path, SvgFillRule fillRule = SvgFillRule.EvenOdd)
        {
            var curveData = path.SplitCurves();
            var curves    = new List <Curve>();

            foreach (var data in curveData)
            {
                // Add all open curves
                curves.AddRange(data.Curves);

                // Force close the open curves
                var p0 = data.Curves[0].At(0);
                var p1 = data.Curves[data.Curves.Length - 1].At(1);
                if (!DoubleUtils.RoughlyEquals(p0, p1))
                {
                    curves.Add(Curve.Line(p1, p0));
                }
            }

            return(CompileCurves(curves, fillRule));
        }
示例#21
0
        /// <summary>
        /// Parses the specified string into a collection of path segments.
        /// </summary>
        /// <param name="path">A <see cref="string"/> containing path data.</param>
        public static SvgPathSegmentList Parse(string path)
        {
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }

            var segments = new SvgPathSegmentList();

            try
            {
                foreach (var commandSet in SplitCommands(path.TrimEnd(null)))
                {
                    CreatePathSegment(commandSet[0], segments, new CoordinateParser(commandSet.Trim()));
                }
            }
            catch (Exception exc)
            {
                Trace.TraceError("Error parsing path \"{0}\": {1}", path, exc.Message);
            }

            return(segments);
        }
示例#22
0
文件: SvgGlyph.cs 项目: zhaojw83/SVG
        /// <summary>
        /// Initializes a new instance of the <see cref="SvgGlyph"/> class.
        /// </summary>
        public SvgGlyph()
        {
            var pathData = new SvgPathSegmentList();

            this.Attributes["d"] = pathData;
        }
示例#23
0
        public static void CreatePathSegment(char command, SvgPathSegmentList segments, List <float> coords, bool isRelative)
        {
            switch (command)
            {
            case 'm':             // relative moveto
            case 'M':             // moveto
                segments.Add(
                    new SvgMoveToSegment(ToAbsolute(coords[0], coords[1], segments, isRelative)));

                for (var i = 2; i < coords.Count; i += 2)
                {
                    segments.Add(new SvgLineSegment(segments.Last.End,
                                                    ToAbsolute(coords[i], coords[i + 1], segments, isRelative)));
                }
                break;

            case 'a':
            case 'A':
                SvgArcSize  size;
                SvgArcSweep sweep;

                for (var i = 0; i < coords.Count; i += 7)
                {
                    size  = (coords[i + 3] != 0.0f) ? SvgArcSize.Large : SvgArcSize.Small;
                    sweep = (coords[i + 4] != 0.0f) ? SvgArcSweep.Positive : SvgArcSweep.Negative;

                    // A|a rx ry x-axis-rotation large-arc-flag sweep-flag x y
                    segments.Add(new SvgArcSegment(segments.Last.End, coords[i], coords[i + 1], coords[i + 2],
                                                   size, sweep, ToAbsolute(coords[i + 5], coords[i + 6], segments, isRelative)));
                }
                break;

            case 'l':             // relative lineto
            case 'L':             // lineto
                for (var i = 0; i < coords.Count; i += 2)
                {
                    segments.Add(new SvgLineSegment(segments.Last.End,
                                                    ToAbsolute(coords[i], coords[i + 1], segments, isRelative)));
                }
                break;

            case 'H':             // horizontal lineto
            case 'h':             // relative horizontal lineto
                foreach (var value in coords)
                {
                    segments.Add(new SvgLineSegment(segments.Last.End,
                                                    ToAbsolute(value, segments.Last.End.Y, segments, isRelative, false)));
                }
                break;

            case 'V':             // vertical lineto
            case 'v':             // relative vertical lineto
                foreach (var value in coords)
                {
                    segments.Add(new SvgLineSegment(segments.Last.End,
                                                    ToAbsolute(segments.Last.End.X, value, segments, false, isRelative)));
                }
                break;

            case 'Q':             // curveto
            case 'q':             // relative curveto
                for (var i = 0; i < coords.Count; i += 4)
                {
                    segments.Add(new SvgQuadraticCurveSegment(segments.Last.End,
                                                              ToAbsolute(coords[i], coords[i + 1], segments, isRelative),
                                                              ToAbsolute(coords[i + 2], coords[i + 3], segments, isRelative)));
                }
                break;

            case 'T':             // shorthand/smooth curveto
            case 't':             // relative shorthand/smooth curveto
                for (var i = 0; i < coords.Count; i += 2)
                {
                    var lastQuadCurve = segments.Last as SvgQuadraticCurveSegment;

                    var controlPoint = lastQuadCurve != null
                                    ? Reflect(lastQuadCurve.ControlPoint, segments.Last.End)
                                    : segments.Last.End;

                    segments.Add(new SvgQuadraticCurveSegment(segments.Last.End, controlPoint,
                                                              ToAbsolute(coords[i], coords[i + 1], segments, isRelative)));
                }
                break;

            case 'C':             // curveto
            case 'c':             // relative curveto
                for (var i = 0; i < coords.Count; i += 6)
                {
                    segments.Add(new SvgCubicCurveSegment(segments.Last.End,
                                                          ToAbsolute(coords[i], coords[i + 1], segments, isRelative),
                                                          ToAbsolute(coords[i + 2], coords[i + 3], segments, isRelative),
                                                          ToAbsolute(coords[i + 4], coords[i + 5], segments, isRelative)));
                }
                break;

            case 'S':             // shorthand/smooth curveto
            case 's':             // relative shorthand/smooth curveto

                for (var i = 0; i < coords.Count; i += 4)
                {
                    var lastCubicCurve = segments.Last as SvgCubicCurveSegment;

                    var controlPoint = lastCubicCurve != null
                                    ? Reflect(lastCubicCurve.SecondControlPoint, segments.Last.End)
                                    : segments.Last.End;

                    segments.Add(new SvgCubicCurveSegment(segments.Last.End, controlPoint,
                                                          ToAbsolute(coords[i], coords[i + 1], segments, isRelative),
                                                          ToAbsolute(coords[i + 2], coords[i + 3], segments, isRelative)));
                }
                break;

            case 'Z':             // closepath
            case 'z':             // relative closepath
                segments.Add(new SvgClosePathSegment());
                break;
            }
        }
示例#24
0
        /// <summary>
        /// Gets the bounds of the element.
        /// </summary>
        /// <value>The bounds.</value>
//        public override System.Drawing.RectangleF Bounds
//        {
//            get { return this.Path.GetBounds(); }
//        }

        /// <summary>
        /// Initializes a new instance of the <see cref="SvgPath"/> class.
        /// </summary>
        public SvgPath()
        {
            this._pathData        = new SvgPathSegmentList();
            this._pathData._owner = this;
        }
示例#25
0
文件: SvgPath.cs 项目: DnevnikRu/SVG
 /// <summary>
 /// Initializes a new instance of the <see cref="SvgPath"/> class.
 /// </summary>
 public SvgPath()
 {
     this._pathData = new SvgPathSegmentList();
     this._pathData._owner = this;
 }
示例#26
0
 /// <summary>
 ///     Creates point with absolute coorindates.
 /// </summary>
 /// <param name="x">Raw X-coordinate value.</param>
 /// <param name="y">Raw Y-coordinate value.</param>
 /// <param name="segments">Current path segments.</param>
 /// <param name="isRelativeBoth">
 ///     <b>true</b> if <paramref name="x" /> and <paramref name="y" /> contains relative
 ///     coordinate values, otherwise <b>false</b>.
 /// </param>
 /// <returns><see cref="PointF" /> that contains absolute coordinates.</returns>
 private static Point ToAbsolute(double x, double y, SvgPathSegmentList segments, bool isRelativeBoth)
 {
     return(ToAbsolute(x, y, segments, isRelativeBoth, isRelativeBoth));
 }
示例#27
0
        /// <summary>
        /// Creates point with absolute coorindates.
        /// </summary>
        /// <param name="x">Raw X-coordinate value.</param>
        /// <param name="y">Raw Y-coordinate value.</param>
        /// <param name="segments">Current path segments.</param>
        /// <param name="isRelativeX"><b>true</b> if <paramref name="x"/> contains relative coordinate value, otherwise <b>false</b>.</param>
        /// <param name="isRelativeY"><b>true</b> if <paramref name="y"/> contains relative coordinate value, otherwise <b>false</b>.</param>
        /// <returns><see cref="PointF"/> that contains absolute coordinates.</returns>
        private static PointF ToAbsolute(float x, float y, SvgPathSegmentList segments, bool isRelativeX, bool isRelativeY)
        {
            var point = new PointF(x, y);

            if ((isRelativeX || isRelativeY) && segments.Count > 0)
            {
                var lastSegment = segments.Last;

                // if the last element is a SvgClosePathSegment the position of the previous element should be used because the position of SvgClosePathSegment is 0,0
                if (lastSegment is SvgClosePathSegment)
                    lastSegment = segments[segments.Count - 2];

                if (isRelativeX)
                {
                    point.X += lastSegment.End.X;
                }

                if (isRelativeY)
                {
                    point.Y += lastSegment.End.Y;
                }
            }

            return point;
        }
示例#28
0
 /// <summary>
 /// Creates point with absolute coorindates.
 /// </summary>
 /// <param name="x">Raw X-coordinate value.</param>
 /// <param name="y">Raw Y-coordinate value.</param>
 /// <param name="segments">Current path segments.</param>
 /// <param name="isRelativeBoth"><b>true</b> if <paramref name="x"/> and <paramref name="y"/> contains relative coordinate values, otherwise <b>false</b>.</param>
 /// <returns><see cref="PointF"/> that contains absolute coordinates.</returns>
 private static PointF ToAbsolute(float x, float y, SvgPathSegmentList segments, bool isRelativeBoth)
 {
     return(ToAbsolute(x, y, segments, isRelativeBoth, isRelativeBoth));
 }
示例#29
0
 /// <summary>
 /// Creates point with absolute coorindates.
 /// </summary>
 /// <param name="x">Raw X-coordinate value.</param>
 /// <param name="y">Raw Y-coordinate value.</param>
 /// <param name="segments">Current path segments.</param>
 /// <param name="isRelativeBoth"><b>true</b> if <paramref name="x"/> and <paramref name="y"/> contains relative coordinate values, otherwise <b>false</b>.</param>
 /// <returns><see cref="PointF"/> that contains absolute coordinates.</returns>
 private static PointF ToAbsolute(float x, float y, SvgPathSegmentList segments, bool isRelativeBoth)
 {
     return ToAbsolute(x, y, segments, isRelativeBoth, isRelativeBoth);
 }
示例#30
0
        private static void CreatePathSegment(char command, SvgPathSegmentList segments, ref CoordinateParserState state, ref ReadOnlySpan <char> chars)
        {
            var isRelative = char.IsLower(command);

            // http://www.w3.org/TR/SVG11/paths.html#PathDataGeneralInformation

            switch (command)
            {
            case 'M':     // moveto
            case 'm':     // relative moveto
            {
                if (CoordinateParser.TryGetFloat(out var coords0, ref chars, ref state) &&
                    CoordinateParser.TryGetFloat(out var coords1, ref chars, ref state))
                {
                    segments.Add(
                        new SvgMoveToSegment(
                            isRelative, new PointF(coords0, coords1)));
                }
                while (CoordinateParser.TryGetFloat(out coords0, ref chars, ref state) &&
                       CoordinateParser.TryGetFloat(out coords1, ref chars, ref state))
                {
                    segments.Add(
                        new SvgLineSegment(
                            isRelative, new PointF(coords0, coords1)));
                }
            }
            break;

            case 'A':     // elliptical arc
            case 'a':     // relative elliptical arc
            {
                while (CoordinateParser.TryGetFloat(out var coords0, ref chars, ref state) &&
                       CoordinateParser.TryGetFloat(out var coords1, ref chars, ref state) &&
                       CoordinateParser.TryGetFloat(out var coords2, ref chars, ref state) &&
                       CoordinateParser.TryGetBool(out var size, ref chars, ref state) &&
                       CoordinateParser.TryGetBool(out var sweep, ref chars, ref state) &&
                       CoordinateParser.TryGetFloat(out var coords3, ref chars, ref state) &&
                       CoordinateParser.TryGetFloat(out var coords4, ref chars, ref state))
                {
                    // A|a rx ry x-axis-rotation large-arc-flag sweep-flag x y
                    segments.Add(
                        new SvgArcSegment(
                            coords0,
                            coords1,
                            coords2,
                            size ? SvgArcSize.Large : SvgArcSize.Small,
                            sweep ? SvgArcSweep.Positive : SvgArcSweep.Negative,
                            isRelative, new PointF(coords3, coords4)));
                }
            }
            break;

            case 'L':     // lineto
            case 'l':     // relative lineto
            {
                while (CoordinateParser.TryGetFloat(out var coords0, ref chars, ref state) &&
                       CoordinateParser.TryGetFloat(out var coords1, ref chars, ref state))
                {
                    segments.Add(
                        new SvgLineSegment(
                            isRelative, new PointF(coords0, coords1)));
                }
            }
            break;

            case 'H':     // horizontal lineto
            case 'h':     // relative horizontal lineto
            {
                while (CoordinateParser.TryGetFloat(out var coords0, ref chars, ref state))
                {
                    segments.Add(
                        new SvgLineSegment(
                            isRelative, new PointF(coords0, float.NaN)));
                }
            }
            break;

            case 'V':     // vertical lineto
            case 'v':     // relative vertical lineto
            {
                while (CoordinateParser.TryGetFloat(out var coords0, ref chars, ref state))
                {
                    segments.Add(
                        new SvgLineSegment(
                            isRelative, new PointF(float.NaN, coords0)));
                }
            }
            break;

            case 'Q':     // quadratic bézier curveto
            case 'q':     // relative quadratic bézier curveto
            {
                while (CoordinateParser.TryGetFloat(out var coords0, ref chars, ref state) &&
                       CoordinateParser.TryGetFloat(out var coords1, ref chars, ref state) &&
                       CoordinateParser.TryGetFloat(out var coords2, ref chars, ref state) &&
                       CoordinateParser.TryGetFloat(out var coords3, ref chars, ref state))
                {
                    segments.Add(
                        new SvgQuadraticCurveSegment(
                            isRelative,
                            new PointF(coords0, coords1),
                            new PointF(coords2, coords3)));
                }
            }
            break;

            case 'T':     // shorthand/smooth quadratic bézier curveto
            case 't':     // relative shorthand/smooth quadratic bézier curveto
            {
                while (CoordinateParser.TryGetFloat(out var coords0, ref chars, ref state) &&
                       CoordinateParser.TryGetFloat(out var coords1, ref chars, ref state))
                {
                    segments.Add(
                        new SvgQuadraticCurveSegment(
                            isRelative, new PointF(coords0, coords1)));
                }
            }
            break;

            case 'C':     // curveto
            case 'c':     // relative curveto
            {
                while (CoordinateParser.TryGetFloat(out var coords0, ref chars, ref state) &&
                       CoordinateParser.TryGetFloat(out var coords1, ref chars, ref state) &&
                       CoordinateParser.TryGetFloat(out var coords2, ref chars, ref state) &&
                       CoordinateParser.TryGetFloat(out var coords3, ref chars, ref state) &&
                       CoordinateParser.TryGetFloat(out var coords4, ref chars, ref state) &&
                       CoordinateParser.TryGetFloat(out var coords5, ref chars, ref state))
                {
                    segments.Add(
                        new SvgCubicCurveSegment(
                            isRelative,
                            new PointF(coords0, coords1),
                            new PointF(coords2, coords3),
                            new PointF(coords4, coords5)));
                }
            }
            break;

            case 'S':     // shorthand/smooth curveto
            case 's':     // relative shorthand/smooth curveto
            {
                while (CoordinateParser.TryGetFloat(out var coords0, ref chars, ref state) &&
                       CoordinateParser.TryGetFloat(out var coords1, ref chars, ref state) &&
                       CoordinateParser.TryGetFloat(out var coords2, ref chars, ref state) &&
                       CoordinateParser.TryGetFloat(out var coords3, ref chars, ref state))
                {
                    segments.Add(
                        new SvgCubicCurveSegment(
                            isRelative,
                            new PointF(coords0, coords1),
                            new PointF(coords2, coords3)));
                }
            }
            break;

            case 'Z':     // closepath
            case 'z':     // relative closepath
            {
                segments.Add(new SvgClosePathSegment(isRelative));
            }
            break;
            }
        }
示例#31
0
 /// <summary>
 ///     Creates point with absolute coorindates.
 /// </summary>
 /// <param name="x">Raw X-coordinate value.</param>
 /// <param name="y">Raw Y-coordinate value.</param>
 /// <param name="segments">Current path segments.</param>
 /// <param name="isRelativeBoth">
 ///     <b>true</b> if <paramref name="x" /> and <paramref name="y" /> contains relative
 ///     coordinate values, otherwise <b>false</b>.
 /// </param>
 /// <returns><see cref="PointF" /> that contains absolute coordinates.</returns>
 private static Point ToAbsolute(double x, double y, SvgPathSegmentList segments, bool isRelativeBoth)
 {
     return ToAbsolute(x, y, segments, isRelativeBoth, isRelativeBoth);
 }
示例#32
0
        /// <summary>
        ///     Creates point with absolute coorindates.
        /// </summary>
        /// <param name="x">Raw X-coordinate value.</param>
        /// <param name="y">Raw Y-coordinate value.</param>
        /// <param name="segments">Current path segments.</param>
        /// <param name="isRelativeX">
        ///     <b>true</b> if <paramref name="x" /> contains relative coordinate value, otherwise
        ///     <b>false</b>.
        /// </param>
        /// <param name="isRelativeY">
        ///     <b>true</b> if <paramref name="y" /> contains relative coordinate value, otherwise
        ///     <b>false</b>.
        /// </param>
        /// <returns><see cref="PointF" /> that contains absolute coordinates.</returns>
        private static Point ToAbsolute(double x, double y, SvgPathSegmentList segments, bool isRelativeX,
            bool isRelativeY)
        {
            var point = new Point(x, y);

            if ((isRelativeX || isRelativeY) && segments.Count > 0)
            {
                var lastSegment = segments.Last;

                // if the last element is a SvgClosePathSegment the position of the previous element should be used because the position of SvgClosePathSegment is 0,0
                if (lastSegment is SvgClosePathSegment)
                    lastSegment = segments.Reverse().OfType<SvgMoveToSegment>().First();

                if (isRelativeX)
                {
                    point.X += lastSegment.End.X;
                }

                if (isRelativeY)
                {
                    point.Y += lastSegment.End.Y;
                }
            }

            return point;
        }
示例#33
0
        public static StrokeCollection exec(string absolutePath, int width, int height, int thickness, System.Windows.Media.Color color, bool dotted)
        {
            string filename = Path.GetFileName(absolutePath);

            if (!isPotraceDirectory)
            {
                Directory.SetCurrentDirectory(Directory.GetCurrentDirectory() + "/../../Potrace");
                isPotraceDirectory = true;
            }
            string extension = absolutePath.Substring(absolutePath.Length - 4, 4);

            if (extension.ToLower() == PNG || extension.ToLower() == JPG)
            {
                Image img = Image.FromFile(absolutePath);
                filename = filename.Substring(0, filename.Length - 4) + BMP;
                img.Save("Images/" + filename, ImageFormat.Bmp);
            }
            else if (extension.ToLower() != BMP)
            {
                throw new FileFormatException();
            }
            Process process = new Process();

            process.StartInfo.FileName               = "cmd.exe";
            process.StartInfo.CreateNoWindow         = true;
            process.StartInfo.RedirectStandardInput  = true;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.UseShellExecute        = false;
            process.Start();
            process.StandardInput.WriteLine("mkbitmap.exe -o Images/mkbitmap-o/" + filename + " Images/" + filename);
            process.StandardInput.Flush();
            process.StandardInput.WriteLine("potrace.exe --svg -o Images/potrace-o/" + filename.Substring(0, filename.Length - 4) + SVG + " -a 0 --flat -W " + width + "pt -H " + height + "pt Images/mkbitmap-o/" + filename);
            process.StandardInput.Flush();
            process.StandardInput.Close();
            process.WaitForExit();
            string svg = File.ReadAllText("Images/potrace-o/" + filename.Substring(0, filename.Length - 4) + SVG);
            SvgTransformCollection transforms   = (SvgTransformCollection) new SvgTransformConverter().ConvertFrom(svg.Substring(svg.IndexOf(TRANSFORM_KEY) + TRANSFORM_KEY.Length));
            SvgPathSegmentList     pathSegments = (SvgPathSegmentList) new SvgPathBuilder().ConvertFrom(svg.Substring(svg.IndexOf(PATH_KEY) + PATH_KEY.Length));

            PointF translate = new PointF(0, 0);
            PointF scale     = new PointF(1, 1);

            for (int i = 0; i < transforms.Count; i++)
            {
                if (transforms[i].GetType() == typeof(SvgTranslate))
                {
                    translate = new PointF(((SvgTranslate)transforms[i]).X, ((SvgTranslate)transforms[i]).Y);
                }
                else if (transforms[i].GetType() == typeof(SvgScale))
                {
                    scale = new PointF(((SvgScale)transforms[i]).X, ((SvgScale)transforms[i]).Y);
                }
            }

            StrokeCollection strokes = new StrokeCollection();

            if (dotted)
            {
                for (int i = 0; i < pathSegments.Count; i++)
                {
                    StylusPointCollection stylusPoints = new StylusPointCollection();
                    stylusPoints.Add(new StylusPoint(scale.X * pathSegments[i].Start.X + translate.X, scale.Y * pathSegments[i].Start.Y + translate.Y));
                    Stroke stroke = new Stroke(stylusPoints);
                    stroke.DrawingAttributes.Width = stroke.DrawingAttributes.Height = thickness;
                    stroke.DrawingAttributes.Color = color;
                    strokes.Add(stroke);
                }
            }
            else
            {
                for (int i = 0; i < pathSegments.Count; i++)
                {
                    if (pathSegments[i].GetType() == typeof(SvgMoveToSegment))
                    {
                        StylusPointCollection stylusPoints = new StylusPointCollection();
                        stylusPoints.Add(new StylusPoint(scale.X * pathSegments[i].Start.X + translate.X, scale.Y * pathSegments[i].Start.Y + translate.Y));
                        Stroke stroke = new Stroke(stylusPoints);
                        stroke.DrawingAttributes.Width = stroke.DrawingAttributes.Height = thickness;
                        stroke.DrawingAttributes.Color = color;
                        strokes.Add(stroke);
                    }
                    else if (pathSegments[i].GetType() == typeof(SvgLineSegment))
                    {
                        strokes[strokes.Count - 1].StylusPoints.Add(new StylusPoint(scale.X * pathSegments[i].End.X + translate.X, scale.Y * pathSegments[i].End.Y + translate.Y));
                    }
                }
            }
            if (extension.ToLower() == PNG || extension.ToLower() == JPG)
            {
                File.Delete("Images/" + filename);
            }
            File.Delete("Images/mkbitmap-o/" + filename);
            File.Delete("Images/potrace-o/" + filename.Substring(0, filename.Length - 4) + SVG);
            return(strokes);
        }
示例#34
0
        public static void CreatePathSegment(char command, SvgPathSegmentList segments, List<float> coords, bool isRelative)
        {
            switch (command)
                    {
                        case 'm': // relative moveto
                        case 'M': // moveto
                            segments.Add(
                                new SvgMoveToSegment(ToAbsolute(coords[0], coords[1], segments, isRelative)));

                            for (var i = 2; i < coords.Count; i += 2)
                            {
                                segments.Add(new SvgLineSegment(segments.Last.End,
                                    ToAbsolute(coords[i], coords[i + 1], segments, isRelative)));
                            }
                            break;
                        case 'a':
                        case 'A':
                            SvgArcSize size;
                            SvgArcSweep sweep;

                            for (var i = 0; i < coords.Count; i += 7)
                            {
                                size = (coords[i + 3] != 0.0f) ? SvgArcSize.Large : SvgArcSize.Small;
                                sweep = (coords[i + 4] != 0.0f) ? SvgArcSweep.Positive : SvgArcSweep.Negative;

                                // A|a rx ry x-axis-rotation large-arc-flag sweep-flag x y
                                segments.Add(new SvgArcSegment(segments.Last.End, coords[i], coords[i + 1], coords[i + 2],
                                    size, sweep, ToAbsolute(coords[i + 5], coords[i + 6], segments, isRelative)));
                            }
                            break;
                        case 'l': // relative lineto
                        case 'L': // lineto
                            for (var i = 0; i < coords.Count; i += 2)
                            {
                                segments.Add(new SvgLineSegment(segments.Last.End,
                                    ToAbsolute(coords[i], coords[i + 1], segments, isRelative)));
                            }
                            break;
                        case 'H': // horizontal lineto
                        case 'h': // relative horizontal lineto
                            foreach (var value in coords)
                                segments.Add(new SvgLineSegment(segments.Last.End,
                                    ToAbsolute(value, segments.Last.End.Y, segments, isRelative, false)));
                            break;
                        case 'V': // vertical lineto
                        case 'v': // relative vertical lineto
                            foreach (var value in coords)
                                segments.Add(new SvgLineSegment(segments.Last.End,
                                    ToAbsolute(segments.Last.End.X, value, segments, false, isRelative)));
                            break;
                        case 'Q': // curveto
                        case 'q': // relative curveto
                            for (var i = 0; i < coords.Count; i += 4)
                            {
                                segments.Add(new SvgQuadraticCurveSegment(segments.Last.End,
                                    ToAbsolute(coords[i], coords[i + 1], segments, isRelative),
                                    ToAbsolute(coords[i + 2], coords[i + 3], segments, isRelative)));
                            }
                            break;
                        case 'T': // shorthand/smooth curveto
                        case 't': // relative shorthand/smooth curveto
                            for (var i = 0; i < coords.Count; i += 2)
                            {
                                var lastQuadCurve = segments.Last as SvgQuadraticCurveSegment;

                                var controlPoint = lastQuadCurve != null
                                    ? Reflect(lastQuadCurve.ControlPoint, segments.Last.End)
                                    : segments.Last.End;

                                segments.Add(new SvgQuadraticCurveSegment(segments.Last.End, controlPoint,
                                    ToAbsolute(coords[i], coords[i + 1], segments, isRelative)));
                            }
                            break;
                        case 'C': // curveto
                        case 'c': // relative curveto
                            for (var i = 0; i < coords.Count; i += 6)
                            {
                                segments.Add(new SvgCubicCurveSegment(segments.Last.End,
                                    ToAbsolute(coords[i], coords[i + 1], segments, isRelative),
                                    ToAbsolute(coords[i + 2], coords[i + 3], segments, isRelative),
                                    ToAbsolute(coords[i + 4], coords[i + 5], segments, isRelative)));
                            }
                            break;
                        case 'S': // shorthand/smooth curveto
                        case 's': // relative shorthand/smooth curveto

                            for (var i = 0; i < coords.Count; i += 4)
                            {
                                var lastCubicCurve = segments.Last as SvgCubicCurveSegment;

                                var controlPoint = lastCubicCurve != null
                                    ? Reflect(lastCubicCurve.SecondControlPoint, segments.Last.End)
                                    : segments.Last.End;

                                segments.Add(new SvgCubicCurveSegment(segments.Last.End, controlPoint,
                                    ToAbsolute(coords[i], coords[i + 1], segments, isRelative),
                                    ToAbsolute(coords[i + 2], coords[i + 3], segments, isRelative)));
                            }
                            break;
                        case 'Z': // closepath
                        case 'z': // relative closepath
                            segments.Add(new SvgClosePathSegment());
                            break;
                    }
        }
示例#35
0
        private static void CreatePathSegment(char command, SvgPathSegmentList segments, CoordinateParser parser,
            bool isRelative)
        {
            var coords = new float[6];

            switch (command)
            {
                case 'm': // relative moveto
                case 'M': // moveto
                    if (parser.TryGetFloat(out coords[0]) && parser.TryGetFloat(out coords[1]))
                    {
                        segments.Add(new SvgMoveToSegment(ToAbsolute(coords[0], coords[1], segments, isRelative)));
                    }

                    while (parser.TryGetFloat(out coords[0]) && parser.TryGetFloat(out coords[1]))
                    {
                        segments.Add(new SvgLineSegment(segments.Last.End,
                            ToAbsolute(coords[0], coords[1], segments, isRelative)));
                    }
                    break;
                case 'a':
                case 'A':
                    bool size;
                    bool sweep;

                    while (parser.TryGetFloat(out coords[0]) && parser.TryGetFloat(out coords[1]) &&
                           parser.TryGetFloat(out coords[2]) && parser.TryGetBool(out size) &&
                           parser.TryGetBool(out sweep) && parser.TryGetFloat(out coords[3]) &&
                           parser.TryGetFloat(out coords[4]))
                    {
                        // A|a rx ry x-axis-rotation large-arc-flag sweep-flag x y
                        segments.Add(new SvgArcSegment(segments.Last.End, coords[0], coords[1], coords[2],
                            (size ? SvgArcSize.Large : SvgArcSize.Small),
                            (sweep ? SvgArcSweep.Positive : SvgArcSweep.Negative),
                            ToAbsolute(coords[3], coords[4], segments, isRelative)));
                    }
                    break;
                case 'l': // relative lineto
                case 'L': // lineto
                    while (parser.TryGetFloat(out coords[0]) && parser.TryGetFloat(out coords[1]))
                    {
                        segments.Add(new SvgLineSegment(segments.Last.End,
                            ToAbsolute(coords[0], coords[1], segments, isRelative)));
                    }
                    break;
                case 'H': // horizontal lineto
                case 'h': // relative horizontal lineto
                    while (parser.TryGetFloat(out coords[0]))
                    {
                        segments.Add(new SvgLineSegment(segments.Last.End,
                            ToAbsolute(coords[0], segments.Last.End.Y, segments, isRelative, false)));
                    }
                    break;
                case 'V': // vertical lineto
                case 'v': // relative vertical lineto
                    while (parser.TryGetFloat(out coords[0]))
                    {
                        segments.Add(new SvgLineSegment(segments.Last.End,
                            ToAbsolute(segments.Last.End.X, coords[0], segments, false, isRelative)));
                    }
                    break;
                case 'Q': // curveto
                case 'q': // relative curveto
                    while (parser.TryGetFloat(out coords[0]) && parser.TryGetFloat(out coords[1]) &&
                           parser.TryGetFloat(out coords[2]) && parser.TryGetFloat(out coords[3]))
                    {
                        segments.Add(new SvgQuadraticCurveSegment(segments.Last.End,
                            ToAbsolute(coords[0], coords[1], segments, isRelative),
                            ToAbsolute(coords[2], coords[3], segments, isRelative)));
                    }
                    break;
                case 'T': // shorthand/smooth curveto
                case 't': // relative shorthand/smooth curveto
                    while (parser.TryGetFloat(out coords[0]) && parser.TryGetFloat(out coords[1]))
                    {
                        var lastQuadCurve = segments.Last as SvgQuadraticCurveSegment;

                        var controlPoint = lastQuadCurve != null
                            ? Reflect(lastQuadCurve.ControlPoint, segments.Last.End)
                            : segments.Last.End;

                        segments.Add(new SvgQuadraticCurveSegment(segments.Last.End, controlPoint,
                            ToAbsolute(coords[0], coords[1], segments, isRelative)));
                    }
                    break;
                case 'C': // curveto
                case 'c': // relative curveto
                    while (parser.TryGetFloat(out coords[0]) && parser.TryGetFloat(out coords[1]) &&
                           parser.TryGetFloat(out coords[2]) && parser.TryGetFloat(out coords[3]) &&
                           parser.TryGetFloat(out coords[4]) && parser.TryGetFloat(out coords[5]))
                    {
                        segments.Add(new SvgCubicCurveSegment(segments.Last.End,
                            ToAbsolute(coords[0], coords[1], segments, isRelative),
                            ToAbsolute(coords[2], coords[3], segments, isRelative),
                            ToAbsolute(coords[4], coords[5], segments, isRelative)));
                    }
                    break;
                case 'S': // shorthand/smooth curveto
                case 's': // relative shorthand/smooth curveto
                    while (parser.TryGetFloat(out coords[0]) && parser.TryGetFloat(out coords[1]) &&
                           parser.TryGetFloat(out coords[2]) && parser.TryGetFloat(out coords[3]))
                    {
                        var lastCubicCurve = segments.Last as SvgCubicCurveSegment;

                        var controlPoint = lastCubicCurve != null
                            ? Reflect(lastCubicCurve.SecondControlPoint, segments.Last.End)
                            : segments.Last.End;

                        segments.Add(new SvgCubicCurveSegment(segments.Last.End, controlPoint,
                            ToAbsolute(coords[0], coords[1], segments, isRelative),
                            ToAbsolute(coords[2], coords[3], segments, isRelative)));
                    }
                    break;
                case 'Z': // closepath
                case 'z': // relative closepath
                    segments.Add(new SvgClosePathSegment());
                    break;
            }
        }
示例#36
0
        private static void CreatePathSegment(char command, SvgPathSegmentList segments, CoordinateParser parser, bool isRelative)
        {
            var coords = new float[6];

            switch (command)
            {
            case 'm':     // relative moveto
            case 'M':     // moveto
                if (parser.TryGetFloat(out coords[0]) && parser.TryGetFloat(out coords[1]))
                {
                    segments.Add(new SvgMoveToSegment(ToAbsolute(coords[0], coords[1], segments, isRelative)));
                }

                while (parser.TryGetFloat(out coords[0]) && parser.TryGetFloat(out coords[1]))
                {
                    segments.Add(new SvgLineSegment(segments.Last.End,
                                                    ToAbsolute(coords[0], coords[1], segments, isRelative)));
                }
                break;

            case 'a':
            case 'A':
                bool size;
                bool sweep;

                while (parser.TryGetFloat(out coords[0]) && parser.TryGetFloat(out coords[1]) &&
                       parser.TryGetFloat(out coords[2]) && parser.TryGetBool(out size) &&
                       parser.TryGetBool(out sweep) && parser.TryGetFloat(out coords[3]) &&
                       parser.TryGetFloat(out coords[4]))
                {
                    // A|a rx ry x-axis-rotation large-arc-flag sweep-flag x y
                    segments.Add(new SvgArcSegment(segments.Last.End, coords[0], coords[1], coords[2],
                                                   size ? SvgArcSize.Large : SvgArcSize.Small,
                                                   sweep ? SvgArcSweep.Positive : SvgArcSweep.Negative,
                                                   ToAbsolute(coords[3], coords[4], segments, isRelative)));
                }
                break;

            case 'l':     // relative lineto
            case 'L':     // lineto
                while (parser.TryGetFloat(out coords[0]) && parser.TryGetFloat(out coords[1]))
                {
                    segments.Add(new SvgLineSegment(segments.Last.End,
                                                    ToAbsolute(coords[0], coords[1], segments, isRelative)));
                }
                break;

            case 'H':     // horizontal lineto
            case 'h':     // relative horizontal lineto
                while (parser.TryGetFloat(out coords[0]))
                {
                    segments.Add(new SvgLineSegment(segments.Last.End,
                                                    ToAbsolute(coords[0], segments.Last.End.Y, segments, isRelative, false)));
                }
                break;

            case 'V':     // vertical lineto
            case 'v':     // relative vertical lineto
                while (parser.TryGetFloat(out coords[0]))
                {
                    segments.Add(new SvgLineSegment(segments.Last.End,
                                                    ToAbsolute(segments.Last.End.X, coords[0], segments, false, isRelative)));
                }
                break;

            case 'Q':     // curveto
            case 'q':     // relative curveto
                while (parser.TryGetFloat(out coords[0]) && parser.TryGetFloat(out coords[1]) &&
                       parser.TryGetFloat(out coords[2]) && parser.TryGetFloat(out coords[3]))
                {
                    segments.Add(new SvgQuadraticCurveSegment(segments.Last.End,
                                                              ToAbsolute(coords[0], coords[1], segments, isRelative),
                                                              ToAbsolute(coords[2], coords[3], segments, isRelative)));
                }
                break;

            case 'T':     // shorthand/smooth curveto
            case 't':     // relative shorthand/smooth curveto
                while (parser.TryGetFloat(out coords[0]) && parser.TryGetFloat(out coords[1]))
                {
                    var lastQuadCurve = segments.Last as SvgQuadraticCurveSegment;

                    var controlPoint = lastQuadCurve != null
                            ? Reflect(lastQuadCurve.ControlPoint, segments.Last.End)
                            : segments.Last.End;

                    segments.Add(new SvgQuadraticCurveSegment(segments.Last.End, controlPoint,
                                                              ToAbsolute(coords[0], coords[1], segments, isRelative)));
                }
                break;

            case 'C':     // curveto
            case 'c':     // relative curveto
                while (parser.TryGetFloat(out coords[0]) && parser.TryGetFloat(out coords[1]) &&
                       parser.TryGetFloat(out coords[2]) && parser.TryGetFloat(out coords[3]) &&
                       parser.TryGetFloat(out coords[4]) && parser.TryGetFloat(out coords[5]))
                {
                    segments.Add(new SvgCubicCurveSegment(segments.Last.End,
                                                          ToAbsolute(coords[0], coords[1], segments, isRelative),
                                                          ToAbsolute(coords[2], coords[3], segments, isRelative),
                                                          ToAbsolute(coords[4], coords[5], segments, isRelative)));
                }
                break;

            case 'S':     // shorthand/smooth curveto
            case 's':     // relative shorthand/smooth curveto
                while (parser.TryGetFloat(out coords[0]) && parser.TryGetFloat(out coords[1]) &&
                       parser.TryGetFloat(out coords[2]) && parser.TryGetFloat(out coords[3]))
                {
                    var lastCubicCurve = segments.Last as SvgCubicCurveSegment;

                    var controlPoint = lastCubicCurve != null
                            ? Reflect(lastCubicCurve.SecondControlPoint, segments.Last.End)
                            : segments.Last.End;

                    segments.Add(new SvgCubicCurveSegment(segments.Last.End, controlPoint,
                                                          ToAbsolute(coords[0], coords[1], segments, isRelative),
                                                          ToAbsolute(coords[2], coords[3], segments, isRelative)));
                }
                break;

            case 'Z':     // closepath
            case 'z':     // relative closepath
                segments.Add(new SvgClosePathSegment());
                break;
            }
        }
示例#37
0
        /// <summary>
        /// Parses the specified string into a collection of path segments.
        /// </summary>
        /// <param name="path">A <see cref="string"/> containing path data.</param>
        public static SvgPathSegmentList Parse(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException("path");
            }

            var segments = new SvgPathSegmentList();

            try
            {
                List <float> coords;
                char         command;
                bool         isRelative;

                foreach (var commandSet in SplitCommands(path.TrimEnd(null)))
                {
                    coords     = new List <float>(ParseCoordinates(commandSet.Trim()));
                    command    = commandSet[0];
                    isRelative = char.IsLower(command);
                    // http://www.w3.org/TR/SVG11/paths.html#PathDataGeneralInformation

                    switch (command)
                    {
                    case 'm':     // relative moveto
                    case 'M':     // moveto
                        segments.Add(
                            new SvgMoveToSegment(ToAbsolute(coords[0], coords[1], segments, isRelative)));

                        for (var i = 2; i < coords.Count; i += 2)
                        {
                            segments.Add(new SvgLineSegment(segments.Last.End,
                                                            ToAbsolute(coords[i], coords[i + 1], segments, isRelative)));
                        }
                        break;

                    case 'a':
                    case 'A':
                        SvgArcSize  size;
                        SvgArcSweep sweep;

                        for (var i = 0; i < coords.Count; i += 7)
                        {
                            size  = (coords[i + 3] != 0.0f) ? SvgArcSize.Large : SvgArcSize.Small;
                            sweep = (coords[i + 4] != 0.0f) ? SvgArcSweep.Positive : SvgArcSweep.Negative;

                            // A|a rx ry x-axis-rotation large-arc-flag sweep-flag x y
                            segments.Add(new SvgArcSegment(segments.Last.End, coords[i], coords[i + 1], coords[i + 2],
                                                           size, sweep, ToAbsolute(coords[i + 5], coords[i + 6], segments, isRelative)));
                        }
                        break;

                    case 'l':     // relative lineto
                    case 'L':     // lineto
                        for (var i = 0; i < coords.Count; i += 2)
                        {
                            segments.Add(new SvgLineSegment(segments.Last.End,
                                                            ToAbsolute(coords[i], coords[i + 1], segments, isRelative)));
                        }
                        break;

                    case 'H':     // horizontal lineto
                    case 'h':     // relative horizontal lineto
                        foreach (var value in coords)
                        {
                            segments.Add(new SvgLineSegment(segments.Last.End,
                                                            ToAbsolute(value, segments.Last.End.Y, segments, isRelative, false)));
                        }
                        break;

                    case 'V':     // vertical lineto
                    case 'v':     // relative vertical lineto
                        foreach (var value in coords)
                        {
                            segments.Add(new SvgLineSegment(segments.Last.End,
                                                            ToAbsolute(segments.Last.End.X, value, segments, false, isRelative)));
                        }
                        break;

                    case 'Q':     // curveto
                    case 'q':     // relative curveto
                        for (var i = 0; i < coords.Count; i += 4)
                        {
                            segments.Add(new SvgQuadraticCurveSegment(segments.Last.End,
                                                                      ToAbsolute(coords[i], coords[i + 1], segments, isRelative),
                                                                      ToAbsolute(coords[i + 2], coords[i + 3], segments, isRelative)));
                        }
                        break;

                    case 'T':     // shorthand/smooth curveto
                    case 't':     // relative shorthand/smooth curveto
                        for (var i = 0; i < coords.Count; i += 2)
                        {
                            var lastQuadCurve = segments.Last as SvgQuadraticCurveSegment;

                            var controlPoint = lastQuadCurve != null
                                    ? Reflect(lastQuadCurve.ControlPoint, segments.Last.End)
                                    : segments.Last.End;

                            segments.Add(new SvgQuadraticCurveSegment(segments.Last.End, controlPoint,
                                                                      ToAbsolute(coords[i], coords[i + 1], segments, isRelative)));
                        }
                        break;

                    case 'C':     // curveto
                    case 'c':     // relative curveto
                        for (var i = 0; i < coords.Count; i += 6)
                        {
                            segments.Add(new SvgCubicCurveSegment(segments.Last.End,
                                                                  ToAbsolute(coords[i], coords[i + 1], segments, isRelative),
                                                                  ToAbsolute(coords[i + 2], coords[i + 3], segments, isRelative),
                                                                  ToAbsolute(coords[i + 4], coords[i + 5], segments, isRelative)));
                        }
                        break;

                    case 'S':     // shorthand/smooth curveto
                    case 's':     // relative shorthand/smooth curveto

                        for (var i = 0; i < coords.Count; i += 4)
                        {
                            var lastCubicCurve = segments.Last as SvgCubicCurveSegment;

                            var controlPoint = lastCubicCurve != null
                                    ? Reflect(lastCubicCurve.SecondControlPoint, segments.Last.End)
                                    : segments.Last.End;

                            segments.Add(new SvgCubicCurveSegment(segments.Last.End, controlPoint,
                                                                  ToAbsolute(coords[i], coords[i + 1], segments, isRelative),
                                                                  ToAbsolute(coords[i + 2], coords[i + 3], segments, isRelative)));
                        }
                        break;

                    case 'Z':     // closepath
                    case 'z':     // relative closepath
                        segments.Add(new SvgClosePathSegment());
                        break;
                    }
                }
            }
            catch (Exception exc)
            {
                Trace.TraceError("Error parsing path \"{0}\": {1}", path, exc.Message);
            }

            return(segments);
        }
示例#38
0
        /// <summary>
        /// Parses the specified string into a collection of path segments.
        /// </summary>
        /// <param name="path">A <see cref="string"/> containing path data.</param>
        public static SvgPathSegmentList Parse(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException("path");
            }

            var segments = new SvgPathSegmentList();

            try
            {
                List<float> coords;
                char command;
                bool isRelative;

                foreach (var commandSet in SplitCommands(path.TrimEnd(null)))
                {
                    coords = new List<float>(ParseCoordinates(commandSet.Trim()));
                    command = commandSet[0];
                    isRelative = char.IsLower(command);
                    // http://www.w3.org/TR/SVG11/paths.html#PathDataGeneralInformation

                    switch (command)
                    {
                        case 'm': // relative moveto
                        case 'M': // moveto
                            segments.Add(
                                new SvgMoveToSegment(ToAbsolute(coords[0], coords[1], segments, isRelative)));

                            for (var i = 2; i < coords.Count; i += 2)
                            {
                                segments.Add(new SvgLineSegment(segments.Last.End,
                                    ToAbsolute(coords[i], coords[i + 1], segments, isRelative)));
                            }
                            break;
                        case 'a':
                        case 'A':
                            SvgArcSize size;
                            SvgArcSweep sweep;

                            for (var i = 0; i < coords.Count; i += 7)
                            {
                                size = (coords[i + 3] != 0.0f) ? SvgArcSize.Large : SvgArcSize.Small;
                                sweep = (coords[i + 4] != 0.0f) ? SvgArcSweep.Positive : SvgArcSweep.Negative;

                                // A|a rx ry x-axis-rotation large-arc-flag sweep-flag x y
                                segments.Add(new SvgArcSegment(segments.Last.End, coords[i], coords[i + 1], coords[i + 2],
                                    size, sweep, ToAbsolute(coords[i + 5], coords[i + 6], segments, isRelative)));
                            }
                            break;
                        case 'l': // relative lineto
                        case 'L': // lineto
                            for (var i = 0; i < coords.Count; i += 2)
                            {
                                segments.Add(new SvgLineSegment(segments.Last.End,
                                    ToAbsolute(coords[i], coords[i + 1], segments, isRelative)));
                            }
                            break;
                        case 'H': // horizontal lineto
                        case 'h': // relative horizontal lineto
                            foreach (var value in coords)
                                segments.Add(new SvgLineSegment(segments.Last.End,
                                    ToAbsolute(value, segments.Last.End.Y, segments, isRelative, false)));
                            break;
                        case 'V': // vertical lineto
                        case 'v': // relative vertical lineto
                            foreach (var value in coords)
                                segments.Add(new SvgLineSegment(segments.Last.End,
                                    ToAbsolute(segments.Last.End.X, value, segments, false, isRelative)));
                            break;
                        case 'Q': // curveto
                        case 'q': // relative curveto
                            for (var i = 0; i < coords.Count; i += 4)
                            {
                                segments.Add(new SvgQuadraticCurveSegment(segments.Last.End,
                                    ToAbsolute(coords[i], coords[i + 1], segments, isRelative),
                                    ToAbsolute(coords[i + 2], coords[i + 3], segments, isRelative)));
                            }
                            break;
                        case 'T': // shorthand/smooth curveto
                        case 't': // relative shorthand/smooth curveto
                            for (var i = 0; i < coords.Count; i += 2)
                            {
                                var lastQuadCurve = segments.Last as SvgQuadraticCurveSegment;

                                var controlPoint = lastQuadCurve != null
                                    ? Reflect(lastQuadCurve.ControlPoint, segments.Last.End)
                                    : segments.Last.End;

                                segments.Add(new SvgQuadraticCurveSegment(segments.Last.End, controlPoint,
                                    ToAbsolute(coords[i], coords[i + 1], segments, isRelative)));
                            }
                            break;
                        case 'C': // curveto
                        case 'c': // relative curveto
                            for (var i = 0; i < coords.Count; i += 6)
                            {
                                segments.Add(new SvgCubicCurveSegment(segments.Last.End,
                                    ToAbsolute(coords[i], coords[i + 1], segments, isRelative),
                                    ToAbsolute(coords[i + 2], coords[i + 3], segments, isRelative),
                                    ToAbsolute(coords[i + 4], coords[i + 5], segments, isRelative)));
                            }
                            break;
                        case 'S': // shorthand/smooth curveto
                        case 's': // relative shorthand/smooth curveto

                            for (var i = 0; i < coords.Count; i += 4)
                            {
                                var lastCubicCurve = segments.Last as SvgCubicCurveSegment;

                                var controlPoint = lastCubicCurve != null
                                    ? Reflect(lastCubicCurve.SecondControlPoint, segments.Last.End)
                                    : segments.Last.End;

                                segments.Add(new SvgCubicCurveSegment(segments.Last.End, controlPoint,
                                    ToAbsolute(coords[i], coords[i + 1], segments, isRelative),
                                    ToAbsolute(coords[i + 2], coords[i + 3], segments, isRelative)));
                            }
                            break;
                        case 'Z': // closepath
                        case 'z': // relative closepath
                            segments.Add(new SvgClosePathSegment());
                            break;
                    }
                }
            }
            catch (Exception exc)
            {
            //                Trace.TraceError("Error parsing path \"{0}\": {1}", path, exc.Message);
            }

            return segments;
        }
示例#39
0
 public static IEnumerable <Curve> Curves(this SvgPathSegmentList pathSegments)
 => pathSegments.SplitCurves().SelectMany(c => c.Curves);
        public void DrawPath(IEnumerable<IEnumerable<Point>> points, bool winding, GraphicsContext context,
            DeviceDescription description)
        {
            var svgContext = _mapper.MapGraphicsContextToSvg(context);
            foreach (var point in points)
            {
                var vertices = point.ToList();
                var list = new SvgPathSegmentList();
                var first = vertices.First();
                list.Add(new SvgMoveToSegment(new PointF((float)first.X, (float)first.Y)));

                foreach (var vertex in vertices.Skip(1))
                {
                    list.Add(new SvgLineSegment(new PointF((float)first.X, (float)first.Y),
                                                  new PointF((float)vertex.X, (float)vertex.Y)));
                    first = vertex;
                }

                list.Add(new SvgClosePathSegment());
                AddChild(new SvgPath
                {
                    Fill = svgContext.Fill,
                    FillOpacity = svgContext.Opacity,
                    PathData = list,
                    Stroke = svgContext.Pen.Stroke,
                    StrokeDashArray = svgContext.Pen.StrokeDashArray,
                    StrokeLineCap = svgContext.Pen.StrokeLineCap,
                    StrokeLineJoin = svgContext.Pen.StrokeLineJoin,
                    StrokeWidth = svgContext.Pen.StrokeWidth
                });
            }
        }
示例#41
0
        /// <summary>
        /// Creates point with absolute coorindates.
        /// </summary>
        /// <param name="x">Raw X-coordinate value.</param>
        /// <param name="y">Raw Y-coordinate value.</param>
        /// <param name="segments">Current path segments.</param>
        /// <param name="isRelativeX"><b>true</b> if <paramref name="x"/> contains relative coordinate value, otherwise <b>false</b>.</param>
        /// <param name="isRelativeY"><b>true</b> if <paramref name="y"/> contains relative coordinate value, otherwise <b>false</b>.</param>
        /// <returns><see cref="PointF"/> that contains absolute coordinates.</returns>
        private static PointF ToAbsolute(float x, float y, SvgPathSegmentList segments, bool isRelativeX, bool isRelativeY)
        {
            var point = new PointF(x, y);

            if ((isRelativeX || isRelativeY) && segments.Count > 0)
            {
                var lastSegment = segments.Last;

                if (isRelativeX)
                {
                    point.X += lastSegment.End.X;
                }

                if (isRelativeY)
                {
                    point.Y += lastSegment.End.Y;
                }
            }

            return point;
        }
示例#42
0
        public static SvgPathSegmentList NormalizeAndTruncate(this SvgPathSegmentList path, out DoubleMatrix transform, double halfSize = 2048)
        {
            // Calculate the bounding box of the path
            var points = path.Curves().SelectMany(c => c.EnclosingPolygon).ToArray();

            // Don't normalize an empty path
            if (points.Length == 0)
            {
                transform = DoubleMatrix.Identity;
                return(path);
            }

            var minx = double.PositiveInfinity;
            var maxx = double.NegativeInfinity;
            var miny = double.PositiveInfinity;
            var maxy = double.NegativeInfinity;

            // Find the bounding box
            foreach (var pt in points)
            {
                minx = Math.Min(minx, pt.X);
                maxx = Math.Max(maxx, pt.X);
                miny = Math.Min(miny, pt.Y);
                maxy = Math.Max(maxy, pt.Y);
            }

            // Calculate the points
            var center = new Double2(minx + maxx, miny + maxy) / 2;

            // And the half-sizes
            var hx = (maxx - minx) / 2;
            var hy = (maxy - miny) / 2;

            // Chose the maximum value of it
            var d  = halfSize / Math.Max(hx, hy);
            var dm = Double2.Zero;

            // And transform the path
            var newPath = new SvgPathSegmentList();

            foreach (var segment in path)
            {
                if (segment is SvgMoveToSegment move)
                {
                    newPath.Add(new SvgMoveToSegment(Transform(move.Start)));
                }
                else if (segment is SvgLineSegment line)
                {
                    newPath.Add(new SvgLineSegment(Transform(line.Start), Transform(line.End)));
                }
                else if (segment is SvgQuadraticCurveSegment quad)
                {
                    newPath.Add(new SvgQuadraticCurveSegment(Transform(quad.Start), Transform(quad.ControlPoint), Transform(quad.End)));
                }
                else if (segment is SvgCubicCurveSegment cubic)
                {
                    newPath.Add(new SvgCubicCurveSegment(Transform(cubic.Start), Transform(cubic.FirstControlPoint),
                                                         Transform(cubic.SecondControlPoint), Transform(cubic.End)));
                }
                else if (segment is SvgArcSegment arc)
                {
                    newPath.Add(new SvgArcSegment(Transform(arc.Start), (float)(arc.RadiusX * d).Truncate(),
                                                  (float)(arc.RadiusY * d).Truncate(), arc.Angle, arc.Size, arc.Sweep, Transform(arc.End)));
                }
                else if (segment is SvgClosePathSegment)
                {
                    newPath.Add(new SvgClosePathSegment());
                }
            }

            // Mount the inverse matrix
            transform = new DoubleMatrix(1 / d, 0, 0, 1 / d, center.X, center.Y);
            return(newPath);

            System.Drawing.PointF Transform(System.Drawing.PointF point)
            {
                var pt = (point.ToDouble2() * d - center * d).Truncate() + dm;

                return(new System.Drawing.PointF((float)pt.X, (float)pt.Y));
            }
        }