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);
        }
Пример #5
0
        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);
        }
Пример #6
0
        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();
        }
Пример #7
0
 public virtual void Visit(SvgPathSeg segment)
 => segment?.Accept(this);
Пример #8
0
 public virtual void DefaultVisit(SvgPathSeg segment)
 {
     // nop
 }
Пример #9
0
 public override void DefaultVisit(SvgPathSeg segment)
 => throw new NotSupportedException($"SVG Path segment of type '{segment?.GetType()}' can't be converted to a DyanmicPdf SubPath");
Пример #10
0
 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);
 }