Пример #1
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);
        }
Пример #2
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
                });
            }
        }
Пример #3
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);
        }
Пример #4
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);
        }
Пример #5
0
        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);
        }
Пример #6
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);
        }
Пример #7
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);
        }
Пример #8
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;
            }
        }
Пример #9
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;
                    }
        }
        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
                });
            }
        }
Пример #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 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;
        }
Пример #12
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;
            }
        }
Пример #13
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;
            }
        }
Пример #14
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;
            }
        }
Пример #15
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));
            }
        }