/// <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 void Parse(Path path, string pathString) { if (string.IsNullOrEmpty(pathString)) { throw new ArgumentNullException("pathString"); } var segments = new SvgPathSegmentList(); try { char command; bool isRelative; foreach (var commandSet in SplitCommands(pathString.TrimEnd(null))) { command = commandSet[0]; isRelative = char.IsLower(command); // http://www.w3.org/TR/SVG11/paths.html#PathDataGeneralInformation CreatePathSegment(command, segments, new CoordinateParser(commandSet.Trim()), isRelative); } foreach (var segment in segments) { segment.AddToPath(path); } } catch (Exception exc) { throw new Exception(string.Format("Error parsing path \"{0}\": {1}", path, exc.Message)); } //return segments; }
public override void AddToPath(Path graphicsPath) { //todo May need to fix //// Important for custom line caps. Force the path the close with an explicit line, not just an implicit close of the figure. //if (graphicsPath.PointCount > 0 && !graphicsPath.PathPoints[0].Equals(graphicsPath.PathPoints[graphicsPath.PathPoints.Length - 1])) //{ // int i = graphicsPath.PathTypes.Length - 1; // while (i >= 0 && graphicsPath.PathTypes[i] > 0) i--; // if (i < 0) i = 0; // graphicsPath.AddLine(graphicsPath.PathPoints[graphicsPath.PathPoints.Length - 1], graphicsPath.PathPoints[i]); //} graphicsPath.Close(); }
public override void AddToPath(Path graphicsPath) { if (Start == End) { return; } if (RadiusX == 0.0f && RadiusY == 0.0f) { graphicsPath.LineTo(Start, End); return; } var sinPhi = Math.Sin(Angle*RadiansPerDegree); var cosPhi = Math.Cos(Angle*RadiansPerDegree); var x1dash = cosPhi*(Start.X - End.X)/2.0 + sinPhi*(Start.Y - End.Y)/2.0; var y1dash = -sinPhi*(Start.X - End.X)/2.0 + cosPhi*(Start.Y - End.Y)/2.0; double root; var numerator = RadiusX*RadiusX*RadiusY*RadiusY - RadiusX*RadiusX*y1dash*y1dash - RadiusY*RadiusY*x1dash*x1dash; var rx = RadiusX; var ry = RadiusY; if (numerator < 0.0) { var s = (float) Math.Sqrt(1.0 - numerator/(RadiusX*RadiusX*RadiusY*RadiusY)); rx *= s; ry *= s; root = 0.0; } else { root = ((Size == SvgArcSize.Large && Sweep == SvgArcSweep.Positive) || (Size == SvgArcSize.Small && Sweep == SvgArcSweep.Negative) ? -1.0 : 1.0)*Math.Sqrt(numerator/(RadiusX*RadiusX*y1dash*y1dash + RadiusY*RadiusY*x1dash*x1dash)); } var cxdash = root*rx*y1dash/ry; var cydash = -root*ry*x1dash/rx; var cx = cosPhi*cxdash - sinPhi*cydash + (Start.X + End.X)/2.0; var cy = sinPhi*cxdash + cosPhi*cydash + (Start.Y + End.Y)/2.0; var theta1 = CalculateVectorAngle(1.0, 0.0, (x1dash - cxdash)/rx, (y1dash - cydash)/ry); var dtheta = CalculateVectorAngle((x1dash - cxdash)/rx, (y1dash - cydash)/ry, (-x1dash - cxdash)/rx, (-y1dash - cydash)/ry); if (Sweep == SvgArcSweep.Negative && dtheta > 0) { dtheta -= 2.0*Math.PI; } else if (Sweep == SvgArcSweep.Positive && dtheta < 0) { dtheta += 2.0*Math.PI; } var segments = (int) Math.Ceiling(Math.Abs(dtheta/(Math.PI/2.0))); var delta = dtheta/segments; var t = 8.0/3.0*Math.Sin(delta/4.0)*Math.Sin(delta/4.0)/Math.Sin(delta/2.0); var startX = Start.X; var startY = Start.Y; for (var i = 0; i < segments; ++i) { var cosTheta1 = Math.Cos(theta1); var sinTheta1 = Math.Sin(theta1); var theta2 = theta1 + delta; var cosTheta2 = Math.Cos(theta2); var sinTheta2 = Math.Sin(theta2); var endpointX = cosPhi*rx*cosTheta2 - sinPhi*ry*sinTheta2 + cx; var endpointY = sinPhi*rx*cosTheta2 + cosPhi*ry*sinTheta2 + cy; var dx1 = t*(-cosPhi*rx*sinTheta1 - sinPhi*ry*cosTheta1); var dy1 = t*(-sinPhi*rx*sinTheta1 + cosPhi*ry*cosTheta1); var dxe = t*(cosPhi*rx*sinTheta2 + sinPhi*ry*cosTheta2); var dye = t*(sinPhi*rx*sinTheta2 - cosPhi*ry*cosTheta2); graphicsPath.CurveTo(new Point(startX, startY), new Point((startX + dx1), (startY + dy1)), new Point((endpointX + dxe), (endpointY + dye)), new Point(endpointX, endpointY)); theta1 = theta2; startX = (float) endpointX; startY = (float) endpointY; } }
public override void AddToPath(Path graphicsPath) { graphicsPath.MoveTo(Start, End, false); }
private void AddElement(IList<IDrawable> list, XElement e, Pen inheritPen, BaseBrush inheritBaseBrush) { Element element = null; var styleAttributedDictionary = e.Attributes().ToDictionary(k => k.Name.LocalName, v => v.Value); var pen = _stylesParser.GetPen(styleAttributedDictionary); var baseBrush = _stylesParser.GetBrush(styleAttributedDictionary,defs, pen); var style = ReadString(e.Attribute("style")); if (!string.IsNullOrWhiteSpace(style)) { ApplyStyle(style, ref pen, ref baseBrush); } pen = pen ?? inheritPen; baseBrush = baseBrush ?? inheritBaseBrush; //var id = ReadString (e.Attribute ("id")); // // Elements // switch (e.Name.LocalName) { case "text": { var x = _valuesParser.ReadNumber(e.Attribute("x")); var y = _valuesParser.ReadNumber(e.Attribute("y")); var text = e.Value.Trim(); var font = new Font(); element = new Text(text, new Rect(new Point(x, y), new Size(double.MaxValue, double.MaxValue)), font, TextAlignment.Left, pen, baseBrush); } break; case "rect": { var x = _valuesParser.ReadNumber(e.Attribute("x")); var y = _valuesParser.ReadNumber(e.Attribute("y")); var width = _valuesParser.ReadNumber(e.Attribute("width")); var height = _valuesParser.ReadNumber(e.Attribute("height")); element = new Rectangle(new Point(x, y), new Size(width, height), pen, baseBrush); } break; case "ellipse": { var cx = _valuesParser.ReadNumber(e.Attribute("cx")); var cy = _valuesParser.ReadNumber(e.Attribute("cy")); var rx = _valuesParser.ReadNumber(e.Attribute("rx")); var ry = _valuesParser.ReadNumber(e.Attribute("ry")); element = new Ellipse(new Point(cx - rx, cy - ry), new Size(2*rx, 2*ry), pen, baseBrush); } break; case "circle": { var cx = _valuesParser.ReadNumber(e.Attribute("cx")); var cy = _valuesParser.ReadNumber(e.Attribute("cy")); var rr = _valuesParser.ReadNumber(e.Attribute("r")); element = new Ellipse(new Point(cx - rr, cy - rr), new Size(2*rr, 2*rr), pen, baseBrush); } break; case "path": { var dA = e.Attribute("d"); if (dA != null && !string.IsNullOrWhiteSpace(dA.Value)) { var p = new Path(pen, baseBrush); SvgPathParser.Parse(p, dA.Value); element = p; } } break; case "g": { var g = new Group(); AddElements(g.Children, e.Elements(), pen, baseBrush); element = g; } break; case "use": { var href = ReadString(e.Attributes().FirstOrDefault(x => x.Name.LocalName == "href")); if (!string.IsNullOrWhiteSpace(href)) { XElement useE; if (defs.TryGetValue(href.Trim().Replace("#", ""), out useE)) { var useList = new List<IDrawable>(); AddElement(useList, useE, pen, baseBrush); element = useList.OfType<Element>().FirstOrDefault(); } } } break; case "title": Graphic.Title = ReadString(e); break; case "description": Graphic.Description = ReadString(e); break; case "defs": // Already read in earlier pass break; case "namedview": case "metadata": case "SVGTestCase": case "switch": break; default: throw new NotSupportedException("SVG element \"" + e.Name.LocalName + "\" is not supported"); } if (element != null) { element.Transform = ReadTransform(ReadString(e.Attribute("transform"))); list.Add(element); } }
public override void AddToPath(Path graphicsPath) { graphicsPath.LineTo(Start, End); }
public abstract void AddToPath(Path graphicsPath);
public override void AddToPath(Path graphicsPath) { graphicsPath.CurveTo(Start, FirstControlPoint, SecondControlPoint, End); }