protected override SqrtPolynomial getArcLengthPolynomial() { double c3x, c3y, c2x, c2y, c1x, c1y; SvgPointF p1 = PreviousSeg.AbsXY; SvgPointF p2 = CubicX1Y1; SvgPointF p3 = CubicX2Y2; SvgPointF p4 = AbsXY; // convert curve into polynomial c3x = -1.0 * p1.X + 3.0 * p2.X - 3.0 * p3.X + p4.X; c3y = -1.0 * p1.Y + 3.0 * p2.Y - 3.0 * p3.Y + p4.Y; c2x = 3.0 * p1.X - 6.0 * p2.X + 3.0 * p3.X; c2y = 3.0 * p1.Y - 6.0 * p2.Y + 3.0 * p3.Y; c1x = -3.0 * p1.X + 3.0 * p2.X; c1y = -3.0 * p1.Y + 3.0 * p2.Y; // build polynomial // dx = dx/dt // dy = dy/dt // sqrt poly = sqrt( (dx*dx) + (dy*dy) ) return(new SqrtPolynomial(c1x * c1x + c1y * c1y, 4.0 * (c1x * c2x + c1y * c2y), 4.0 * (c2x * c2x + c2y * c2y) + 6.0 * (c1x * c3x + c1y * c3y), 12.0 * (c2x * c3x + c2y * c3y), 9.0 * (c3x * c3x + c3y * c3y))); }
public double GetStartAngle(int index) { SvgPointF[] positions = this.MarkerPositions; index--; if (index < 0) { index = 1; if (index + 1 >= positions.Length) { index = 0; } } if (index > positions.Length - 1) { throw new Exception("GetStartAngle: index to large"); } SvgPointF p1 = positions[index]; SvgPointF p2 = positions[index + 1]; double dx = p2.X - p1.X; double dy = p2.Y - p1.Y; double a = (Math.Atan2(dy, dx) * 180 / Math.PI); a -= 90; a %= 360; return(a); }
/// <summary> /// Initializes a new instance of the <see cref="SvgRectF"/> structure /// with the specified location and size. /// </summary> /// <param name="size"> /// A <see cref="SvgSizeF"/> that represents the width and height of the /// rectangular region. /// </param> /// <param name="location"> /// A <see cref="SvgPointF"/> that represents the upper-left corner /// of the rectangular region. /// </param> public SvgRectF(SvgPointF location, SvgSizeF size) { _x = location.X; _y = location.Y; _width = size.Width; _height = size.Height; }
public SvgPathSegHandler(SvgPathSegList pathList) { _closedPath = 0; _startPoint = new SvgPointF(0, 0); _isClosed = false; _mayHaveCurves = false; _pathList = pathList; }
public SvgMarker(int index, ISvgPathSeg segment) { _index = index; _segment = segment; if (segment != null) { _position = segment.AbsXY; } }
public void LinetoAbs(float x, float y) { var seg = new SvgPathSegLinetoAbs(x, y); SvgPointF endPoint = new SvgPointF(x, y); seg.Limits = new SvgPointF[] { _startPoint, endPoint }; _startPoint = endPoint; _pathList.AppendItem(seg); }
public void MovetoRel(float x, float y) { var seg = new SvgPathSegMovetoRel(x, y); SvgPointF endPoint = new SvgPointF(x + _startPoint.X, y + _startPoint.Y); seg.Limits = new SvgPointF[] { _startPoint, endPoint }; _startPoint = endPoint; _pathList.AppendItem(seg); }
public void ArcRel(float rx, float ry, float xAxisRotation, bool largeArcFlag, bool sweepFlag, float x, float y) { var seg = new SvgPathSegArcRel(x, y, rx, ry, xAxisRotation, largeArcFlag, sweepFlag); SvgPointF endPoint = new SvgPointF(x + _startPoint.X, y + _startPoint.Y); seg.Limits = new SvgPointF[] { _startPoint, endPoint }; _startPoint = endPoint; _pathList.AppendItem(seg); }
public void LinetoVerticalRel(float y) { var seg = new SvgPathSegLinetoVerticalRel(y); SvgPointF endPoint = new SvgPointF(_startPoint.X, y + _startPoint.Y); seg.Limits = new SvgPointF[] { _startPoint, endPoint }; _startPoint = endPoint; _pathList.AppendItem(seg); }
public void LinetoHorizontalRel(float x) { var seg = new SvgPathSegLinetoHorizontalRel(x); SvgPointF endPoint = new SvgPointF(x + _startPoint.X, _startPoint.Y); seg.Limits = new SvgPointF[] { _startPoint, endPoint }; _startPoint = endPoint; _pathList.AppendItem(seg); }
public void CurvetoQuadraticSmoothRel(float x, float y) { var seg = new SvgPathSegCurvetoQuadraticSmoothRel(x, y); _mayHaveCurves = true; SvgPointF endPoint = new SvgPointF(x + _startPoint.X, y + _startPoint.Y); seg.Limits = new SvgPointF[] { _startPoint, endPoint }; _startPoint = endPoint; _pathList.AppendItem(seg); }
public void CurvetoQuadraticAbs(float x1, float y1, float x, float y) { var seg = new SvgPathSegCurvetoQuadraticAbs(x, y, x1, y1); _mayHaveCurves = true; SvgPointF endPoint = new SvgPointF(x, y); seg.Limits = new SvgPointF[] { _startPoint, endPoint }; _startPoint = endPoint; _pathList.AppendItem(seg); }
public void CurvetoCubicSmoothAbs(float x2, float y2, float x, float y) { var seg = new SvgPathSegCurvetoCubicSmoothAbs(x, y, x2, y2); _mayHaveCurves = true; SvgPointF endPoint = new SvgPointF(x, y); seg.Limits = new SvgPointF[] { _startPoint, endPoint }; _startPoint = endPoint; _pathList.AppendItem(seg); }
public void CurvetoCubicRel(float x1, float y1, float x2, float y2, float x, float y) { var seg = new SvgPathSegCurvetoCubicRel(x, y, x1, y1, x2, y2); _mayHaveCurves = true; SvgPointF endPoint = new SvgPointF(x + _startPoint.X, y + _startPoint.Y); seg.Limits = new SvgPointF[] { _startPoint, endPoint }; _startPoint = endPoint; _pathList.AppendItem(seg); }
public void ArcAbs(float rx, float ry, float xAxisRotation, bool largeArcFlag, bool sweepFlag, float x, float y) { var seg = new SvgPathSegArcAbs(x, y, rx, ry, xAxisRotation, largeArcFlag, sweepFlag); _mayHaveCurves = true; SvgPointF endPoint = new SvgPointF(x, y); seg.Limits = new SvgPointF[] { _startPoint, endPoint }; _startPoint = endPoint; _pathList.AppendItem(seg); }
private void MapRectToRect(SvgRectF rect, SvgPointF[] plgpts) { SvgPointF pt1 = new SvgPointF(plgpts[1].X - plgpts[0].X, plgpts[1].Y - plgpts[0].Y); SvgPointF pt2 = new SvgPointF(plgpts[2].X - plgpts[0].X, plgpts[2].Y - plgpts[0].Y); this.m11 = pt1.X / rect.Width; this.m12 = pt1.Y / rect.Width; this.m21 = pt2.X / rect.Height; this.m22 = pt2.Y / rect.Height; this.dx = plgpts[0].X - rect.X / rect.Width * pt1.X - rect.Y / rect.Height * pt2.X; this.dy = plgpts[0].Y - rect.X / rect.Width * pt1.Y - rect.Y / rect.Height * pt2.Y; }
private SvgPointF GetPrevPoint() { SvgPathSeg prevSeg = this.PreviousSeg; SvgPointF prevPoint; if (prevSeg == null) { prevPoint = new SvgPointF(0, 0); } else { prevPoint = prevSeg.AbsXY; } return(prevPoint); }
public ISvgMarker GetMarker(int index) { SvgPointF position = SvgPointF.Empty; if (index == 0) { position = new SvgPointF(X1.AnimVal.Value, Y1.AnimVal.Value); } else if (index == 1) { position = new SvgPointF(X2.AnimVal.Value, Y2.AnimVal.Value); } return(new SvgMarker(index, position)); }
/// <summary> /// Applies a clockwise rotation about the specified point to this /// <see cref="SvgTransformF"/> in the specified order. /// </summary> /// <param name="angle"> /// The angle (extent) of the rotation, in degrees. /// </param> /// <param name="point"> /// A <see cref="SvgPointF"/> that represents the center of the rotation. /// </param> /// <param name="order"> /// A <see cref="TransformOrder"/> that specifies the order (append or /// prepend) in which the rotation is applied. /// </param> public void RotateAt(float angle, SvgPointF point, SvgTransformOrder order) { if (order == SvgTransformOrder.Prepend) { Translate(point.X, point.Y); Rotate(angle); Translate(-point.X, -point.Y); } else { Translate(-point.X, -point.Y); Rotate(angle, SvgTransformOrder.Append); Translate(point.X, point.Y); } }
public void ClosePath() { _closedPath++; var seg = new SvgPathSegClosePath(); _pathList.AppendItem(seg); if (_pathList.Count >= 2) { SvgPointF endPoint = _pathList[0].Limits[0]; seg.Limits = new SvgPointF[] { endPoint, _startPoint }; _startPoint = endPoint; } else { seg.Limits = new SvgPointF[] { _startPoint, _startPoint }; _startPoint = new SvgPointF(0, 0); } }
protected override SqrtPolynomial GetArcLengthPolynomial() { double c2x, c2y, c1x, c1y; SvgPointF p1 = PreviousSeg.AbsXY; SvgPointF p2 = QuadraticX1Y1; SvgPointF p3 = AbsXY; c2x = p1.X - 2.0 * p2.X + p3.X; c2y = p1.Y - 2.0 * p2.Y + p3.Y; c1x = -2.0 * p1.X + 2.0 * p2.X; c1y = -2.0 * p1.Y + 2.0 * p2.Y; // build polynomial // dx = dx/dt // dy = dy/dt // sqrt poly = sqrt( (dx*dx) + (dy*dy) ) return(new SqrtPolynomial(c1x * c1x + c1y * c1y, 4.0 * (c1x * c2x + c1y * c2y), 4.0 * (c2x * c2x + c2y * c2y))); }
public SvgMarker(int index, SvgPointF position) { _index = index; _position = position; }
public CalculatedArcValues GetCalculatedArcValues() { CalculatedArcValues calcVal = new CalculatedArcValues(); /* * This algorithm is taken from the Batik source. All cudos to the Batik crew. */ SvgPointF startPoint = PreviousSeg.AbsXY; SvgPointF endPoint = AbsXY; double x0 = startPoint.X; double y0 = startPoint.Y; double x = endPoint.X; double y = endPoint.Y; // Compute the half distance between the current and the final point double dx2 = (x0 - x) / 2.0; double dy2 = (y0 - y) / 2.0; // Convert angle from degrees to radians double radAngle = Angle * Math.PI / 180; double cosAngle = Math.Cos(radAngle); double sinAngle = Math.Sin(radAngle); // // Step 1 : Compute (x1, y1) // double x1 = (cosAngle * dx2 + sinAngle * dy2); double y1 = (-sinAngle * dx2 + cosAngle * dy2); // Ensure radii are large enough double rx = Math.Abs(R1); double ry = Math.Abs(R2); double Prx = rx * rx; double Pry = ry * ry; double Px1 = x1 * x1; double Py1 = y1 * y1; // check that radii are large enough double radiiCheck = Px1 / Prx + Py1 / Pry; if (radiiCheck > 1) { rx = Math.Sqrt(radiiCheck) * rx; ry = Math.Sqrt(radiiCheck) * ry; Prx = rx * rx; Pry = ry * ry; } // // Step 2 : Compute (cx1, cy1) // double sign = (LargeArcFlag == SweepFlag) ? -1 : 1; double sq = ((Prx * Pry) - (Prx * Py1) - (Pry * Px1)) / ((Prx * Py1) + (Pry * Px1)); sq = (sq < 0) ? 0 : sq; double coef = (sign * Math.Sqrt(sq)); double cx1 = coef * ((rx * y1) / ry); double cy1 = coef * -((ry * x1) / rx); // // Step 3 : Compute (cx, cy) from (cx1, cy1) // double sx2 = (x0 + x) / 2.0; double sy2 = (y0 + y) / 2.0; double cx = sx2 + (cosAngle * cx1 - sinAngle * cy1); double cy = sy2 + (sinAngle * cx1 + cosAngle * cy1); // // Step 4 : Compute the angleStart (angle1) and the angleExtent (dangle) // double ux = (x1 - cx1); // rx; double uy = (y1 - cy1); // ry; double vx = (-x1 - cx1); // rx; double vy = (-y1 - cy1); // ry; double p, n; // Compute the angle start n = Math.Sqrt((ux * ux) + (uy * uy)); p = ux; // (1 * ux) + (0 * uy) sign = (uy < 0) ? -1d : 1d; double angleStart = sign * Math.Acos(p / n); angleStart = angleStart * 180 / Math.PI; // Compute the angle extent n = Math.Sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy)); p = ux * vx + uy * vy; sign = (ux * vy - uy * vx < 0) ? -1d : 1d; double angleExtent = sign * Math.Acos(p / n); angleExtent = angleExtent * 180 / Math.PI; if (!_sweepFlag && angleExtent > 0) { angleExtent -= 360f; } else if (_sweepFlag && angleExtent < 0) { angleExtent += 360f; } angleExtent %= 360f; angleStart %= 360f; calcVal.CorrRx = rx; calcVal.CorrRy = ry; calcVal.Cx = cx; calcVal.Cy = cy; calcVal.AngleStart = angleStart; calcVal.AngleExtent = angleExtent; return(calcVal); }
/// <overloads> /// Applies a clockwise rotation about the specified point to this /// <see cref="SvgTransformF"/> by appending or prepending the rotation. /// </overloads> /// <summary> /// Applies a clockwise rotation about the specified point to this /// <see cref="SvgTransformF"/> by prepending the rotation. /// </summary> /// <param name="angle"> /// The angle (extent) of the rotation, in degrees. /// </param> /// <param name="point"> /// A <see cref="SvgPointF"/> that represents the center of the rotation. /// </param> public void RotateAt(float angle, SvgPointF point) { Translate(point.X, point.Y); Rotate(angle); Translate(-point.X, -point.Y); }
public bool Parse(ISvgPathSegList pathList, string pathSegs) { if (pathList == null || string.IsNullOrWhiteSpace(pathSegs)) { return(false); } _isClosed = false; _mayHaveCurves = false; int closedPath = 0; ISvgPathSeg seg; string[] segs = RegexPathCmd.Split(pathSegs); SvgPointF startPoint = new SvgPointF(0, 0); foreach (string s in segs) { string segment = s.Trim(); if (segment.Length > 0) { char cmd = segment.ToCharArray(0, 1)[0]; double[] coords = ParseCoords(segment); int length = coords.Length; switch (cmd) { #region moveto case 'M': for (int i = 0; i < length; i += 2) { if (i == 0) { seg = new SvgPathSegMovetoAbs(coords[i], coords[i + 1]); startPoint = new SvgPointF(coords[i], coords[i + 1]); SvgPointF endPoint = new SvgPointF(coords[i], coords[i + 1]); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } else { seg = new SvgPathSegLinetoAbs(coords[i], coords[i + 1]); SvgPointF endPoint = new SvgPointF(coords[i], coords[i + 1]); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } pathList.AppendItem(seg); } break; case 'm': for (int i = 0; i < length; i += 2) { if (i == 0) { seg = new SvgPathSegMovetoRel(coords[i], coords[i + 1]); SvgPointF endPoint = new SvgPointF(coords[i] + startPoint.X, coords[i + 1] + startPoint.Y); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } else { seg = new SvgPathSegLinetoRel(coords[i], coords[i + 1]); SvgPointF endPoint = new SvgPointF(coords[i] + startPoint.X, coords[i + 1] + startPoint.Y); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } pathList.AppendItem(seg); } break; #endregion #region lineto case 'L': for (int i = 0; i < length; i += 2) { seg = new SvgPathSegLinetoAbs(coords[i], coords[i + 1]); pathList.AppendItem(seg); SvgPointF endPoint = new SvgPointF(coords[i], coords[i + 1]); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; case 'l': for (int i = 0; i < length; i += 2) { seg = new SvgPathSegLinetoRel(coords[i], coords[i + 1]); pathList.AppendItem(seg); SvgPointF endPoint = new SvgPointF(coords[i] + startPoint.X, coords[i + 1] + startPoint.Y); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; case 'H': for (int i = 0; i < length; i++) { seg = new SvgPathSegLinetoHorizontalAbs(coords[i]); pathList.AppendItem(seg); SvgPointF endPoint = new SvgPointF(coords[i], startPoint.Y); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; case 'h': for (int i = 0; i < length; i++) { seg = new SvgPathSegLinetoHorizontalRel(coords[i]); pathList.AppendItem(seg); SvgPointF endPoint = new SvgPointF(coords[i] + startPoint.X, startPoint.Y); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; case 'V': for (int i = 0; i < length; i++) { seg = new SvgPathSegLinetoVerticalAbs(coords[i]); pathList.AppendItem(seg); SvgPointF endPoint = new SvgPointF(startPoint.X, coords[i]); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; case 'v': for (int i = 0; i < length; i++) { seg = new SvgPathSegLinetoVerticalRel(coords[i]); pathList.AppendItem(seg); SvgPointF endPoint = new SvgPointF(startPoint.X, coords[i] + startPoint.Y); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; #endregion #region beziers case 'C': for (int i = 0; i < length; i += 6) { seg = new SvgPathSegCurvetoCubicAbs( coords[i + 4], coords[i + 5], coords[i], coords[i + 1], coords[i + 2], coords[i + 3]); pathList.AppendItem(seg); _mayHaveCurves = true; SvgPointF endPoint = new SvgPointF(coords[i + 4], coords[i + 5]); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; case 'c': for (int i = 0; i < length; i += 6) { seg = new SvgPathSegCurvetoCubicRel( coords[i + 4], coords[i + 5], coords[i], coords[i + 1], coords[i + 2], coords[i + 3]); pathList.AppendItem(seg); _mayHaveCurves = true; SvgPointF endPoint = new SvgPointF(coords[i + 4] + startPoint.X, coords[i + 5] + startPoint.Y); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; case 'S': for (int i = 0; i < length; i += 4) { seg = new SvgPathSegCurvetoCubicSmoothAbs( coords[i + 2], coords[i + 3], coords[i], coords[i + 1]); pathList.AppendItem(seg); _mayHaveCurves = true; SvgPointF endPoint = new SvgPointF(coords[i + 2], coords[i + 3]); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; case 's': for (int i = 0; i < length; i += 4) { seg = new SvgPathSegCurvetoCubicSmoothRel( coords[i + 2], coords[i + 3], coords[i], coords[i + 1]); pathList.AppendItem(seg); _mayHaveCurves = true; SvgPointF endPoint = new SvgPointF(coords[i + 2] + startPoint.X, coords[i + 3] + startPoint.Y); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; case 'Q': for (int i = 0; i < length; i += 4) { seg = new SvgPathSegCurvetoQuadraticAbs( coords[i + 2], coords[i + 3], coords[i], coords[i + 1]); pathList.AppendItem(seg); _mayHaveCurves = true; SvgPointF endPoint = new SvgPointF(coords[i + 2], coords[i + 3]); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; case 'q': for (int i = 0; i < length; i += 4) { seg = new SvgPathSegCurvetoQuadraticRel( coords[i + 2], coords[i + 3], coords[i], coords[i + 1]); pathList.AppendItem(seg); _mayHaveCurves = true; SvgPointF endPoint = new SvgPointF(coords[i + 2] + startPoint.X, coords[i + 3] + startPoint.Y); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; case 'T': for (int i = 0; i < length; i += 2) { seg = new SvgPathSegCurvetoQuadraticSmoothAbs( coords[i], coords[i + 1]); pathList.AppendItem(seg); _mayHaveCurves = true; SvgPointF endPoint = new SvgPointF(coords[i], coords[i + 1]); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; case 't': for (int i = 0; i < length; i += 2) { seg = new SvgPathSegCurvetoQuadraticSmoothRel( coords[i], coords[i + 1]); pathList.AppendItem(seg); _mayHaveCurves = true; SvgPointF endPoint = new SvgPointF(coords[i] + startPoint.X, coords[i + 1] + startPoint.Y); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; #endregion #region arcs case 'A': case 'a': for (int i = 0; i < length; i += 7) { if (cmd == 'A') { seg = new SvgPathSegArcAbs( coords[i + 5], coords[i + 6], coords[i], coords[i + 1], coords[i + 2], (!coords[i + 3].Equals(0)), (!coords[i + 4].Equals(0))); SvgPointF endPoint = new SvgPointF(coords[i + 5], coords[i + 6]); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } else { seg = new SvgPathSegArcRel( coords[i + 5], coords[i + 6], coords[i], coords[i + 1], coords[i + 2], (!coords[i + 3].Equals(0)), (!coords[i + 4].Equals(0))); SvgPointF endPoint = new SvgPointF(coords[i + 5] + startPoint.X, coords[i + 6] + startPoint.Y); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } pathList.AppendItem(seg); _mayHaveCurves = true; } break; #endregion #region close case 'z': case 'Z': closedPath++; seg = new SvgPathSegClosePath(); pathList.AppendItem(seg); if (pathList.Count >= 2) { SvgPointF endPoint = pathList[0].Limits[0]; seg.Limits = new SvgPointF[] { endPoint, startPoint }; startPoint = endPoint; } else { seg.Limits = new SvgPointF[] { startPoint, startPoint }; startPoint = new SvgPointF(0, 0); } break; #endregion #region Unknown path command default: throw new ApplicationException(string.Format("Unknown path command - ({0})", cmd)); #endregion } } } _isClosed = (closedPath == 1); return(true); }
/// <summary>Initializes a new instance of the <see cref="SvgSizeF"/> class from the specified <see cref="SvgPointF"/>.</summary> /// <param name="pt">The <see cref="SvgPointF"/> from which to initialize this <see cref="SvgSizeF"/>. </param> public SvgSizeF(SvgPointF pt) { _width = pt.X; _height = pt.Y; }
/// <overloads> /// Adjusts the location of this rectangle by the specified amount. /// </overloads> /// <summary> /// Adjusts the location of this rectangle by the specified amount. /// </summary> /// <param name="pos">The amount to offset the location. </param> /// <returns>This method does not return a value.</returns> public void Offset(SvgPointF pos) { this.Offset(pos.X, pos.Y); }
/// <summary> /// This determines if the specified point is contained within this /// <see cref="SvgRectF"/> structure. /// </summary> /// <param name="pt">The <see cref="SvgPointF"/> to test. </param> /// <returns> /// This method returns true if the point represented by the pt /// parameter is contained within this <see cref="SvgRectF"/> /// structure; otherwise false. /// </returns> public bool Contains(SvgPointF pt) { return(this.Contains(pt.X, pt.Y)); }
public SvgMarker(int index, SvgPointF position, ISvgPathSeg segment) { _index = index; _position = position; _segment = segment; }
private bool Parse(SvgPathSegList pathList, string[] paths) { int closedPath = 0; SvgPathSeg seg; SvgPointF startPoint = new SvgPointF(0, 0); foreach (string path in paths) { string segment = path.Trim(); if (segment.Length == 0) { continue; } char cmd = segment[0]; double[] coords = SvgNumber.ParseDoubles(segment.Substring(1)); int length = coords.Length; switch (cmd) { // Parse: moveto case 'M': for (int i = 0; i < length; i += 2) { if (length < 2) { return(false); } if (i == 0) { seg = new SvgPathSegMovetoAbs(coords[i], coords[i + 1]); startPoint = new SvgPointF(coords[i], coords[i + 1]); SvgPointF endPoint = new SvgPointF(coords[i], coords[i + 1]); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } else { seg = new SvgPathSegLinetoAbs(coords[i], coords[i + 1]); SvgPointF endPoint = new SvgPointF(coords[i], coords[i + 1]); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } pathList.AppendItem(seg); } break; case 'm': for (int i = 0; i < length; i += 2) { if (length < 2) { return(false); } if (i == 0) { seg = new SvgPathSegMovetoRel(coords[i], coords[i + 1]); SvgPointF endPoint = new SvgPointF(coords[i] + startPoint.X, coords[i + 1] + startPoint.Y); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } else { seg = new SvgPathSegLinetoRel(coords[i], coords[i + 1]); SvgPointF endPoint = new SvgPointF(coords[i] + startPoint.X, coords[i + 1] + startPoint.Y); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } pathList.AppendItem(seg); } break; // End of: moveto // Parse: lineto case 'L': for (int i = 0; i < length; i += 2) { seg = new SvgPathSegLinetoAbs(coords[i], coords[i + 1]); pathList.AppendItem(seg); SvgPointF endPoint = new SvgPointF(coords[i], coords[i + 1]); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; case 'l': for (int i = 0; i < length; i += 2) { seg = new SvgPathSegLinetoRel(coords[i], coords[i + 1]); pathList.AppendItem(seg); SvgPointF endPoint = new SvgPointF(coords[i] + startPoint.X, coords[i + 1] + startPoint.Y); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; case 'H': for (int i = 0; i < length; i++) { seg = new SvgPathSegLinetoHorizontalAbs(coords[i]); pathList.AppendItem(seg); SvgPointF endPoint = new SvgPointF(coords[i], startPoint.Y); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; case 'h': for (int i = 0; i < length; i++) { seg = new SvgPathSegLinetoHorizontalRel(coords[i]); pathList.AppendItem(seg); SvgPointF endPoint = new SvgPointF(coords[i] + startPoint.X, startPoint.Y); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; case 'V': for (int i = 0; i < length; i++) { seg = new SvgPathSegLinetoVerticalAbs(coords[i]); pathList.AppendItem(seg); SvgPointF endPoint = new SvgPointF(startPoint.X, coords[i]); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; case 'v': for (int i = 0; i < length; i++) { seg = new SvgPathSegLinetoVerticalRel(coords[i]); pathList.AppendItem(seg); SvgPointF endPoint = new SvgPointF(startPoint.X, coords[i] + startPoint.Y); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; // End of: lineto // Parse: beziers case 'C': for (int i = 0; i < length; i += 6) { seg = new SvgPathSegCurvetoCubicAbs( coords[i + 4], coords[i + 5], coords[i], coords[i + 1], coords[i + 2], coords[i + 3]); pathList.AppendItem(seg); _mayHaveCurves = true; SvgPointF endPoint = new SvgPointF(coords[i + 4], coords[i + 5]); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; case 'c': for (int i = 0; i < length; i += 6) { if ((i + 5) >= length) { break; } seg = new SvgPathSegCurvetoCubicRel( coords[i + 4], coords[i + 5], coords[i], coords[i + 1], coords[i + 2], coords[i + 3]); pathList.AppendItem(seg); _mayHaveCurves = true; SvgPointF endPoint = new SvgPointF(coords[i + 4] + startPoint.X, coords[i + 5] + startPoint.Y); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; case 'S': for (int i = 0; i < length; i += 4) { seg = new SvgPathSegCurvetoCubicSmoothAbs( coords[i + 2], coords[i + 3], coords[i], coords[i + 1]); pathList.AppendItem(seg); _mayHaveCurves = true; SvgPointF endPoint = new SvgPointF(coords[i + 2], coords[i + 3]); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; case 's': for (int i = 0; i < length; i += 4) { seg = new SvgPathSegCurvetoCubicSmoothRel( coords[i + 2], coords[i + 3], coords[i], coords[i + 1]); pathList.AppendItem(seg); _mayHaveCurves = true; SvgPointF endPoint = new SvgPointF(coords[i + 2] + startPoint.X, coords[i + 3] + startPoint.Y); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; case 'Q': for (int i = 0; i < length; i += 4) { seg = new SvgPathSegCurvetoQuadraticAbs( coords[i + 2], coords[i + 3], coords[i], coords[i + 1]); pathList.AppendItem(seg); _mayHaveCurves = true; SvgPointF endPoint = new SvgPointF(coords[i + 2], coords[i + 3]); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; case 'q': for (int i = 0; i < length; i += 4) { seg = new SvgPathSegCurvetoQuadraticRel( coords[i + 2], coords[i + 3], coords[i], coords[i + 1]); pathList.AppendItem(seg); _mayHaveCurves = true; SvgPointF endPoint = new SvgPointF(coords[i + 2] + startPoint.X, coords[i + 3] + startPoint.Y); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; case 'T': for (int i = 0; i < length; i += 2) { seg = new SvgPathSegCurvetoQuadraticSmoothAbs( coords[i], coords[i + 1]); pathList.AppendItem(seg); _mayHaveCurves = true; SvgPointF endPoint = new SvgPointF(coords[i], coords[i + 1]); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; case 't': for (int i = 0; i < length; i += 2) { seg = new SvgPathSegCurvetoQuadraticSmoothRel( coords[i], coords[i + 1]); pathList.AppendItem(seg); _mayHaveCurves = true; SvgPointF endPoint = new SvgPointF(coords[i] + startPoint.X, coords[i + 1] + startPoint.Y); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } break; // End of: bezier // Parse: arcs case 'A': case 'a': for (int i = 0; i < length; i += 7) { if (cmd == 'A') { seg = new SvgPathSegArcAbs( coords[i + 5], coords[i + 6], coords[i], coords[i + 1], coords[i + 2], (!coords[i + 3].Equals(0)), (!coords[i + 4].Equals(0))); SvgPointF endPoint = new SvgPointF(coords[i + 5], coords[i + 6]); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } else { seg = new SvgPathSegArcRel( coords[i + 5], coords[i + 6], coords[i], coords[i + 1], coords[i + 2], (!coords[i + 3].Equals(0)), (!coords[i + 4].Equals(0))); SvgPointF endPoint = new SvgPointF(coords[i + 5] + startPoint.X, coords[i + 6] + startPoint.Y); seg.Limits = new SvgPointF[] { startPoint, endPoint }; startPoint = endPoint; } pathList.AppendItem(seg); _mayHaveCurves = true; } break; // End of: arcs // Parse: close case 'z': case 'Z': closedPath++; seg = new SvgPathSegClosePath(); pathList.AppendItem(seg); if (pathList.Count >= 2) { SvgPointF endPoint = pathList[0].Limits[0]; seg.Limits = new SvgPointF[] { endPoint, startPoint }; startPoint = endPoint; } else { seg.Limits = new SvgPointF[] { startPoint, startPoint }; startPoint = new SvgPointF(0, 0); } break; // End of: close // Unknown path command default: throw new ApplicationException(string.Format("Unknown path command - ({0})", cmd)); } } _isClosed = (closedPath == 1); return(true); }