/// <summary> /// Creates point with absolute coordinates /// </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="Vector2"/> that contains absolute coordinates.</returns> static Vector2 toAbsolute(float x, float y, List <SvgPathSegment> segments, bool isRelativeX, bool isRelativeY) { var point = new Vector2(x, y); if ((isRelativeX || isRelativeY) && segments.Count > 0) { var lastSegment = segments.lastItem(); // 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 = ((IList <SvgPathSegment>)segments).Reverse().OfType <SvgMoveToSegment>().First(); } if (isRelativeX) { point.X += lastSegment.end.X; } if (isRelativeY) { point.Y += lastSegment.end.Y; } } return(point); }
/// <summary> /// creates an SvgPathSegment based on the command and coords passed in /// </summary> /// <param name="command">Command.</param> /// <param name="segments">Segments.</param> /// <param name="coords">Coords.</param> /// <param name="isRelative">If set to <c>true</c> is relative.</param> static void createPathSegment( char command, List<SvgPathSegment> segments, float[] coords, bool isRelative ) { switch( command ) { case 'm': // relative moveto case 'M': // moveto { segments.Add( new SvgMoveToSegment( toAbsolute( coords[0], coords[1], segments, isRelative ) ) ); var index = 2; while( index < coords.Length ) { segments.Add( new SvgLineSegment( segments.lastItem().end, toAbsolute( coords[index], coords[index + 1], segments, isRelative ) ) ); index += 2; } } break; case 'a': // relative arc case 'A': // arc { throw new System.NotImplementedException(); } case 'l': // relative lineto case 'L': // lineto { var index = 0; while( index < coords.Length ) { segments.Add( new SvgLineSegment( segments.lastItem().end, toAbsolute( coords[index], coords[index + 1], segments, isRelative ) ) ); index += 2; } } break; case 'H': // horizontal lineto case 'h': // relative horizontal lineto { var index = 0; while( index < coords.Length ) { segments.Add( new SvgLineSegment( segments.lastItem().end, toAbsolute( coords[index], segments.lastItem().end.Y, segments, isRelative, false ) ) ); index += 1; } } break; case 'V': // vertical lineto case 'v': // relative vertical lineto { var index = 0; while( index < coords.Length ) { segments.Add( new SvgLineSegment( segments.lastItem().end, toAbsolute( coords[index], segments.lastItem().end.X, segments, false, isRelative ) ) ); index += 1; } } break; case 'Q': // curveto case 'q': // relative curveto { var index = 0; while( index < coords.Length ) { var controlPoint = toAbsolute( coords[index], coords[index + 1], segments, isRelative ); var end = toAbsolute( coords[index + 2], coords[index + 3], segments, isRelative ); segments.Add( new SvgQuadraticCurveSegment( segments.lastItem().end, controlPoint, end ) ); index += 4; } } break; case 'T': // shorthand/smooth curveto case 't': // relative shorthand/smooth curveto { var index = 0; while( index < coords.Length ) { var lastQuadCurve = segments.lastItem() as SvgQuadraticCurveSegment; var controlPoint = lastQuadCurve != null ? reflect( lastQuadCurve.controlPoint, segments.lastItem().end ) : segments.lastItem().end; var end = toAbsolute( coords[index], coords[index + 1], segments, isRelative ); segments.Add( new SvgQuadraticCurveSegment( segments.lastItem().end, controlPoint, end ) ); index += 2; } } break; case 'C': // curveto case 'c': // relative curveto { var index = 0; while( index < coords.Length ) { var firstControlPoint = toAbsolute( coords[index], coords[index + 1], segments, isRelative ); var secondControlPoint = toAbsolute( coords[index + 2], coords[index + 3], segments, isRelative ); var end = toAbsolute( coords[index + 4], coords[index + 5], segments, isRelative ); segments.Add( new SvgCubicCurveSegment( segments.lastItem().end, firstControlPoint, secondControlPoint, end ) ); index += 6; } } break; case 'S': // shorthand/smooth curveto case 's': // relative shorthand/smooth curveto { var index = 0; while( index < coords.Length ) { var lastCubicCurve = segments.lastItem() as SvgCubicCurveSegment; var firstControlPoint = lastCubicCurve != null ? reflect( lastCubicCurve.secondCtrlPoint, segments.lastItem().end ) : segments.lastItem().end; var secondControlPoint = toAbsolute( coords[index], coords[index + 1], segments, isRelative ); var end = toAbsolute( coords[index + 2], coords[index + 3], segments, isRelative ); segments.Add( new SvgCubicCurveSegment( segments.lastItem().end, firstControlPoint, secondControlPoint, end ) ); index += 4; } } break; case 'Z': // closepath case 'z': // relative closepath { segments.Add( new SvgClosePathSegment() ); } break; } }
/// <summary> /// Creates point with absolute coordinates /// </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="Vector2"/> that contains absolute coordinates.</returns> static Vector2 toAbsolute( float x, float y, List<SvgPathSegment> segments, bool isRelativeX, bool isRelativeY ) { var point = new Vector2( x, y ); if( ( isRelativeX || isRelativeY ) && segments.Count > 0 ) { var lastSegment = segments.lastItem(); // 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 = ( (IList<SvgPathSegment>)segments ).Reverse().OfType<SvgMoveToSegment>().First(); if( isRelativeX ) point.X += lastSegment.end.X; if( isRelativeY ) point.Y += lastSegment.end.Y; } return point; }
/// <summary> /// creates an SvgPathSegment based on the command and coords passed in /// </summary> /// <param name="command">Command.</param> /// <param name="segments">Segments.</param> /// <param name="coords">Coords.</param> /// <param name="isRelative">If set to <c>true</c> is relative.</param> static void createPathSegment(char command, List <SvgPathSegment> segments, float[] coords, bool isRelative) { switch (command) { case 'm': // relative moveto case 'M': { // moveto segments.Add(new SvgMoveToSegment(toAbsolute(coords[0], coords[1], segments, isRelative))); var index = 2; while (index < coords.Length) { segments.Add( new SvgLineSegment( segments.lastItem().end, toAbsolute(coords[index], coords[index + 1], segments, isRelative))); index += 2; } } break; case 'a': // relative arc case 'A': { // arc throw new System.NotImplementedException(); } case 'l': // relative lineto case 'L': { // lineto var index = 0; while (index < coords.Length) { segments.Add( new SvgLineSegment( segments.lastItem().end, toAbsolute(coords[index], coords[index + 1], segments, isRelative))); index += 2; } } break; case 'H': // horizontal lineto case 'h': { // relative horizontal lineto var index = 0; while (index < coords.Length) { segments.Add( new SvgLineSegment( segments.lastItem().end, toAbsolute(coords[index], segments.lastItem().end.Y, segments, isRelative, false))); index += 1; } } break; case 'V': // vertical lineto case 'v': { // relative vertical lineto var index = 0; while (index < coords.Length) { segments.Add( new SvgLineSegment( segments.lastItem().end, toAbsolute(coords[index], segments.lastItem().end.X, segments, false, isRelative))); index += 1; } } break; case 'Q': // curveto case 'q': { // relative curveto var index = 0; while (index < coords.Length) { var controlPoint = toAbsolute(coords[index], coords[index + 1], segments, isRelative); var end = toAbsolute(coords[index + 2], coords[index + 3], segments, isRelative); segments.Add(new SvgQuadraticCurveSegment(segments.lastItem().end, controlPoint, end)); index += 4; } } break; case 'T': // shorthand/smooth curveto case 't': { // relative shorthand/smooth curveto var index = 0; while (index < coords.Length) { var lastQuadCurve = segments.lastItem() as SvgQuadraticCurveSegment; var controlPoint = lastQuadCurve != null ? reflect(lastQuadCurve.controlPoint, segments.lastItem().end) : segments.lastItem().end; var end = toAbsolute(coords[index], coords[index + 1], segments, isRelative); segments.Add(new SvgQuadraticCurveSegment(segments.lastItem().end, controlPoint, end)); index += 2; } } break; case 'C': // curveto case 'c': { // relative curveto var index = 0; while (index < coords.Length) { var firstControlPoint = toAbsolute(coords[index], coords[index + 1], segments, isRelative); var secondControlPoint = toAbsolute( coords[index + 2], coords[index + 3], segments, isRelative); var end = toAbsolute(coords[index + 4], coords[index + 5], segments, isRelative); segments.Add( new SvgCubicCurveSegment( segments.lastItem().end, firstControlPoint, secondControlPoint, end)); index += 6; } } break; case 'S': // shorthand/smooth curveto case 's': { // relative shorthand/smooth curveto var index = 0; while (index < coords.Length) { var lastCubicCurve = segments.lastItem() as SvgCubicCurveSegment; var firstControlPoint = lastCubicCurve != null ? reflect( lastCubicCurve.secondCtrlPoint, segments.lastItem().end) : segments.lastItem().end; var secondControlPoint = toAbsolute(coords[index], coords[index + 1], segments, isRelative); var end = toAbsolute(coords[index + 2], coords[index + 3], segments, isRelative); segments.Add( new SvgCubicCurveSegment( segments.lastItem().end, firstControlPoint, secondControlPoint, end)); index += 4; } } break; case 'Z': // closepath case 'z': { // relative closepath segments.Add(new SvgClosePathSegment()); } break; } }