Beispiel #1
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();
        }