Пример #1
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="IPoint2F" /> that contains absolute coordinates.</returns>
 private static IPoint2F ToAbsolute(Single x,
                                    Single y,
                                    SvgPathSegmentList segments,
                                    Boolean isRelativeBoth)
 {
     return(ToAbsolute(x, y, segments, isRelativeBoth, isRelativeBoth));
 }
        public Object Clone()
        {
            var segments = new SvgPathSegmentList();

            foreach (var segment in this)
            {
                segments.Add(segment.Clone());
            }

            return(segments);
        }
Пример #3
0
        private ISvgImage Parse(Double width,
                                Double height,
                                String path)
        {
            var segments = new SvgPathSegmentList();


            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.Substring(start, length).Trim();
                    commandStart = i;

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

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

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

            return(new SvgImage(width, height, segments, _imageProvider));
        }
Пример #4
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="IPoint2F" /> that contains absolute coordinates.</returns>
        private static IPoint2F ToAbsolute(Single x,
                                           Single y,
                                           SvgPathSegmentList segments,
                                           Boolean isRelativeX,
                                           Boolean isRelativeY)
        {
            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 (var i = segments.Count - 1; i >= 0; i--)
                    {
                        if (segments[i] is SvgMoveToSegment moveToSegment)
                        {
                            lastSegment = moveToSegment;
                            break;
                        }
                    }
                }

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

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

            var point = new ValuePoint2F(x, y);

            return(point);
        }
Пример #5
0
        private static void CreatePathSegments(Char command,
                                               SvgPathSegmentList segments,
                                               CoordinateParserState state,
                                               String 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))
                {
                    var mov = new SvgMoveToSegment(
                        ToAbsolute(coords0, coords1, segments, isRelative));

                    segments.Add(mov);
                    //yield return mov;
                }

                while (CoordinateParser.TryGetFloat(out coords0, ref chars, ref state) &&
                       CoordinateParser.TryGetFloat(out coords1, ref chars, ref state))
                {
                    var line = new SvgLineSegment(segments.Last.End,
                                                  ToAbsolute(coords0, coords1, segments, isRelative));

                    segments.Add(line);

                    //yield return line;
                }
            }
            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

                    var arc = new SvgArcSegment(
                        segments.Last.End,
                        coords0,
                        coords1,
                        coords2,
                        size ? SvgArcSize.Large : SvgArcSize.Small,
                        sweep ? SvgArcSweep.Positive : SvgArcSweep.Negative,
                        ToAbsolute(coords3, coords4, segments, isRelative));

                    segments.Add(arc);

                    //yield return arc;
                }
            }
            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))
                {
                    var line = new SvgLineSegment(
                        segments.Last.End,
                        ToAbsolute(coords0, coords1, segments, isRelative));

                    segments.Add(line);
                    //yield return line;
                }
            }
            break;

            case 'H':     // horizontal lineto
            case 'h':     // relative horizontal lineto
            {
                while (CoordinateParser.TryGetFloat(out var coords0, ref chars, ref state))
                {
                    var line = new SvgLineSegment(
                        segments.Last.End,
                        ToAbsolute(coords0, segments.Last.End.Y, segments, isRelative, false));

                    segments.Add(line);

                    //yield return line;
                }
            }
            break;

            case 'V':     // vertical lineto
            case 'v':     // relative vertical lineto
            {
                while (CoordinateParser.TryGetFloat(out var coords0, ref chars, ref state))
                {
                    var line = new SvgLineSegment(
                        segments.Last.End,
                        ToAbsolute(segments.Last.End.X, coords0, segments, false, isRelative));

                    segments.Add(line);
                    //yield return line;
                }
            }
            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))
                {
                    var quad = new SvgQuadraticCurveSegment(
                        segments.Last.End,
                        ToAbsolute(coords0, coords1, segments, isRelative),
                        ToAbsolute(coords2, coords3, segments, isRelative));

                    segments.Add(quad);
                    //yield return quad;
                }
            }
            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))
                {
                    var lastQuadCurve = segments.Last as SvgQuadraticCurveSegment;
                    var controlPoint  = lastQuadCurve != null
                            ? Reflect(lastQuadCurve.ControlPoint, segments.Last.End)
                            : segments.Last.End;

                    var quad = new SvgQuadraticCurveSegment(
                        segments.Last.End,
                        controlPoint,
                        ToAbsolute(coords0, coords1, segments, isRelative));

                    segments.Add(quad);
                    //yield return quad;
                }
            }
            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))
                {
                    var cube = new SvgCubicCurveSegment(
                        segments.Last.End,
                        ToAbsolute(coords0, coords1, segments, isRelative),
                        ToAbsolute(coords2, coords3, segments, isRelative),
                        ToAbsolute(coords4, coords5, segments, isRelative));

                    segments.Add(cube);
                    //yield return cube;
                }
            }
            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))
                {
                    var lastCubicCurve = segments.Last as SvgCubicCurveSegment;
                    var controlPoint   = lastCubicCurve != null
                            ? Reflect(lastCubicCurve.SecondControlPoint, segments.Last.End)
                            : segments.Last.End;

                    var cube = new SvgCubicCurveSegment(
                        segments.Last.End,
                        controlPoint,
                        ToAbsolute(coords0, coords1, segments, isRelative),
                        ToAbsolute(coords2, coords3, segments, isRelative));

                    segments.Add(cube);
                    //yield return cube;
                }
            }
            break;

            case 'Z':     // closepath
            case 'z':     // relative closepath
            {
                var bye = new SvgClosePathSegment();
                segments.Add(bye);
                //yield return bye;
            }
            break;
            }
        }