/// <summary> /// Converts the given object to the type of this converter, using the specified context and culture information. /// </summary> /// <param name="context">An <see cref="T:System.ComponentModel.ITypeDescriptorContext"/> that provides a format context.</param> /// <param name="culture">The <see cref="T:System.Globalization.CultureInfo"/> to use as the current culture.</param> /// <param name="value">The <see cref="T:System.Object"/> to convert.</param> /// <returns> /// An <see cref="T:System.Object"/> that represents the converted value. /// </returns> /// <exception cref="T:System.NotSupportedException">The conversion cannot be performed. </exception> public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { if (value is string) { var parser = new CoordinateParser(((string)value).Trim()); var pointValue = 0.0f; var result = new SvgPointCollection(); while (parser.TryGetFloat(out pointValue)) { result.Add(new SvgUnit(SvgUnitType.User, pointValue)); } return(result); } return(base.ConvertFrom(context, culture, value)); }
/// <summary> /// Converts the given object to the type of this converter, using the specified context and culture information. /// </summary> /// <param name="context">An <see cref="T:System.ComponentModel.ITypeDescriptorContext"/> that provides a format context.</param> /// <param name="culture">The <see cref="T:System.Globalization.CultureInfo"/> to use as the current culture.</param> /// <param name="value">The <see cref="T:System.Object"/> to convert.</param> /// <returns> /// An <see cref="T:System.Object"/> that represents the converted value. /// </returns> /// <exception cref="T:System.NotSupportedException">The conversion cannot be performed. </exception> public override SvgPointCollection Convert(string value) { var strValue = ((string)value).Trim(); if (string.Compare(strValue, "none", StringComparison.OrdinalIgnoreCase) == 0) { return(null); } var parser = new CoordinateParser(strValue); var pointValue = 0.0f; var result = new SvgPointCollection(); while (parser.TryGetFloat(out pointValue)) { result.Add(new SvgUnit(SvgUnitType.User, pointValue)); } return(result); }
//private static readonly SvgUnitConverter _unitConverter = new SvgUnitConverter(); /// <summary> /// Converts the given object to the type of this converter, using the specified context and culture information. /// </summary> /// <param name="context">An <see cref="T:System.ComponentModel.ITypeDescriptorContext"/> that provides a format context.</param> /// <param name="culture">The <see cref="T:System.Globalization.CultureInfo"/> to use as the current culture.</param> /// <param name="value">The <see cref="T:System.Object"/> to convert.</param> /// <returns> /// An <see cref="T:System.Object"/> that represents the converted value. /// </returns> /// <exception cref="T:System.NotSupportedException">The conversion cannot be performed. </exception> public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) { if (value is string) { var strValue = ((string)value).Trim(); if (string.Compare(strValue, "none", StringComparison.InvariantCultureIgnoreCase) == 0) { return(null); } var parser = new CoordinateParser(strValue); var pointValue = 0.0f; var result = new SvgPointCollection(); while (parser.TryGetFloat(out pointValue)) { result.Add(new SvgUnit(SvgUnitType.User, pointValue)); } return(result); } return(base.ConvertFrom(context, culture, value)); }
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; } }
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; } }
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; } }