private void EmitQuadraticCurveTo(SvgPathSeg segment) { var cx = CurPenX; var cy = CurPenY; segment.Accept(_tracker); _builder.QuadraticCurveTo(cx, cy, LastX2, LastY2, CurPenX, CurPenY); }
private void EmitSmoothCubicCurveto(SvgPathSeg segment) { // 8.3.6 The cubic Bézier curve commands // The first control point is assumed to be the reflection of the second control point on the previous command relative to the current point. var cx1 = 2 * CurPenX - LastX2; var cy1 = 2 * CurPenY - LastY2; segment.Accept(_tracker); _builder.CubicCurveTo(cx1, cy1, LastX2, LastY2, CurPenX, CurPenY); }
private void EmitSmoothQuadraticCurveto(SvgPathSeg segment) { // 8.3.7 The quadratic Bézier curve commands // The control point is assumed to be the reflection of the control point on the previous command relative to the current point. var cx = 2 * CurPenX - LastX2; var cy = 2 * CurPenY - LastY2; // quadratic to cubic var cx1 = CurPenX + 2.0f / 3.0f * (cx - CurPenX); var cy1 = CurPenY + 2.0f / 3.0f * (cy - CurPenY); segment.Accept(_tracker); var x = CurPenX; var y = CurPenY; var cx2 = x + 2.0f / 3.0f * (cx - x); var cy2 = y + 2.0f / 3.0f * (cy - y); _builder.CubicCurveTo(cx1, cy1, cx2, cy2, x, y); }
public static GraphicsPath CreatePath(SvgPathElement element) { GraphicsPath gp = new GraphicsPath(); SvgPointF initPoint = new SvgPointF(0, 0); SvgPointF lastPoint = new SvgPointF(0, 0); SvgPointF ptXY = new SvgPointF(0, 0); SvgPathSeg segment = null; SvgPathSegMoveto pathMoveTo = null; SvgPathSegLineto pathLineTo = null; SvgPathSegCurveto pathCurveTo = null; SvgPathSegArc pathArc = null; SvgPathSegList segments = element.PathSegList; int nElems = segments.NumberOfItems; for (int i = 0; i < nElems; i++) { segment = segments.GetItem(i); switch (segment.PathType) { case SvgPathType.MoveTo: //if (DynamicCast.Cast(segment, out pathMoveTo)) pathMoveTo = (SvgPathSegMoveto)segment; gp.StartFigure(); lastPoint = initPoint = pathMoveTo.AbsXY; break; case SvgPathType.LineTo: //else if (DynamicCast.Cast(segment, out pathLineTo)) pathLineTo = (SvgPathSegLineto)segment; ptXY = pathLineTo.AbsXY; gp.AddLine(lastPoint.X, lastPoint.Y, ptXY.X, ptXY.Y); lastPoint = ptXY; break; case SvgPathType.CurveTo: //else if (DynamicCast.Cast(segment, out pathCurveTo)) pathCurveTo = (SvgPathSegCurveto)segment; SvgPointF xy = pathCurveTo.AbsXY; SvgPointF x1y1 = pathCurveTo.CubicX1Y1; SvgPointF x2y2 = pathCurveTo.CubicX2Y2; gp.AddBezier(lastPoint.X, lastPoint.Y, x1y1.X, x1y1.Y, x2y2.X, x2y2.Y, xy.X, xy.Y); lastPoint = xy; break; case SvgPathType.ArcTo: //else if (DynamicCast.Cast(segment, out pathArc)) pathArc = (SvgPathSegArc)segment; ptXY = pathArc.AbsXY; if (lastPoint.Equals(ptXY)) { // If the endpoints (x, y) and (x0, y0) are identical, then this // is equivalent to omitting the elliptical arc segment entirely. } else if (pathArc.R1.Equals(0) || pathArc.R2.Equals(0)) { // Ensure radii are valid gp.AddLine(lastPoint.X, lastPoint.Y, ptXY.X, ptXY.Y); } else { CalculatedArcValues calcValues = pathArc.GetCalculatedArcValues(); GraphicsPath subPath = new GraphicsPath(); subPath.StartFigure(); subPath.AddArc((float)(calcValues.Cx - calcValues.CorrRx), (float)(calcValues.Cy - calcValues.CorrRy), (float)calcValues.CorrRx * 2, (float)calcValues.CorrRy * 2, (float)calcValues.AngleStart, (float)calcValues.AngleExtent); Matrix matrix = new Matrix(); matrix.Translate(-(float)calcValues.Cx, -(float)calcValues.Cy); subPath.Transform(matrix); matrix = new Matrix(); matrix.Rotate((float)pathArc.Angle); subPath.Transform(matrix); matrix = new Matrix(); matrix.Translate((float)calcValues.Cx, (float)calcValues.Cy); subPath.Transform(matrix); gp.AddPath(subPath, true); } lastPoint = ptXY; break; case SvgPathType.Close: //else if (segment is SvgPathSegClosePath) gp.CloseFigure(); lastPoint = initPoint; break; } } string fillRule = element.GetPropertyValue("fill-rule"); if (fillRule == "evenodd") { gp.FillMode = FillMode.Alternate; } else { gp.FillMode = FillMode.Winding; } return(gp); }
public Geometry CreateGeometry(SvgPathElement element) { PathGeometry geometry = new PathGeometry(); var comparer = StringComparison.OrdinalIgnoreCase; string fillRule = element.GetPropertyValue("fill-rule"); string clipRule = element.GetAttribute("clip-rule"); if (!string.IsNullOrWhiteSpace(clipRule) && string.Equals(clipRule, "evenodd", comparer) || string.Equals(clipRule, CssConstants.ValNonzero, comparer)) { fillRule = clipRule; } if (string.Equals(fillRule, "evenodd", comparer)) { geometry.FillRule = FillRule.EvenOdd; } else if (string.Equals(fillRule, CssConstants.ValNonzero, comparer)) { geometry.FillRule = FillRule.Nonzero; } SvgPointF initPoint = new SvgPointF(0, 0); SvgPointF lastPoint = new SvgPointF(0, 0); SvgPointF ptXY = new SvgPointF(0, 0); SvgPathSeg segment = null; SvgPathSegMoveto pathMoveTo = null; SvgPathSegLineto pathLineTo = null; SvgPathSegCurveto pathCurveTo = null; SvgPathSegArc pathArc = null; SvgPathSegList segments = element.PathSegList; int numSegs = segments.NumberOfItems; if (numSegs == 0) { return(geometry); } PathFigure pathFigure = null; for (int i = 0; i < numSegs; i++) { segment = segments.GetItem(i); switch (segment.PathType) { case SvgPathType.MoveTo: //if (DynamicCast.Cast(segment, out pathMoveTo)) pathMoveTo = (SvgPathSegMoveto)segment; if (pathFigure != null) { pathFigure.IsClosed = false; pathFigure.IsFilled = true; geometry.Figures.Add(pathFigure); pathFigure = null; } lastPoint = initPoint = pathMoveTo.AbsXY; pathFigure = new PathFigure(); pathFigure.StartPoint = new Point(initPoint.ValueX, initPoint.ValueY); break; case SvgPathType.LineTo: //else if (DynamicCast.Cast(segment, out pathLineTo)) pathLineTo = (SvgPathSegLineto)segment; ptXY = pathLineTo.AbsXY; pathFigure.Segments.Add(new LineSegment(new Point(ptXY.ValueX, ptXY.ValueY), true)); lastPoint = ptXY; break; case SvgPathType.CurveTo: //else if (DynamicCast.Cast(segment, out pathCurveTo)) pathCurveTo = (SvgPathSegCurveto)segment; SvgPointF xy = pathCurveTo.AbsXY; SvgPointF x1y1 = pathCurveTo.CubicX1Y1; SvgPointF x2y2 = pathCurveTo.CubicX2Y2; pathFigure.Segments.Add(new BezierSegment(new Point(x1y1.ValueX, x1y1.ValueY), new Point(x2y2.ValueX, x2y2.ValueY), new Point(xy.ValueX, xy.ValueY), true)); lastPoint = xy; break; case SvgPathType.ArcTo: //else if (DynamicCast.Cast(segment, out pathArc)) pathArc = (SvgPathSegArc)segment; ptXY = pathArc.AbsXY; if (lastPoint.Equals(ptXY)) { // If the endpoints (x, y) and (x0, y0) are identical, then this // is equivalent to omitting the elliptical arc segment entirely. } else if (pathArc.R1.Equals(0) || pathArc.R2.Equals(0)) { // Ensure radii are valid pathFigure.Segments.Add(new LineSegment(new Point(ptXY.ValueX, ptXY.ValueY), true)); } else { CalculatedArcValues calcValues = pathArc.GetCalculatedArcValues(); pathFigure.Segments.Add(new ArcSegment(new Point(ptXY.ValueX, ptXY.ValueY), new Size(pathArc.R1, pathArc.R2), pathArc.Angle, pathArc.LargeArcFlag, pathArc.SweepFlag ? SweepDirection.Clockwise : SweepDirection.Counterclockwise, true)); } lastPoint = ptXY; break; case SvgPathType.Close: //else if (segment is SvgPathSegClosePath) if (pathFigure != null) { pathFigure.IsClosed = true; pathFigure.IsFilled = true; geometry.Figures.Add(pathFigure); pathFigure = null; } lastPoint = initPoint; break; } } if (pathFigure != null) { pathFigure.IsClosed = false; pathFigure.IsFilled = true; geometry.Figures.Add(pathFigure); } return(geometry); }
public override void ReEvaluateComputeValue(ref ReEvaluateArgs args) { var myspec = this.spec; this.fillColor = myspec.ActualColor; this.strokeColor = myspec.StrokeColor; this.ActualStrokeWidth = ConvertToPx(myspec.StrokeWidth, ref args); if (this.IsPathValid) { return; } ClearCachePath(); if (segments == null) { this.myCachedPath = null; } else { List <SvgPathSeg> segs = this.segments; int segcount = segs.Count; GraphicsPath gpath = this.myCachedPath = new GraphicsPath(); float lastMoveX = 0; float lastMoveY = 0; PointF lastPoint = new PointF(); PointF p2 = new PointF(); //curve control point PointF p3 = new PointF(); //curve control point PointF intm_c3_c = new PointF(); for (int i = 0; i < segcount; ++i) { SvgPathSeg seg = segs[i]; switch (seg.Command) { case SvgPathCommand.ZClosePath: { gpath.CloseFigure(); } break; case SvgPathCommand.MoveTo: { var moveTo = (SvgPathSegMoveTo)seg; PointF moveToPoint; moveTo.GetAbsolutePoints(ref lastPoint, out moveToPoint); lastPoint = moveToPoint; gpath.StartFigure(); lastMoveX = lastPoint.X; lastMoveY = lastPoint.Y; } break; case SvgPathCommand.LineTo: { var lineTo = (SvgPathSegLineTo)seg; PointF lineToPoint; lineTo.GetAbsolutePoints(ref lastPoint, out lineToPoint); gpath.AddLine(lastPoint, lineToPoint); lastPoint = lineToPoint; } break; case SvgPathCommand.HorizontalLineTo: { var hlintTo = (SvgPathSegLineToHorizontal)seg; PointF lineToPoint; hlintTo.GetAbsolutePoints(ref lastPoint, out lineToPoint); gpath.AddLine(lastPoint, lineToPoint); lastPoint = lineToPoint; } break; case SvgPathCommand.VerticalLineTo: { var vlineTo = (SvgPathSegLineToVertical)seg; PointF lineToPoint; vlineTo.GetAbsolutePoints(ref lastPoint, out lineToPoint); gpath.AddLine(lastPoint, lineToPoint); lastPoint = lineToPoint; } break; //--------------------------------------------------------------------------- //curve modes...... case SvgPathCommand.CurveTo: { //cubic curve to (2 control points) var cubicCurve = (SvgPathSegCurveToCubic)seg; PointF p; cubicCurve.GetAbsolutePoints(ref lastPoint, out p2, out p3, out p); gpath.AddBezierCurve(lastPoint, p2, p3, p); lastPoint = p; } break; case SvgPathCommand.QuadraticBezierCurve: { //quadratic curve (1 control point) //auto calculate for c1,c2 var quadCurve = (SvgPathSegCurveToQuadratic)seg; PointF p; quadCurve.GetAbsolutePoints(ref lastPoint, out intm_c3_c, out p); SvgCurveHelper.Curve3GetControlPoints(lastPoint, intm_c3_c, p, out p2, out p3); gpath.AddBezierCurve(lastPoint, p2, p3, p); lastPoint = p; } break; //------------------------------------------------------------------------------------ case SvgPathCommand.SmoothCurveTo: { //smooth cubic curve to var smthC4 = (SvgPathSegCurveToCubicSmooth)seg; PointF c2, p; smthC4.GetAbsolutePoints(ref lastPoint, out c2, out p); //connect with prev segment if (i > 0) { //------------------ //calculate p1 from prev segment //------------------ var prevSeg = segments[i - 1]; //check if prev is curve switch (prevSeg.Command) { case SvgPathCommand.Arc: case SvgPathCommand.CurveTo: case SvgPathCommand.SmoothCurveTo: case SvgPathCommand.QuadraticBezierCurve: case SvgPathCommand.TSmoothQuadraticBezierCurveTo: //make mirror point p2 = SvgCurveHelper.CreateMirrorPoint(p3, lastPoint); p3 = c2; gpath.AddBezierCurve(lastPoint, p2, p3, p); break; default: continue; } } lastPoint = p; } break; case SvgPathCommand.TSmoothQuadraticBezierCurveTo: { //curve 3 var smtC3 = (SvgPathSegCurveToQuadraticSmooth)seg; PointF p; smtC3.GetAbsolutePoints(ref lastPoint, out p); if (i > 0) { //------------------ //calculate p1 from prev segment //------------------ var prevSeg = segments[i - 1]; //check if prev is curve switch (prevSeg.Command) { case SvgPathCommand.Arc: case SvgPathCommand.CurveTo: case SvgPathCommand.SmoothCurveTo: { PointF c = SvgCurveHelper.CreateMirrorPoint(p3, lastPoint); SvgCurveHelper.Curve3GetControlPoints(lastPoint, c, p, out p2, out p3); gpath.AddBezierCurve(lastPoint, p2, p3, p); lastPoint = p; } break; case SvgPathCommand.TSmoothQuadraticBezierCurveTo: { //make mirror point PointF c = SvgCurveHelper.CreateMirrorPoint(intm_c3_c, lastPoint); SvgCurveHelper.Curve3GetControlPoints(lastPoint, c, p, out p2, out p3); gpath.AddBezierCurve(lastPoint, p2, p3, p); lastPoint = p; intm_c3_c = c; } break; case SvgPathCommand.QuadraticBezierCurve: { PointF c = SvgCurveHelper.CreateMirrorPoint(intm_c3_c, lastPoint); SvgCurveHelper.Curve3GetControlPoints(lastPoint, c, p, out p2, out p3); gpath.AddBezierCurve(lastPoint, p2, p3, p); lastPoint = p; intm_c3_c = c; } break; default: continue; } } lastPoint = p; } break; case SvgPathCommand.Arc: { var arcTo = (SvgPathSegArc)seg; PointF p; arcTo.GetAbsolutePoints(ref lastPoint, out p); if (lastPoint.IsEq(p)) { return; } if (arcTo.R1 == 0 && arcTo.R2 == 0) { gpath.AddLine(lastPoint, p); lastPoint = p; return; } PointF[] bz4Points; SvgCurveHelper.MakeBezierCurveFromArc( ref lastPoint, ref p, arcTo.R1, arcTo.R2, arcTo.Angle, arcTo.LargeArgFlag, arcTo.SweepFlag, out bz4Points); int j = bz4Points.Length; int nn = 0; while (nn < j) { gpath.AddBezierCurve( bz4Points[nn], bz4Points[nn + 1], bz4Points[nn + 2], bz4Points[nn + 3]); nn += 4; //step 4 points } //set control points p3 = bz4Points[nn - 2]; p2 = bz4Points[nn - 3]; lastPoint = p; //--------------------------------------------- } break; default: throw new NotSupportedException(); } } } ValidatePath(); }
public virtual void Visit(SvgPathSeg segment) => segment?.Accept(this);
public virtual void DefaultVisit(SvgPathSeg segment) { // nop }
public override void DefaultVisit(SvgPathSeg segment) => throw new NotSupportedException($"SVG Path segment of type '{segment?.GetType()}' can't be converted to a DyanmicPdf SubPath");
public override void DefaultVisit(SvgPathSeg segment) => throw new InvalidOperationException($"Unsupported path segment '{segment?.GetType()}'");
private void EmitLineto(SvgPathSeg segment) { segment.Accept(_tracker); _builder.LineTo(CurPenX, CurPenY); }
private void EmitMoveto(SvgPathSeg segment) { CloseSubPath(); segment.Accept(_tracker); _builder.MoveTo(CurPenX, CurPenY); }