Пример #1
0
 private void AddCurveToPoint(PointF point1, PointF point2, PointF point3)
 {
     Check(point1);
     Check(point2);
     Check(point3);
                 #if __UNIFIED__
     Control.AddCurveToPoint(point1.ToNS(), point2.ToNS(), point3.ToNS());
                 #else
     Control.AddCurveToPoint(point1.ToSD(), point2.ToSD(), point3.ToSD());
                 #endif
 }
        private void Setup()
        {
            // set up events
            TouchUpInside += OnTapped;

            // create the check path
            var path = new CGPath();

            path.MoveToPoint(5.07473346f, 20.2956615f);
            path.AddCurveToPoint(3.1031115f, 24.4497281f, 2f, 29.0960413f, 2f, 34f);
            path.AddCurveToPoint(2f, 51.673112f, 16.326888f, 66f, 34f, 66f);
            path.AddCurveToPoint(51.673112f, 66f, 66f, 51.673112f, 66f, 34f);
            path.AddCurveToPoint(66f, 16.326888f, 51.673112f, 2f, 34f, 2f);
            path.AddCurveToPoint(21.3077047f, 2f, 10.3412842f, 9.38934836f, 5.16807419f, 20.1007094f);
            path.AddLineToPoint(29.9939289f, 43.1625671f);
            path.AddLineToPoint(56.7161293f, 17.3530369f);

            shape.Path  = path;
            circle.Path = path;
            check.Path  = path;

            shape.StrokeColor  = color.CGColor;
            circle.StrokeColor = skeletonColor.CGColor;
            check.StrokeColor  = skeletonColor.CGColor;

            shape.StrokeStart  = circleStrokeStart;
            shape.StrokeEnd    = circleStrokeEnd;
            circle.StrokeStart = circleStrokeStart;
            circle.StrokeEnd   = circleStrokeEnd;
            check.StrokeStart  = checkStrokeStart;
            check.StrokeEnd    = checkStrokeEnd;

            shape.LineWidth  = lineWidth;
            circle.LineWidth = lineWidth;
            check.LineWidth  = lineWidthBold;

            foreach (var layer in new[] { circle, check, shape })
            {
                layer.FillColor     = null;
                layer.MiterLimit    = 4;
                layer.LineCap       = CAShapeLayer.CapRound;
                layer.MasksToBounds = true;

                var strokingPath = layer.Path.CopyByStrokingPath(4f, CGLineCap.Round, CGLineJoin.Miter, 4f);
                layer.Bounds  = strokingPath.BoundingBox;
                layer.Actions = NSDictionary.FromObjectsAndKeys(
                    new[] { NSNull.Null, NSNull.Null, NSNull.Null },
                    new[] { "strokeStart", "strokeEnd", "transform" });
                Layer.AddSublayer(layer);
            }
        }
Пример #3
0
 private void AddCurveToPoint(PointF point1, PointF point2, PointF point3)
 {
     Check(point1);
     Check(point2);
     Check(point3);
     Control.AddCurveToPoint(point1.ToNS(), point2.ToNS(), point3.ToNS());
 }
        public static CGPath ToCGPath(this NSBezierPath nsPath)
        {
            var cgPath = new CGPath();
            var points = null as CGPoint[];

            for (int i = 0; i < nsPath.ElementCount; i++)
            {
                var type = nsPath.ElementAt(i, out points);

                switch (type)
                {
                case NSBezierPathElement.MoveTo:
                    cgPath.MoveToPoint(points[0]);
                    break;

                case NSBezierPathElement.LineTo:
                    cgPath.AddLineToPoint(points[0]);
                    break;

                case NSBezierPathElement.CurveTo:
                    cgPath.AddCurveToPoint(cp1: points[0], cp2: points[1], point: points[2]);
                    break;

                case NSBezierPathElement.ClosePath:
                    cgPath.CloseSubpath();
                    break;
                }
            }

            return(cgPath);
        }
        public static CGPath ToCGPath(this NSBezierPath bezierPath)
        {
            var path = new CGPath();

            for (var i = 0; i < bezierPath.ElementCount; i++)
            {
                var type = bezierPath.ElementAt(i, out var points);

                switch (type)
                {
                case NSBezierPathElement.MoveTo:
                    path.MoveToPoint(points[0]);
                    break;

                case NSBezierPathElement.LineTo:
                    path.AddLineToPoint(points[0]);
                    break;

                case NSBezierPathElement.CurveTo:
                    path.AddCurveToPoint(points[0], points[1], points[2]);
                    break;

                case NSBezierPathElement.ClosePath:
                    path.CloseSubpath();
                    break;
                }
            }

            return(path);
        }
Пример #6
0
        public override void RelCurveTo(object backend, double dx1, double dy1, double dx2, double dy2, double dx3, double dy3)
        {
            CGPath path = (CGPath)backend;
            PointF p    = path.CurrentPoint;

            path.AddCurveToPoint((float)(p.X + dx1), (float)(p.Y + dy1), (float)(p.X + dx2), (float)(p.Y + dy2), (float)(p.X + dx3), (float)(p.Y + dy3));
        }
        // Creates the path that we'll use to animate on. Once the path is created, it calls
        // DrawPathAsBackground to draw the path on the screen.
        protected void CreatePath()
        {
            // define our path
            PointF curve1StartPoint    = new PointF(56, 104);
            PointF curve1ControlPoint1 = new PointF(50, 250);
            PointF curve1ControlPoint2 = new PointF(220, 450);
            PointF curve1EndPoint      = new PointF(384, 450);
            PointF curve2ControlPoint1 = new PointF(500, 450);
            PointF curve2ControlPoint2 = new PointF(700, 650);
            PointF curve2EndPoint      = new PointF(700, 900);

            animationPath.MoveToPoint(curve1StartPoint.X, curve1StartPoint.Y);
            animationPath.AddCurveToPoint(curve1ControlPoint1.X, curve1ControlPoint1.Y, curve1ControlPoint2.X, curve1ControlPoint2.Y, curve1EndPoint.X, curve1EndPoint.Y);
            animationPath.AddCurveToPoint(curve2ControlPoint1.X, curve2ControlPoint1.Y, curve2ControlPoint2.X, curve2ControlPoint2.Y, curve2EndPoint.X, curve2EndPoint.Y);

            //
            DrawPathAsBackground();
        }
Пример #8
0
        void PlotPath(GraphicsPath path)
        {
            float x1 = 0, y1 = 0, x2 = 0, y2 = 0, x3 = 0, y3 = 0;
            var   points = path.PathPoints;
            var   types  = path.PathTypes;
            int   bidx   = 0;

            for (int i = 0; i < points.Length; i++)
            {
                var point = points [i];
                var type  = (PathPointType)types [i];

                switch (type & PathPointType.PathTypeMask)
                {
                case PathPointType.Start:
                    regionPath.MoveToPoint(point.ToCGPoint());
                    break;

                case PathPointType.Line:
                    regionPath.AddLineToPoint(point.ToCGPoint());
                    break;

                case PathPointType.Bezier3:
                    // collect 3 points
                    switch (bidx++)
                    {
                    case 0:
                        x1 = point.X;
                        y1 = point.Y;
                        break;

                    case 1:
                        x2 = point.X;
                        y2 = point.Y;
                        break;

                    case 2:
                        x3 = point.X;
                        y3 = point.Y;
                        break;
                    }
                    if (bidx == 3)
                    {
                        regionPath.AddCurveToPoint(x1, y1, x2, y2, x3, y3);
                        bidx = 0;
                    }
                    break;

                default:
                    throw new Exception("Inconsistent internal state, path type=" + type);
                }
                if ((type & PathPointType.CloseSubpath) != 0)
                {
                    regionPath.CloseSubpath();
                }
            }
        }
Пример #9
0
        private void AppendCubicCurve(bool relative)
        {
            if (_operands.Count % 6 != 0)
            {
                throw new Exception("Invalid number of parameters for C command");
            }

            for (int i = 0; i < _operands.Count; i += 6)
            {
                float x1 = _operands[i + 0];
                float y1 = _operands[i + 1];
                float x2 = _operands[i + 2];
                float y2 = _operands[i + 3];
                float x  = _operands[i + 4];
                float y  = _operands[i + 5];

                _spath.BezierCurveTo(x1, y1, x2, y2, x, y, relative);

                if (relative)
                {
                    x1 += _posx;
                    y1 += _posy;
                    x2 += _posx;
                    y2 += _posy;
                    x  += _posx;
                    y  += _posy;
                }
#if OSX
                _cgpath.AddCurveToPoint(x1, y1, x2, y2, x, y);
#endif

                _last_control_x = x2;
                _last_control_y = y2;

                _posx = x;
                _posy = y;

                _scaler.AddXYOperands(x1, y1);
                _scaler.AddXYOperands(x2, y2);
                _scaler.AddXYOperands(x, y);
            }
            _scaler.AddOperator('C');
        }
Пример #10
0
        private void CurveTo(bool isRelative)
        {
            var point = NewPoint(NextValue, NextValue, isRelative, false);
            var x     = NextValue;
            var y     = NextValue;

            var isQuad = char.IsLetter(_commandStack.Peek()[0]);
            var point2 = NewPoint(x, y, isRelative, isQuad);

            if (isQuad)
            {
                _path.AddQuadCurveToPoint(point.X, point.Y, point2.X, point2.Y);
            }
            else
            {
                var point3 = NewPoint(NextValue, NextValue, isRelative, true);
                _path.AddCurveToPoint(point, point2, point3);
                _lastCurveControlPoint = point2;
            }
        }
Пример #11
0
        public static CGPath ToCGPath(this  _BezierPath nSBezierPath)
        {
#if __IOS__
            return(nSBezierPath.CGPath);
#elif __MACOS__
            // Then draw the path elements.
            var numElements = nSBezierPath.ElementCount;

            if (numElements > 0)
            {
                var path         = new CGPath();
                var points       = new CGPoint[3];
                var didClosePath = true;

                for (var i = 0; i < numElements; i++)
                {
                    switch (nSBezierPath.ElementAt(i, out points))
                    {
                    case NSBezierPathElement.MoveTo:
                        path.MoveToPoint(points[0].X, points[0].Y);
                        break;

                    case NSBezierPathElement.LineTo:
                        path.AddLineToPoint(points[0].X, points[0].Y);
                        didClosePath = false;
                        break;

                    case NSBezierPathElement.CurveTo:
                        path.AddCurveToPoint(points[0].X, points[0].Y,
                                             points[1].X, points[1].Y,
                                             points[2].X, points[2].Y);
                        didClosePath = false;
                        break;

                    case NSBezierPathElement.ClosePath:
                        path.CloseSubpath();
                        didClosePath = true;
                        break;
                    }
                }

                // Be sure the path is closed or Quartz may not do valid hit detection.
                if (!didClosePath)
                {
                    path.CloseSubpath();
                }

                return(path);
            }

            return(new CGPath());
#endif
        }
Пример #12
0
        // Creates the path that we'll use to animate on. Once the path is created, it calls
        // DrawPathAsBackground to draw the path on the screen.
        protected void CreatePath()
        {
            // define our path
            var curve1StartPoint    = new PointF(56f, 104f);
            var curve1ControlPoint1 = new PointF(50f, 250f);
            var curve1ControlPoint2 = new PointF(220f, 450f);
            var curve1EndPoint      = new PointF(384f, 450f);
            var curve2ControlPoint1 = new PointF(500f, 450f);
            var curve2ControlPoint2 = new PointF(700f, 650f);
            var curve2EndPoint      = new PointF(700f, 900f);

            animationPath.MoveToPoint(curve1StartPoint.X, curve1StartPoint.Y);
            animationPath.AddCurveToPoint(curve1ControlPoint1.X, curve1ControlPoint1.Y,
                                          curve1ControlPoint2.X, curve1ControlPoint2.Y,
                                          curve1EndPoint.X, curve1EndPoint.Y);

            animationPath.AddCurveToPoint(curve2ControlPoint1.X, curve2ControlPoint1.Y,
                                          curve2ControlPoint2.X, curve2ControlPoint2.Y,
                                          curve2EndPoint.X, curve2EndPoint.Y);

            DrawPathAsBackground();
        }
Пример #13
0
		public ClockView ()
		{
			// Set background to pink.
			this.BackgroundColor = UIColor.FromRGB (1.0f, 0.8f, 0.8f);

			// All paths are based on 100-unit clock radius
			//		centered at (0, 0)

			// Define circle for tick marks.
			tickMarks = new CGPath ();
			tickMarks.AddEllipseInRect(new CGRect(-90, -90, 180, 180));

			// Hour, minute, second hands defined to point straight up.

			// Define hour hand.
			hourHand = new CGPath ();
			hourHand.MoveToPoint (0, -60);
			hourHand.AddCurveToPoint (0, -30, 20, -30, 5, - 20);
			hourHand.AddLineToPoint (5, 0);
			hourHand.AddCurveToPoint (5, 7.5f, -5, 7.5f, -5, 0);
			hourHand.AddLineToPoint (-5, -20);
			hourHand.AddCurveToPoint (-20, -30, 0, -30, 0, -60);
			hourHand.CloseSubpath ();

			// Define minute hand.
			minuteHand = new CGPath ();
			minuteHand.MoveToPoint (0, -80);
			minuteHand.AddCurveToPoint (0, -75, 0, -70, 2.5f, -60);
			minuteHand.AddLineToPoint (2.5f, 0);
			minuteHand.AddCurveToPoint (2.5f, 5, -2.5f, 5, -2.5f, 0);
			minuteHand.AddLineToPoint (-2.5f, -60);
			minuteHand.AddCurveToPoint (0, -70, 0, -75, 0, -80);
			minuteHand.CloseSubpath ();

			// Define second hand.
			secondHand = new CGPath ();
			secondHand.MoveToPoint (0, 10);
			secondHand.AddLineToPoint(0, -80);
		}
Пример #14
0
        public ClockView()
        {
            // Set background to pink.
            this.BackgroundColor = UIColor.FromRGB(1.0f, 0.8f, 0.8f);

            // All paths are based on 100-unit clock radius
            //		centered at (0, 0)

            // Define circle for tick marks.
            tickMarks = new CGPath();
            tickMarks.AddEllipseInRect(new CGRect(-90, -90, 180, 180));

            // Hour, minute, second hands defined to point straight up.

            // Define hour hand.
            hourHand = new CGPath();
            hourHand.MoveToPoint(0, -60);
            hourHand.AddCurveToPoint(0, -30, 20, -30, 5, -20);
            hourHand.AddLineToPoint(5, 0);
            hourHand.AddCurveToPoint(5, 7.5f, -5, 7.5f, -5, 0);
            hourHand.AddLineToPoint(-5, -20);
            hourHand.AddCurveToPoint(-20, -30, 0, -30, 0, -60);
            hourHand.CloseSubpath();

            // Define minute hand.
            minuteHand = new CGPath();
            minuteHand.MoveToPoint(0, -80);
            minuteHand.AddCurveToPoint(0, -75, 0, -70, 2.5f, -60);
            minuteHand.AddLineToPoint(2.5f, 0);
            minuteHand.AddCurveToPoint(2.5f, 5, -2.5f, 5, -2.5f, 0);
            minuteHand.AddLineToPoint(-2.5f, -60);
            minuteHand.AddCurveToPoint(0, -70, 0, -75, 0, -80);
            minuteHand.CloseSubpath();

            // Define second hand.
            secondHand = new CGPath();
            secondHand.MoveToPoint(0, 10);
            secondHand.AddLineToPoint(0, -80);
        }
Пример #15
0
        CGPath iOSCreatePath(GraphicsPath p)
        {
            CGPath path = new CGPath();

            for (int i = 0; i < p._segments.Count; i++)
            {
                {
                    var ln = p._segments[i] as GraphicsPath._LineSegment;
                    if (ln != null)
                    {
                        if (i == 0)
                        {
                            path.MoveToPoint(ln.x1, ln.y1);
                        }
                        else
                        {
                            path.AddLineToPoint(ln.x1, ln.y1);
                        }
                        path.AddLineToPoint(ln.x2, ln.y2);
                        continue;
                    }
                }
                {
                    var bz = p._segments[i] as GraphicsPath._BezierSegment;
                    if (bz != null)
                    {
                        if (i == 0)
                        {
                            path.MoveToPoint(bz.x1, bz.y1);
                        }
                        else
                        {
                            path.AddLineToPoint(bz.x1, bz.y1);
                        }

                        path.AddCurveToPoint(
                            bz.x2, bz.y2,
                            bz.x3, bz.y3,
                            bz.x4, bz.y4);
                        continue;
                    }
                }
            }
            if (p._closed)
            {
                path.CloseSubpath();
            }

            return(path);
        }
Пример #16
0
        public static CGPath ToCGPath(this NSBezierPath path, bool closePath)
        {
            int i, numElements;

            // Need to begin a path here.
            CGPath cgpath = new CGPath();

            // Then draw the path elements.
            numElements = (int)path.ElementCount;

            if (numElements > 0)
            {
                CGPoint [] points       = new CGPoint [3];
                bool       didClosePath = true;

                for (i = 0; i < numElements; i++)
                {
                    switch (path.ElementAt(i, out points))
                    {
                    case NSBezierPathElement.MoveTo:
                        cgpath.MoveToPoint(points [0].X, points [0].Y);
                        break;

                    case NSBezierPathElement.LineTo:
                        cgpath.AddLineToPoint(points [0].X, points [0].Y);
                        didClosePath = false;
                        break;

                    case NSBezierPathElement.CurveTo:
                        cgpath.AddCurveToPoint(points [0], points [1], points [2]);
                        didClosePath = false;
                        break;

                    case NSBezierPathElement.ClosePath:
                        cgpath.CloseSubpath();
                        didClosePath = true;
                        break;
                    }
                }

                // Be sure the path is closed or Quartz may not do valid hit detection.
                if (!didClosePath && closePath)
                {
                    cgpath.CloseSubpath();
                }
            }

            return(cgpath);
        }
Пример #17
0
        public void AddCurveToPoint()
        {
            var matrix = CGAffineTransform.MakeIdentity();

            using (CGPath p1 = new CGPath())
                using (CGPath p2 = new CGPath()) {
                    Assert.IsTrue(p1.IsEmpty, "IsEmpty-1");
                    p1.MoveToPoint(0, 0);
                    p1.AddCurveToPoint(1, 2, 3, 4, 5, 6);
                    p2.MoveToPoint(0, 0);
                    p2.AddCurveToPoint(matrix, 1, 2, 3, 4, 5, 6);
                    Assert.IsFalse(p1.IsEmpty, "IsEmpty-2");
                    Assert.That(p1, Is.EqualTo(p2), "CGPathEqualToPath");
                }
        }
Пример #18
0
        void DrawPathOnLayer(CAShapeLayer layer)
        {
            var offset = Math.Abs(CurrentStartPosition.X - CurrentEndPosition.X) / 5;

            var ctrlPointA = new CGPoint(CurrentEndPosition.X - offset, CurrentStartPosition.Y);
            var ctrlPointB = new CGPoint(CurrentStartPosition.X + offset, CurrentEndPosition.Y);

            var path = new CGPath();

            path.MoveToPoint(CurrentStartPosition);
            path.AddCurveToPoint(
                ctrlPointA.X, ctrlPointA.Y,
                ctrlPointB.X, ctrlPointB.Y,
                CurrentEndPosition.X, CurrentEndPosition.Y);

            layer.Path = path;
        }
Пример #19
0
 private static CGPath AddBeziers(CGPath path, SKPoint[] controlPoints)
 {
     path.MoveToPoint(CG.Point(controlPoints[0]));
     for (int i = 0; i < controlPoints.Length - 2; i += 4)
     {
         if (i + 3 > controlPoints.Length - 1)
         {
             var cp = CG.Point(controlPoints[i + 1]); var p = CG.Point(controlPoints[i + 2]);
             path.AddQuadCurveToPoint(cp.X, cp.Y, p.X, p.Y);
         }
         else
         {
             path.AddCurveToPoint(CG.Point(controlPoints[i + 1]), CG.Point(controlPoints[i + 2]), CG.Point(controlPoints[i + 3]));
         }
     }
     return(path);
 }
Пример #20
0
        //TODO: we should move this to a shared place
        public static CGPath ToCGPath(this NSBezierPath path)
        {
            var numElements = path.ElementCount;

            if (numElements == 0)
            {
                return(null);
            }

            CGPath result       = new CGPath();
            bool   didClosePath = true;


            for (int i = 0; i < numElements; i++)
            {
                CGPoint[] points;
                var       element = path.ElementAt(i, out points);
                if (element == NSBezierPathElement.MoveTo)
                {
                    result.MoveToPoint(points[0].X, points[0].Y);
                }
                else if (element == NSBezierPathElement.LineTo)
                {
                    result.AddLineToPoint(points[0].X, points[0].Y);
                    didClosePath = false;
                }
                else if (element == NSBezierPathElement.CurveTo)
                {
                    result.AddCurveToPoint(points[0].X, points[0].Y,
                                           points[1].X, points[1].Y,
                                           points[2].X, points[2].Y);
                    didClosePath = false;
                }
                else if (element == NSBezierPathElement.ClosePath)
                {
                    result.CloseSubpath();
                }
            }

            // Be sure the path is closed or Quartz may not do valid hit detection.
            if (!didClosePath)
            {
                result.CloseSubpath();
            }
            return(result);
        }
Пример #21
0
        public static void DrawCurve(CGContext context, IEnumerable <CGPoint> points, LineStyle lineStyle, double intensity = 0.15f)
        {
            if ((points?.Count() ?? 0) < 2)
            {
                return;
            }

            var curvePath = new CGPath();

            var pointsCount = points.Count();

            var currentDx = new Func <int, CGPoint>((int arg) => points.ElementAt(arg + 1 < pointsCount ? arg + 1 : arg).Subtract(points.ElementAt(arg - 1)).Multiply(intensity));

            var prevDx = new Func <int, CGPoint>((int arg) => points.ElementAt(arg).Subtract(points.ElementAt(arg - (arg > 1 ? 2 : 1))).Multiply(intensity));

            var curveDirections = points
                                  .Skip(1)
                                  .Take(pointsCount - 1)
                                  .Select((CGPoint point, int index) => new
            {
                Point    = point,
                Control1 = points.ElementAt(index).Add(prevDx(index + 1)),
                Control2 = point.Subtract(currentDx(index + 1))
            });

            curvePath.MoveToPoint(points.ElementAt(0));

            foreach (var curve in curveDirections)
            {
                curvePath.AddCurveToPoint(curve.Control1, curve.Control2, curve.Point);
            }

            context.AddPath(curvePath);

            context.SetLineWidth(lineStyle.LineWidth);

            context.SetStrokeColor(lineStyle.Color.CGColor);

            context.StrokePath();
        }
Пример #22
0
 public void AddBezier(PointF start, PointF control1, PointF control2, PointF end)
 {
     ConnectTo(start);
     Control.AddCurveToPoint(control1.X, control1.Y, control2.X, control2.Y, end.X, end.Y);
 }
Пример #23
0
		void drawLines ()
		{
			layer.RemoveAllAnimations ();

			var dot = new CGRect (0, 0, lineWidth, lineWidth);

			nfloat x, y;

			CGPoint start = CGPoint.Empty;
			CGPoint end = CGPoint.Empty;


			// Draw curved graph line
			using (UIColor color = UIColor.White.ColorWithAlpha (0.25f), dotColor = UIColor.White.ColorWithAlpha (0.70f)) {

				//color.SetStroke ();

				//dotColor.SetFill ();

				//ctx.SetLineWidth (lineWidth);

				using (CGPath path = new CGPath ()) {


					var count = hourly ? HourlyTemps.Count : (Forecasts.Count * 2);

					for (int i = 0; i < count; i++) {

						// adjusted index
						var ai = i;

						double temp;

						if (hourly) {

							temp = HourlyTemps [ai];

						} else {

							// reset start when switching from highs to lows
							if (i == Forecasts.Count) start = CGPoint.Empty;

							var highs = i < Forecasts.Count;

							ai = highs ? i : i - Forecasts.Count;

							temp = highs ? HighTemps [ai] : LowTemps [ai];
						}

						var percent = ((nfloat)temp - scaleLow) / scaleRange;


						x = padding + inset + (ai * scaleX);

						y = graphRect.GetMaxY () - (graphRect.Height * percent);

						end = new CGPoint (x, y);


						if (!hourly) {

							dot.X = end.X - (lineWidth / 2);
							dot.Y = end.Y - (lineWidth / 2);

							path.AddEllipseInRect (dot);

							//ctx.AddEllipseInRect (dot);
						}


						if (start == CGPoint.Empty) {

							path.MoveToPoint (end);

						} else {

							path.MoveToPoint (start);

							if (hourly) {

								path.AddLineToPoint (end);

							} else {

								var diff = (end.X - start.X) / 2;

								path.AddCurveToPoint (end.X - diff, start.Y, start.X + diff, end.Y, end.X, end.Y);
							}
						}

						start = end;
					}

					// draw all dots to context
					//if (!hourly) ctx.DrawPath (CGPathDrawingMode.Fill);

					// add line path to context
					layer.Path = path;
					//ctx.AddPath (path);

					// draw lines
					//ctx.DrawPath (CGPathDrawingMode.Stroke);

					layer.LineWidth = lineWidth;
					layer.StrokeColor = color.CGColor;
					layer.FillColor = dotColor.CGColor;

					CABasicAnimation pathAnimation = new CABasicAnimation { KeyPath = "strokeEnd" };
					pathAnimation.Duration = 1.0;
					pathAnimation.From = NSNumber.FromNFloat (0);
					pathAnimation.To = NSNumber.FromNFloat (1);
					layer.AddAnimation (pathAnimation, "strokeEndAnimation");

				}
			}
		}
Пример #24
0
        public static void DrawFilledCurvePath(CGContext context, IEnumerable <CGPoint> points, IEnumerable <CGPoint> pointsBottom, UIColor fillColor, double intensity = 0.15f, bool reverse = true)
        {
            var pointsBottomReversed = reverse ? pointsBottom.Reverse() : pointsBottom;

            if ((points?.Count() ?? 0) < 2)
            {
                return;
            }

            var fillPath = new CGPath();

            var pointsCount = points.Count();

            var currentDx = new Func <int, IEnumerable <CGPoint>, CGPoint>((int arg, IEnumerable <CGPoint> p) => p.ElementAt(arg + 1 < p.Count() ? arg + 1 : arg).Subtract(p.ElementAt(arg - 1)).Multiply(intensity));

            var prevDx = new Func <int, IEnumerable <CGPoint>, CGPoint>((int arg, IEnumerable <CGPoint> p) => p.ElementAt(arg).Subtract(p.ElementAt(arg - (arg > 1 ? 2 : 1))).Multiply(intensity));

            var curveDirections = points
                                  .Skip(1)
                                  .Take(pointsCount - 1)
                                  .Select((CGPoint point, int index) => new
            {
                Point    = point,
                Control1 = points.ElementAt(index).Add(prevDx(index + 1, points)),
                Control2 = point.Subtract(currentDx(index + 1, points))
            });

            fillPath.MoveToPoint(points.ElementAt(0));

            foreach (var curve in curveDirections)
            {
                fillPath.AddCurveToPoint(curve.Control1, curve.Control2, curve.Point);
            }

            pointsCount = pointsBottomReversed.Count();

            fillPath.AddLineToPoint(pointsBottomReversed.ElementAt(0));

            var curveDirectionsSecond = pointsBottomReversed
                                        .Skip(1)
                                        .Take(pointsCount - 1)
                                        .Select((CGPoint point, int index) => new
            {
                Point    = point,
                Control1 = pointsBottomReversed.ElementAt(index).Add(prevDx(index + 1, pointsBottomReversed)),
                Control2 = point.Subtract(currentDx(index + 1, pointsBottomReversed))
            });

            foreach (var curve in curveDirectionsSecond)
            {
                fillPath.AddCurveToPoint(curve.Control1, curve.Control2, curve.Point);
            }

            fillPath.CloseSubpath();

            context.AddPath(fillPath);

            fillColor.SetFill();

            context.FillPath();
        }
Пример #25
0
        void drawLines()
        {
            layer.RemoveAllAnimations();

            var dot = new CGRect(0, 0, lineWidth, lineWidth);

            nfloat x, y;

            CGPoint start = CGPoint.Empty;
            CGPoint end   = CGPoint.Empty;


            // Draw curved graph line
            using (UIColor color = UIColor.White.ColorWithAlpha(0.25f), dotColor = UIColor.Clear) {
                using (CGPath path = new CGPath()) {
                    var count = hourly ? HourlyTemps.Count : (Forecasts.Count * 2);

                    for (int i = 0; i < count; i++)
                    {
                        // adjusted index
                        var ai = i;

                        double temp;

                        if (hourly)
                        {
                            temp = HourlyTemps [ai];
                        }
                        else
                        {
                            // reset start when switching from highs to lows
                            if (i == Forecasts.Count)
                            {
                                start = CGPoint.Empty;
                            }

                            var highs = i < Forecasts.Count;

                            ai = highs ? i : i - Forecasts.Count;

                            temp = highs ? HighTemps [ai] : LowTemps [ai];
                        }

                        var percent = ((nfloat)temp - scaleLow) / scaleRange;


                        x = padding + inset + (ai * scaleX);

                        y = graphRect.GetMaxY() - (graphRect.Height * percent);

                        end = new CGPoint(x, y);


                        if (!hourly)
                        {
                            dot.X = end.X - (lineWidth / 2);
                            dot.Y = end.Y - (lineWidth / 2);

                            path.AddEllipseInRect(dot);
                        }


                        if (start == CGPoint.Empty)
                        {
                            path.MoveToPoint(end);
                        }
                        else
                        {
                            path.MoveToPoint(start);

                            if (hourly)
                            {
                                path.AddLineToPoint(end);
                            }
                            else
                            {
                                var diff = (end.X - start.X) / 2;

                                path.AddCurveToPoint(end.X - diff, start.Y, start.X + diff, end.Y, end.X, end.Y);
                            }
                        }

                        start = end;
                    }

                    // add line path to context
                    layer.Path = path;

                    layer.LineWidth   = lineWidth;
                    layer.StrokeColor = color.CGColor;
                    layer.FillColor   = dotColor.CGColor;

                    CABasicAnimation pathAnimation = new CABasicAnimation {
                        KeyPath = "strokeEnd"
                    };
                    pathAnimation.Duration = 1.0;
                    pathAnimation.From     = NSNumber.FromNFloat(0);
                    pathAnimation.To       = NSNumber.FromNFloat(1);
                    layer.AddAnimation(pathAnimation, "strokeEndAnimation");
                }
            }
        }
Пример #26
0
        public static CGPath ToCGPath(
            this PathF target)
        {
            var path = new CGPath();

            int pointIndex        = 0;
            int arcAngleIndex     = 0;
            int arcClockwiseIndex = 0;

            foreach (var operation in target.PathOperations)
            {
                if (operation == PathOperation.MoveTo)
                {
                    var point = target[pointIndex++];
                    path.MoveToPoint(point.X, point.Y);
                }
                else if (operation == PathOperation.Line)
                {
                    var endPoint = target[pointIndex++];
                    path.AddLineToPoint(endPoint.X, endPoint.Y);
                }

                else if (operation == PathOperation.Quad)
                {
                    var controlPoint = target[pointIndex++];
                    var endPoint     = target[pointIndex++];
                    path.AddQuadCurveToPoint(
                        controlPoint.X,
                        controlPoint.Y,
                        endPoint.X,
                        endPoint.Y);
                }
                else if (operation == PathOperation.Cubic)
                {
                    var controlPoint1 = target[pointIndex++];
                    var controlPoint2 = target[pointIndex++];
                    var endPoint      = target[pointIndex++];
                    path.AddCurveToPoint(
                        controlPoint1.X,
                        controlPoint1.Y,
                        controlPoint2.X,
                        controlPoint2.Y,
                        endPoint.X,
                        endPoint.Y);
                }
                else if (operation == PathOperation.Arc)
                {
                    var   topLeft     = target[pointIndex++];
                    var   bottomRight = target[pointIndex++];
                    float startAngle  = target.GetArcAngle(arcAngleIndex++);
                    float endAngle    = target.GetArcAngle(arcAngleIndex++);
                    var   clockwise   = target.IsArcClockwise(arcClockwiseIndex++);

                    var startAngleInRadians = GraphicsOperations.DegreesToRadians(-startAngle);
                    var endAngleInRadians   = GraphicsOperations.DegreesToRadians(-endAngle);

                    while (startAngleInRadians < 0)
                    {
                        startAngleInRadians += (float)Math.PI * 2;
                    }

                    while (endAngleInRadians < 0)
                    {
                        endAngleInRadians += (float)Math.PI * 2;
                    }

                    var cx     = (bottomRight.X + topLeft.X) / 2;
                    var cy     = (bottomRight.Y + topLeft.Y) / 2;
                    var width  = bottomRight.X - topLeft.X;
                    var height = bottomRight.Y - topLeft.Y;
                    var r      = width / 2;

                    var transform = CGAffineTransform.MakeTranslation(cx, cy);
                    transform = CGAffineTransform.Multiply(CGAffineTransform.MakeScale(1, height / width), transform);

                    path.AddArc(transform, 0, 0, r, startAngleInRadians, endAngleInRadians, !clockwise);
                }
                else if (operation == PathOperation.Close)
                {
                    path.CloseSubpath();
                }
            }

            return(path);
        }
Пример #27
0
        public void DrawDropletPulledVer(CGContext canvas, string label, bool biggie, SKPoint c1, SKPoint c2, KDeviceHandler.Direction dir, float r, float r1, float neckX, float r2, float textStrokeWidth, SKPaint fillPaint, float strokeWidth, float accentStrokeWidth, Swipe swipe)
        {
            float ratio = ((r1 + r2) / 2) / r;

            //strokeWidth = strokeWidth * ratio;
            textStrokeWidth   = textStrokeWidth * ratio;
            accentStrokeWidth = accentStrokeWidth * ratio;

            float lr = r1 - (strokeWidth + accentStrokeWidth) / 2.0f;
            float dr = r2 - (strokeWidth + accentStrokeWidth) / 2.0f;

            // place the neck in an Y-position proportional to the rate between r1 and r2, with m1+r1Y to the top leading to c1.Y, and m2+r2Y to the bot leading to c2.Y
            float m1 = (2 * r - (r1 + r2)) / (1 + r2 / r1);
            float m2 = m1 * r2 / r1;
            // position of the neck
            float nY = c1.Y + r1 + m1;
            float nX = c1.X;
            // Control points: a1*2 is on a line from nY,nX-neckX to c1.Y,c.X-r1 where it intersects c1.Y+r1; we divide it by 2 to make the curve smoother
            float a1 = (m1 * (r1 - neckX) / (r1 + m1)) / 2;
            float a2 = (m2 * (r2 - neckX) / (r2 + m2)) / 2;

            var path = new CGPath();

            path.MoveToPoint(CG.Point(swipe % new SKPoint(c1.X - r1, c1.Y)));
            path.AddCurveToPoint(CG.Point(swipe % new SKPoint(c1.X - r1, c1.Y + 0.5f * r1)), CG.Point(swipe % new SKPoint(nX - (neckX + a1), c1.Y + r1)), CG.Point(swipe % new SKPoint(nX - neckX, nY)));
            path.AddCurveToPoint(CG.Point(swipe % new SKPoint(nX - (neckX + a2), c2.Y - r2)), CG.Point(swipe % new SKPoint(c2.X - r2, c2.Y - 0.5f * r2)), CG.Point(swipe % new SKPoint(c2.X - r2, c2.Y)));

            path.AddCurveToPoint(CG.Point(swipe % new SKPoint(c2.X - r2, c2.Y + 0.75f * r2)), CG.Point(swipe % new SKPoint(c2.X - 0.75f * r2, c2.Y + r2)), CG.Point(swipe % new SKPoint(c2.X, c2.Y + r2)));
            path.AddCurveToPoint(CG.Point(swipe % new SKPoint(c2.X + 0.75f * r2, c2.Y + r2)), CG.Point(swipe % new SKPoint(c2.X + r2, c2.Y + 0.75f * r2)), CG.Point(swipe % new SKPoint(c2.X + r2, c2.Y)));

            path.AddCurveToPoint(CG.Point(swipe % new SKPoint(c2.X + r2, c2.Y - 0.5f * r2)), CG.Point(swipe % new SKPoint(nX + (neckX + a2), c2.Y - r2)), CG.Point(swipe % new SKPoint(nX + neckX, nY)));
            path.AddCurveToPoint(CG.Point(swipe % new SKPoint(nX + (neckX + a1), c1.Y + r1)), CG.Point(swipe % new SKPoint(c1.X + r1, c1.Y + 0.5f * r1)), CG.Point(swipe % new SKPoint(c1.X + r1, c1.Y)));

            path.AddCurveToPoint(CG.Point(swipe % new SKPoint(c1.X + r1, c1.Y - 0.75f * r1)), CG.Point(swipe % new SKPoint(c1.X + 0.75f * r1, c1.Y - r1)), CG.Point(swipe % new SKPoint(c1.X, c1.Y - r1)));
            path.AddCurveToPoint(CG.Point(swipe % new SKPoint(c1.X - 0.75f * r1, c1.Y - r1)), CG.Point(swipe % new SKPoint(c1.X - r1, c1.Y - 0.75f * r1)), CG.Point(swipe % new SKPoint(c1.X - r1, c1.Y)));
            path.CloseSubpath();

            var darkPath = new CGPath();

            darkPath.MoveToPoint(CG.Point(swipe % new SKPoint(c2.X, c2.Y + dr)));
            darkPath.AddCurveToPoint(CG.Point(swipe % new SKPoint(c2.X + 0.75f * dr, c2.Y + dr)), CG.Point(swipe % new SKPoint(c2.X + dr, c2.Y + 0.75f * dr)), CG.Point(swipe % new SKPoint(c2.X + dr, c2.Y)));

            var lightPath = new CGPath();

            lightPath.MoveToPoint(CG.Point(swipe % new SKPoint(c1.X, c1.Y - lr)));
            lightPath.AddCurveToPoint(CG.Point(swipe % new SKPoint(c1.X - 0.75f * lr, c1.Y - lr)), CG.Point(swipe % new SKPoint(c1.X - lr, c1.Y - 0.75f * lr)), CG.Point(swipe % new SKPoint(c1.X - lr, c1.Y)));

            using (var strokePaint = new SKPaint {
                Style = SKPaintStyle.Stroke, Color = new SKColor(0, 0, 0, 191), StrokeWidth = swipe % strokeWidth, IsAntialias = true
            })
                using (var accentLightPaint = new SKPaint {
                    Style = SKPaintStyle.Stroke, Color = new SKColor(255, 255, 255, 191), StrokeWidth = swipe % accentStrokeWidth, StrokeCap = SKStrokeCap.Round, IsAntialias = true
                })
                    using (var accentDarkPaint = new SKPaint {
                        Style = SKPaintStyle.Stroke, Color = new SKColor(0, 0, 0, 95), StrokeWidth = swipe % accentStrokeWidth, StrokeCap = SKStrokeCap.Round, IsAntialias = true
                    })
                    {
                        canvas.AddPath(path);
                        canvas.SetFillColor(CG.Color(fillPaint.Color));
                        canvas.FillPath();

                        canvas.AddPath(darkPath);
                        canvas.SetStrokeColor(CG.Color(accentDarkPaint.Color));
                        canvas.SetLineWidth(accentDarkPaint.StrokeWidth);
                        canvas.SetLineJoin(CG.LineJoin(accentDarkPaint.StrokeJoin));
                        canvas.SetLineCap(CG.LineCap(accentDarkPaint.StrokeCap));
                        canvas.StrokePath();

                        canvas.AddPath(lightPath);
                        canvas.SetStrokeColor(CG.Color(accentLightPaint.Color));
                        canvas.SetLineWidth(accentLightPaint.StrokeWidth);
                        canvas.SetLineJoin(CG.LineJoin(accentLightPaint.StrokeJoin));
                        canvas.SetLineCap(CG.LineCap(accentLightPaint.StrokeCap));
                        canvas.StrokePath();

                        canvas.AddPath(path);
                        canvas.SetStrokeColor(CG.Color(strokePaint.Color));
                        canvas.SetLineWidth(strokePaint.StrokeWidth);
                        canvas.SetLineJoin(CG.LineJoin(strokePaint.StrokeJoin));
                        canvas.SetLineCap(CG.LineCap(strokePaint.StrokeCap));
                        canvas.StrokePath();
                    }

            float   rYtext = (r1 == r2) ? ((dir == KDeviceHandler.Direction.Top) ? r1 : r2) : (r1 > r2) ? r1 : r2;
            SKPoint cText  = (r1 == r2) ? ((dir == KDeviceHandler.Direction.Top) ? c1 : c2) : (r1 > r2) ? c1 : c2;

            DrawDropletLabel(canvas, label, cText, rYtext, textStrokeWidth, biggie, swipe);
        }
        public override void ObserveValue(NSString keyPath, NSObject ofObject, NSDictionary change, IntPtr context)
        {
            //base.ObserveValue(keyPath, ofObject, change, context);
            if (keyPath.ToString().ToLower() == "contentInset".ToLower())
            {
                if (!_ignoreInset)
                {
                    this.originalContentInset = (change["new"] as NSValue).UIEdgeInsetsValue;
                    this.Frame = new RectangleF(0, -1 * (kTotalViewHeight + this.scrollView.ContentInset.Top), this.scrollView.Frame.Size.Width, kTotalViewHeight);
                }
                return;
            }

            if (!this.Enabled || this._ignoreOffset)
                return;

            float offset = (change["new"] as NSValue).PointFValue.Y + this.originalContentInset.Top;

            if (_refreshing)
            {
                if (offset != 0)
                {
                    // keep thing pinned at the top
                    CATransaction.Begin();
                    CATransaction.SetValueForKey(NSNumber.FromBoolean(true), CATransaction.DisableActionsKey);
                    _shapeLayer.Position = new PointF(0, kMaxDistance + offset + kOpenedViewHeight);
                    CATransaction.Commit();

                    this.activity.Center = new PointF((float)Math.Floor(this.Frame.Size.Width / 2), (float)Math.Min(offset + this.Frame.Size.Height + Math.Floor(kOpenedViewHeight / 2), this.Frame.Size.Height - kOpenedViewHeight / 2));

                    _ignoreInset = true;
                    _ignoreOffset = true;

                    if (offset < 0)
                    {
                        // set the inset depending on the situation
                        if (offset >= kOpenedViewHeight * -1)
                        {
                            if (!this.scrollView.Dragging)
                            {
                                if (!_didSetInset)
                                {
                                    _didSetInset = true;
                                    _hasSectionHeaders = false;
                                    if (this.scrollView is UITableView)
                                    {
                                        for (int i = 0; i < (this.scrollView as UITableView).NumberOfSections(); ++i)
                                        {
                                            if ((this.scrollView as UITableView).RectForHeaderInSection(i).Size.Height != 0)
                                            {
                                                _hasSectionHeaders = true;
                                                break;
                                            }
                                        }
                                    }
                                }
                                if (_hasSectionHeaders)
                                    this.scrollView.ContentInset = new UIEdgeInsets(Math.Min(offset * -1, kOpenedViewHeight) + this.originalContentInset.Top, this.originalContentInset.Left, this.originalContentInset.Bottom, this.originalContentInset.Right);
                                else
                                    this.scrollView.ContentInset = new UIEdgeInsets(kOpenedViewHeight + this.originalContentInset.Top, this.originalContentInset.Left, this.originalContentInset.Bottom, this.originalContentInset.Right);
                            }
                            else if(_didSetInset && _hasSectionHeaders)
                            {
                                this.scrollView.ContentInset = new UIEdgeInsets(-1 * offset + this.originalContentInset.Top, this.originalContentInset.Left, this.originalContentInset.Bottom, this.originalContentInset.Right);
                            }
                        }
                    }
                    else if (_hasSectionHeaders)
                    {
                        this.scrollView.ContentInset = this.originalContentInset;
                    }
                    _ignoreInset = false;
                    _ignoreOffset = false;
                }
                return;
            }
            else
            {
                // check if we can trigger a new refresh and if we can draw the control
                bool dontDraw = false;  // line 230
                if (!_canRefresh)
                {
                    if (offset >= 0)
                    {
                        // we can refresh again after the control is scrolled out of view
                        _canRefresh = true;
                        _didSetInset = false;
                    }
                    else
                    {
                        dontDraw = true;
                    }
                }
                else
                {
                    if (offset >= 0)
                    {
                        // don't draw if the control is not visible
                        dontDraw = true;
                    }
                }
                if (offset > 0 && _lastOffset > offset  && !this.scrollView.Tracking)
                {
                    // if we are scrolling too fast, don't draw, and don't trigger unless the scrollView bounced back

                    // removed behavior Heath
                    //_canRefresh = false;
                    //dontDraw = true;
                }
                if (dontDraw)
                {
                    _shapeLayer.Path = null;
                    _shapeLayer.ShadowPath = new CGPath(IntPtr.Zero);
                    _arrowLayer.Path = null;
                    _highlightLayer.Path = null;
                    _lastOffset = offset;
                    return;
                }
            }

            _lastOffset = offset;  // line 260

            bool triggered = false;

            CGPath path = new CGPath();

            // calculate some useful points and values
            float verticalShift = (float)Math.Max(0, -1 * ((kMaxTopRadius + kMaxBottomRadius + kMaxTopPadding + kMaxBottomPadding) + offset));
            float distance = (float)Math.Min(kMaxDistance, (float)Math.Abs(verticalShift));
            float percentage = 1 - (distance / kMaxDistance);

            float currentTopPadding = lerp(kMinTopPadding, kMaxTopPadding, percentage);
            float currentTopRadius = lerp(kMinTopRadius, kMaxTopRadius, percentage);
            float currentBottomRadius = lerp(kMinBottomRadius, kMaxBottomRadius, percentage);
            float currentBottomPadding = lerp(kMinBottomPadding, kMaxBottomPadding, percentage);

            PointF bottomOrigin = new PointF((float)Math.Floor(this.Bounds.Size.Width / 2), this.Bounds.Size.Height - currentBottomPadding - currentBottomRadius);
            PointF topOrigin = PointF.Empty;
            if (distance == 0)
            {
                topOrigin = new PointF((float)Math.Floor(this.Bounds.Size.Width / 2), bottomOrigin.Y);
            }
            else
            {
                topOrigin = new PointF((float)Math.Floor(this.Bounds.Size.Width / 2), this.Bounds.Size.Height + offset + currentTopPadding + currentTopRadius);
                if (percentage == 0)
                {
                    bottomOrigin.Y -= (float)Math.Abs(verticalShift) - kMaxDistance;
                    triggered = true;
                }
            }

            // top semicircle
            path.AddArc(topOrigin.X, topOrigin.Y, currentTopRadius, 0, (float)Math.PI, true);

            // left curve
            PointF leftCp1 = new PointF(lerp((topOrigin.X - currentTopRadius), (bottomOrigin.X - currentBottomRadius), 0.1f), lerp(topOrigin.Y, bottomOrigin.Y, 0.2f));
            PointF leftCp2 = new PointF(lerp((topOrigin.X - currentTopRadius), (bottomOrigin.X - currentBottomRadius), 0.9f), lerp(topOrigin.Y, bottomOrigin.Y, 0.2f));
            PointF leftDestination = new PointF(bottomOrigin.X - currentBottomRadius, bottomOrigin.Y);

            path.AddCurveToPoint(leftCp1, leftCp2, leftDestination);

            // bottom semicircle
            path.AddArc(bottomOrigin.X, bottomOrigin.Y, currentBottomRadius, (float)Math.PI, 0, true);

            // right curve
            PointF rightCp2 = new PointF(lerp((topOrigin.X + currentTopRadius), (bottomOrigin.X + currentBottomRadius), 0.1f), lerp(topOrigin.Y, bottomOrigin.Y, 0.2f));
            PointF rightCp1 = new PointF(lerp((topOrigin.X + currentTopRadius), (bottomOrigin.X + currentBottomRadius), 0.9f), lerp(topOrigin.Y, bottomOrigin.Y, 0.2f));
            PointF rightDestination = new PointF(bottomOrigin.X + currentTopRadius, topOrigin.Y);

            path.AddCurveToPoint (rightCp1, rightCp2, rightDestination);
            path.CloseSubpath();

            if (!triggered) // line 309
            {
                // set paths
                _shapeLayer.Path = path;
                _shapeLayer.ShadowPath = path;

                // add the arrow shape
                float currentArrowSize = lerp(kMinArrowSize, kMaxArrowSize, percentage);
                float currentArrowRadius = lerp(kMinArrowRadius, kMaxArrowRadius, percentage);
                float arrowBigRadius = currentArrowRadius + (currentArrowSize / 2);
                float arrowSmallRadius = currentArrowRadius - (currentArrowSize / 2);
                CGPath arrowPath = new CGPath();
                /*
                arrowPath.AddArc(topOrigin.X, topOrigin.Y, arrowBigRadius, 0, 3 * (float)Math.PI, false);
                arrowPath.AddLineToPoint(topOrigin.X, topOrigin.Y - arrowBigRadius - currentArrowSize);
                arrowPath.AddLineToPoint(topOrigin.X + (2 * currentArrowSize), topOrigin.Y - arrowBigRadius + (currentArrowSize / 2));
                arrowPath.AddLineToPoint(topOrigin.X, topOrigin.Y - arrowBigRadius + (2 * currentArrowSize));
                arrowPath.AddLineToPoint(topOrigin.X, topOrigin.Y - arrowBigRadius + currentArrowSize);
                arrowPath.AddArc(topOrigin.X, topOrigin.Y, arrowSmallRadius, 3 * (float)Math.PI, 0, true);
                */
                arrowPath.AddArc (topOrigin.X, topOrigin.Y, arrowBigRadius, 0, 3 * (float) Math.PI / 2.0f, false);
                arrowPath.AddLineToPoint (topOrigin.X, topOrigin.Y - arrowBigRadius - currentArrowSize);
                arrowPath.AddLineToPoint (topOrigin.X + (2 * currentArrowSize), topOrigin.Y - arrowBigRadius + (currentArrowSize / 2.0f));
                arrowPath.AddLineToPoint (topOrigin.X, topOrigin.Y - arrowBigRadius + (2 * currentArrowSize));
                arrowPath.AddLineToPoint (topOrigin.X, topOrigin.Y - arrowBigRadius + currentArrowSize);
                arrowPath.AddArc (topOrigin.X, topOrigin.Y, arrowSmallRadius, 3 * (float) Math.PI / 2.0f, 0, true);

                arrowPath.CloseSubpath();
                _arrowLayer.Path = arrowPath;
                _arrowLayer.FillRule = CAShapeLayer.FillRuleEvenOdd;
                arrowPath.Dispose();

                // add the highlight shape
                CGPath highlightPath = new CGPath();
                highlightPath.AddArc(topOrigin.X, topOrigin.Y, currentTopRadius, 0, (float)Math.PI, true);
                highlightPath.AddArc(topOrigin.X, topOrigin.Y + 1.25f, currentTopRadius, (float)Math.PI, 0, false);

                _highlightLayer.Path = highlightPath;
                _highlightLayer.FillRule = CAShapeLayer.FillRuleNonZero;
                highlightPath.Dispose();
            }
            else
            {
                // start the shape disappearance animation
                float radius = lerp(kMinBottomRadius, kMaxBottomRadius, 0.2f);
                CABasicAnimation pathMorph = CABasicAnimation.FromKeyPath("path");
                pathMorph.Duration = 0.15f;
                pathMorph.FillMode = CAFillMode.Forwards;
                pathMorph.RemovedOnCompletion = false;

                CGPath toPath = new CGPath();
                toPath.AddArc(topOrigin.X, topOrigin.Y, radius, 0, (float)Math.PI, true);
                toPath.AddCurveToPoint(topOrigin.X - radius, topOrigin.Y, topOrigin.X - radius, topOrigin.Y, topOrigin.X - radius, topOrigin.Y);
                toPath.AddArc(topOrigin.X, topOrigin.Y, radius, (float)Math.PI, 0, true);
                toPath.AddCurveToPoint(topOrigin.X + radius, topOrigin.Y, topOrigin.X + radius, topOrigin.Y, topOrigin.X + radius, topOrigin.Y);
                toPath.CloseSubpath();

                pathMorph.To = new NSValue(toPath.Handle);
                _shapeLayer.AddAnimation(pathMorph, null);

                CABasicAnimation shadowPathMorph = CABasicAnimation.FromKeyPath("shadowPath");
                shadowPathMorph.Duration = 0.15f;
                shadowPathMorph.FillMode = CAFillMode.Forwards;
                shadowPathMorph.RemovedOnCompletion = false;
                shadowPathMorph.To = new NSValue(toPath.Handle);

                _shapeLayer.AddAnimation(shadowPathMorph, null);
                toPath.Dispose();

                CABasicAnimation shapeAlphaAnimation = CABasicAnimation.FromKeyPath("opacity");
                shapeAlphaAnimation.Duration = 0.1f;
                shapeAlphaAnimation.BeginTime = CAAnimation.CurrentMediaTime() + 0.1f;
                shapeAlphaAnimation.To = new NSNumber(0);
                shapeAlphaAnimation.FillMode = CAFillMode.Forwards;
                shapeAlphaAnimation.RemovedOnCompletion = false;
                _shapeLayer.AddAnimation(shapeAlphaAnimation, null);

                CABasicAnimation alphaAnimation = CABasicAnimation.FromKeyPath("opacity");
                alphaAnimation.Duration = 0.1f;
                alphaAnimation.To = new NSNumber (0);
                alphaAnimation.FillMode = CAFillMode.Forwards;
                alphaAnimation.RemovedOnCompletion = false;

                _arrowLayer.AddAnimation(alphaAnimation, null);
                _highlightLayer.AddAnimation(alphaAnimation, null);

                CATransaction.Begin();
                CATransaction.DisableActions = true;
                activity.Layer.Transform = CATransform3D.MakeScale(0.1f, 0.1f, 1f);
                CATransaction.Commit();

                UIView.Animate (0.2f, 0.15f, UIViewAnimationOptions.CurveLinear, () => {
                    activity.Alpha = 1;
                    activity.Layer.Transform = CATransform3D.MakeScale(1, 1, 1);
                }, null);

                _refreshing = true;
                _canRefresh = false;
                this.SendActionForControlEvents(UIControlEvent.ValueChanged);

                if (this.Action != null)
                    this.Action();
            }
            path.Dispose();
        }
    public override void ObserveValue (NSString keyPath, NSObject ofObject, NSDictionary change, IntPtr context)
    {
        if (keyPath == "contentInset") {
            if (!_ignoreInset && !_ignoreInsetBlock) {
                OriginalContentInset = ((NSValue) change ["new"]).UIEdgeInsetsValue;

                Frame = (_vertical)
                    ? new RectangleF (0, - (TotalViewHeight + ScrollView.ContentInset.Top), ScrollView.Bounds.Size.Width, TotalViewHeight)
                    : new RectangleF (- (TotalViewHeight + ScrollView.ContentInset.Left), 0, TotalViewHeight, ScrollView.Bounds.Size.Height);
            }
            
            return;
        }
        
        if (!Enabled || _ignoreOffset)
            return;
        
        var newContentOffset = ((NSValue) change ["new"]).PointFValue;
        float offset;
        
        if (_vertical) {
            offset = newContentOffset.Y + OriginalContentInset.Top;
        } else {
            offset = newContentOffset.X + OriginalContentInset.Left;
        }
        
        if (_refreshing) {
            if (offset != 0) {
                // Keep thing pinned at the top
                
                CATransaction.Begin ();
                CATransaction.DisableActions = true;
                
                _shapeLayer.Position = (_vertical)
                    ? new PointF (0, MaxDistance + offset + OpenedViewHeight)
                        : new PointF (MaxDistance + offset + OpenedViewHeight, 0);
                
                CATransaction.Commit ();
                
                if (_vertical) {
                    _activity.Center = new PointF (
                        (float) Math.Floor (Bounds.Width / 2.0f),
                        Math.Min (
                        offset + Bounds.Height + (float) Math.Floor (OpenedViewHeight / 2.0f),
                        Bounds.Height - OpenedViewHeight / 2.0f
                        )
                        );
                } else {
                    _activity.Center = new PointF (
                        Math.Min (
                        offset + Bounds.Width + (float) Math.Floor (OpenedViewHeight / 2.0f),
                        Bounds.Width - OpenedViewHeight / 2.0f
                        ),
                        (float) Math.Floor (Bounds.Height / 2.0f)
                        );
                }
                
                _ignoreInset = true;
                _ignoreOffset = true;
                
                if (offset < 0) {
                    // Set the inset depending on the situation
                    if (offset >= -OpenedViewHeight) {
                        if (!ScrollView.Dragging) {
                            if (!_didSetInset) {
                                _didSetInset = true;
                                _hasSectionHeaders = false;
                                
                                if (ScrollView is UITableView) {
                                    var tableView = (UITableView) ScrollView;
                                    for (var i = 0; i < tableView.NumberOfSections (); i++) {
                                        if (tableView.RectForHeaderInSection (i).Size.Height > 0) {
                                            _hasSectionHeaders = true;
                                            break;
                                        }
                                    }
                                }
                            }
                            
                            if (_hasSectionHeaders) {
                                ScrollView.ContentInset = (_vertical)
                                    ? new UIEdgeInsets (Math.Min (-offset, OpenedViewHeight) + OriginalContentInset.Top, OriginalContentInset.Left, OriginalContentInset.Bottom, OriginalContentInset.Right)
                                    : new UIEdgeInsets (OriginalContentInset.Top, Math.Min (-offset, OpenedViewHeight) + OriginalContentInset.Left, OriginalContentInset.Bottom, OriginalContentInset.Right);
                            } else {
                                ScrollView.ContentInset = (_vertical)
                                    ? new UIEdgeInsets (OpenedViewHeight + OriginalContentInset.Top, OriginalContentInset.Left, OriginalContentInset.Bottom, OriginalContentInset.Right)
                                    : new UIEdgeInsets (OriginalContentInset.Top, OriginalContentInset.Left + OpenedViewHeight, OriginalContentInset.Bottom, OriginalContentInset.Right);
                            }
                        } else if (_didSetInset && _hasSectionHeaders) {
                            ScrollView.ContentInset = (_vertical)
                                ? new UIEdgeInsets (-offset + OriginalContentInset.Top, OriginalContentInset.Left, OriginalContentInset.Bottom, OriginalContentInset.Right)
                                : new UIEdgeInsets (OriginalContentInset.Top, -offset + OriginalContentInset.Left, OriginalContentInset.Bottom, OriginalContentInset.Right);
                        }
                        
                    }
                } else if (_hasSectionHeaders) {
                    ScrollView.ContentInset = OriginalContentInset;
                }
                
                _ignoreInset = false;
                _ignoreOffset = false;
            }
            
            return;
        } else {
            // Check if we can trigger a new refresh and if we can draw the control
            bool dontDraw = false;
            
            if (!_canRefresh) {
                if (offset >= 0) {
                    // We can refresh again after the control is scrolled out of view
                    _canRefresh = true;
                    _didSetInset = false;
                } else {
                    dontDraw = true;
                }
            } else {
                if (offset >= 0) {
                    // Don't draw if the control is not visible
                    dontDraw = true;
                }
            }
            
            if (offset > 0 && _lastOffset > offset && !ScrollView.Tracking) {
                // If we are scrolling too fast, don't draw, and don't trigger unless the scrollView bounced back
                _canRefresh = false;
                dontDraw = true;
            }
            
            if (dontDraw) {
                _shapeLayer.Path = null;
                _shapeLayer.ShadowPath = new CGPath (IntPtr.Zero);
                _arrowLayer.Path = null;
                _highlightLayer.Path = null;
                _lastOffset = offset;
                return;
            }
        }
        
        _lastOffset = offset;
        bool triggered = false;
        
        CGPath path = new CGPath ();
        
        //Calculate some useful points and values
        var verticalShift = Math.Max (0, -((MaxTopRadius + MaxBottomRadius + MaxTopPadding + MaxBottomPadding) + offset));
        var distance = Math.Min (MaxDistance, Math.Abs (verticalShift));
        var percentage = 1 - (distance / MaxDistance);
        
        PointF headOrigin;
        float headRadius;
        
        if (_vertical) {
            float currentTopPadding = lerp (MinTopPadding, MaxTopPadding, percentage);
            float currentTopRadius = lerp (MinTopRadius, MaxTopRadius, percentage);
            float currentBottomRadius = lerp (MinBottomRadius, MaxBottomRadius, percentage);
            float currentBottomPadding = lerp (MinBottomPadding, MaxBottomPadding, percentage);
            
            var bottomOrigin = new PointF ((float) Math.Floor (Bounds.Width / 2.0f), Bounds.Height - currentBottomPadding - currentBottomRadius);
            var topOrigin = PointF.Empty;
            
            if (distance == 0) {
                topOrigin = new PointF ((float) Math.Floor (Bounds.Width / 2.0f), bottomOrigin.Y);
            } else {
                topOrigin = new PointF ((float) Math.Floor (Bounds.Width / 2.0f), Bounds.Height + offset + currentTopPadding + currentTopRadius);
                
                if (percentage == 0) {
                    bottomOrigin.Y -= ((Math.Abs (verticalShift) - MaxDistance));
                    triggered = true;
                }
            }
            
            //Top semicircle
            path.AddArc (topOrigin.X, topOrigin.Y, currentTopRadius, 0, (float) Math.PI, true);
            
            //Left curve
            var leftCp1 = new PointF (lerp ((topOrigin.X - currentTopRadius), (bottomOrigin.X - currentBottomRadius), 0.1f), lerp (topOrigin.Y, bottomOrigin.Y, .2f));
            var leftCp2 = new PointF (lerp ((topOrigin.X - currentTopRadius), (bottomOrigin.X - currentBottomRadius), 0.9f), lerp (topOrigin.Y, bottomOrigin.Y, .2f));
            var leftDestination = new PointF (bottomOrigin.X - currentBottomRadius, bottomOrigin.Y);
            
            path.AddCurveToPoint (leftCp1, leftCp2, leftDestination);
            
            //Bottom semicircle
            path.AddArc (bottomOrigin.X, bottomOrigin.Y, currentBottomRadius, (float) Math.PI, 0, true);
            
            //Right curve
            var rightCp2 = new PointF (lerp ((topOrigin.X + currentTopRadius), (bottomOrigin.X + currentBottomRadius), 0.1f), lerp (topOrigin.Y, bottomOrigin.Y, .2f));
            var rightCp1 = new PointF (lerp ((topOrigin.X + currentTopRadius), (bottomOrigin.X + currentBottomRadius), 0.9f), lerp (topOrigin.Y, bottomOrigin.Y, .2f));
            var rightDestination = new PointF (bottomOrigin.X + currentTopRadius, topOrigin.Y);
            
            path.AddCurveToPoint (rightCp1, rightCp2, rightDestination);
            
            headOrigin = topOrigin;
            headRadius = currentTopRadius;
        } else {
            float currentLeftPadding = lerp (MinTopPadding, MaxTopPadding, percentage);
            float currentLeftRadius = lerp (MinTopRadius, MaxTopRadius, percentage);
            float currentRightRadius = lerp (MinBottomRadius, MaxBottomRadius, percentage);
            float currentRightPadding = lerp (MinBottomPadding, MaxBottomPadding, percentage);
            
            var rightOrigin = new PointF (Bounds.Width - currentRightPadding - currentRightRadius, (float) Math.Floor (Bounds.Height / 2.0f));
            var leftOrigin = PointF.Empty;
            
            if (distance == 0) {
                leftOrigin = new PointF (rightOrigin.X, (float) Math.Floor (Bounds.Size.Height / 2.0f));
            } else {
                leftOrigin = new PointF (Bounds.Size.Width + offset + currentLeftPadding + currentLeftRadius, (float) Math.Floor (Bounds.Height / 2.0f));
                
                if (percentage == 0) {
                    rightOrigin.X -= ((Math.Abs (verticalShift) - MaxDistance));
                    triggered = true;
                }
            }
            
            //Left cemicircle
            path.AddArc (leftOrigin.X, leftOrigin.Y, currentLeftRadius, (float) -Math.PI / 2.0f, (float) Math.PI / 2.0f, true);
            
            // Bottom curve
            var bottomCp1 = new PointF (lerp (leftOrigin.X, rightOrigin.X, .2f), lerp ((leftOrigin.Y + currentLeftRadius), (rightOrigin.Y + currentRightRadius), .1f));
            var bottomCp2 = new PointF (lerp (leftOrigin.X, rightOrigin.X, .2f), lerp ((leftOrigin.Y + currentLeftRadius), (rightOrigin.Y + currentRightRadius), .9f));
            var bottomDestination = new PointF (rightOrigin.X, rightOrigin.Y + currentRightRadius);
            
            path.AddCurveToPoint (bottomCp1, bottomCp2, bottomDestination);
            
            //Right semicircle
            path.AddArc (rightOrigin.X, rightOrigin.Y, currentRightRadius, (float) Math.PI / 2.0f, 3 * (float) Math.PI / 2.0f, true);
            
            //Top curve
            var topCp2 = new PointF (lerp (leftOrigin.X, rightOrigin.X, .2f), lerp ((leftOrigin.Y - currentLeftRadius), (rightOrigin.Y - currentRightRadius), .1f));
            var topCp1 = new PointF (lerp (leftOrigin.X, rightOrigin.X, .2f), lerp ((leftOrigin.Y - currentLeftRadius), (rightOrigin.Y - currentRightRadius), .9f));
            var topDestination = new PointF (leftOrigin.X, leftOrigin.Y - currentLeftRadius);
            
            path.AddCurveToPoint (topCp1, topCp2, topDestination);
            
            headOrigin = leftOrigin;
            headRadius = currentLeftRadius;
        }
        
        path.CloseSubpath ();
        
        if (!triggered) {
            // Set paths
            
            _shapeLayer.Path = path;
            _shapeLayer.ShadowPath = path;
            
            // Add the arrow shape
            
            var currentArrowSize = lerp (MinArrowSize, MaxArrowSize, percentage);
            var currentArrowRadius = lerp (MinArrowRadius, MaxArrowRadius, percentage);
            
            var arrowBigRadius = currentArrowRadius + (currentArrowSize / 2.0f);
            var arrowSmallRadius = currentArrowRadius - (currentArrowSize / 2.0f);
            
            var arrowPath = new CGPath ();
            arrowPath.AddArc (headOrigin.X, headOrigin.Y, arrowBigRadius, 0, 3 * (float) Math.PI / 2.0f, false);
            arrowPath.AddLineToPoint (headOrigin.X, headOrigin.Y - arrowBigRadius - currentArrowSize);
            arrowPath.AddLineToPoint (headOrigin.X + (2 * currentArrowSize), headOrigin.Y - arrowBigRadius + (currentArrowSize / 2.0f));
            arrowPath.AddLineToPoint (headOrigin.X, headOrigin.Y - arrowBigRadius + (2 * currentArrowSize));
            arrowPath.AddLineToPoint (headOrigin.X, headOrigin.Y - arrowBigRadius + currentArrowSize);
            arrowPath.AddArc (headOrigin.X, headOrigin.Y, arrowSmallRadius, 3 * (float) Math.PI / 2.0f, 0, true);
            arrowPath.CloseSubpath ();
            
            _arrowLayer.Path = arrowPath;
            _arrowLayer.FillRule =  CAShapeLayer.FillRuleEvenOdd;
            arrowPath.Dispose ();
            
            // Add the highlight shape
            
            var highlightPath = new CGPath ();
            if (_vertical) {
                highlightPath.AddArc (headOrigin.X, headOrigin.Y, headRadius, 0, (float) Math.PI, true);
                highlightPath.AddArc (headOrigin.X, headOrigin.Y + 1.25f, headRadius, (float) Math.PI, 0, false);
            } else {
                highlightPath.AddArc (headOrigin.X, headOrigin.Y, headRadius, - (float) Math.PI / 2.0f, (float) Math.PI / 2.0f, true);
                highlightPath.AddArc (headOrigin.X + 1.25f, headOrigin.Y, headRadius, (float) Math.PI / 2.0f, - (float) Math.PI / 2.0f, false);
            }
            
            _highlightLayer.Path = highlightPath;
            _highlightLayer.FillRule = CAShapeLayer.FillRuleNonZero;
            highlightPath.Dispose ();
        } else {
            // Start the shape disappearance animation
            var radius = lerp (MinBottomRadius, MaxBottomRadius, .2f);
            var pathMorph = CABasicAnimation.FromKeyPath ("path");
            
            pathMorph.Duration = .15f;
            pathMorph.FillMode = CAFillMode.Forwards;
            pathMorph.RemovedOnCompletion = false;
            
            var toPath = new CGPath ();
            
            if (_vertical) {
                toPath.AddArc (headOrigin.X, headOrigin.Y, radius, 0, (float)Math.PI, true);
                toPath.AddCurveToPoint (headOrigin.X - radius, headOrigin.Y, headOrigin.X - radius, headOrigin.Y, headOrigin.X - radius, headOrigin.Y);
                toPath.AddArc (headOrigin.X, headOrigin.Y, radius, (float) Math.PI, 0, true);
                toPath.AddCurveToPoint (headOrigin.X + radius, headOrigin.Y, headOrigin.X + radius, headOrigin.Y, headOrigin.X + radius, headOrigin.Y);
            } else {
                toPath.AddArc (headOrigin.X, headOrigin.Y, radius, - (float) Math.PI / 2.0f, (float) Math.PI / 2.0f, true);
                toPath.AddCurveToPoint (headOrigin.X, headOrigin.Y + radius, headOrigin.X, headOrigin.Y + radius, headOrigin.X, headOrigin.Y + radius);
                toPath.AddArc (headOrigin.X, headOrigin.Y, radius, (float) Math.PI / 2.0f, - (float) Math.PI / 2.0f, true);
                toPath.AddCurveToPoint (headOrigin.X, headOrigin.Y - radius, headOrigin.X, headOrigin.Y - radius, headOrigin.X, headOrigin.Y - radius);
            }
            
            toPath.CloseSubpath ();
            
            pathMorph.To = new NSValue (toPath.Handle);
            _shapeLayer.AddAnimation (pathMorph, null);
            
            var shadowPathMorph = CABasicAnimation.FromKeyPath ("shadowPath");
            shadowPathMorph.Duration = .15f;
            shadowPathMorph.FillMode = CAFillMode.Forwards;
            shadowPathMorph.RemovedOnCompletion = false;
            shadowPathMorph.To = new NSValue (toPath.Handle);
            
            _shapeLayer.AddAnimation (shadowPathMorph, null);
            toPath.Dispose ();
            
            var shapeAlphaAnimation = CABasicAnimation.FromKeyPath ("opacity");
            shapeAlphaAnimation.Duration = .1f;
            shapeAlphaAnimation.BeginTime = CABasicAnimation.CurrentMediaTime () + .1;
            shapeAlphaAnimation.To = new NSNumber (0);
            shapeAlphaAnimation.FillMode = CAFillMode.Forwards;
            shapeAlphaAnimation.RemovedOnCompletion = false;
            _shapeLayer.AddAnimation (shapeAlphaAnimation, null);
            
            var alphaAnimation = CABasicAnimation.FromKeyPath ("opacity");
            alphaAnimation.Duration = .1f;
            alphaAnimation.To = new NSNumber (0);
            alphaAnimation.FillMode = CAFillMode.Forwards;
            alphaAnimation.RemovedOnCompletion = false;
            
            _arrowLayer.AddAnimation (alphaAnimation, null);
            _highlightLayer.AddAnimation (alphaAnimation, null);
            
            CATransaction.Begin ();
            CATransaction.DisableActions = true;
            _activity.Layer.Transform = CATransform3D.MakeScale (.1f, .1f, 1);
            CATransaction.Commit ();
            
            UIView.Animate (.2f, .15f, UIViewAnimationOptions.CurveLinear, () => {
                _activity.Alpha = 1;
                _activity.Layer.Transform = CATransform3D.MakeScale (1, 1, 1);
            }, null);
            
            _refreshing = true;
            _canRefresh = false;
            
            SendActionForControlEvents (UIControlEvent.ValueChanged);
        }
        
        path.Dispose ();
    }
Пример #30
0
        public static CGPath AsCGPathFromSegment(
            this PathF target,
            int segmentIndex,
            float ppu,
            float zoom)
        {
            ppu = ppu * zoom;
            var path = new CGPath();

            var type = target.GetSegmentType(segmentIndex);

            if (type == PathOperation.Line)
            {
                var pointIndex = target.GetSegmentPointIndex(segmentIndex);
                var startPoint = target[pointIndex - 1];
                path.MoveToPoint(startPoint.X * ppu, startPoint.Y * ppu);
                var endPoint = target[pointIndex];
                path.AddLineToPoint(endPoint.X * ppu, endPoint.Y * ppu);
            }
            else if (type == PathOperation.Quad)
            {
                var pointIndex = target.GetSegmentPointIndex(segmentIndex);
                var startPoint = target[pointIndex - 1];
                path.MoveToPoint(startPoint.X * ppu, startPoint.Y * ppu);
                var controlPoint = target[pointIndex++];
                var endPoint     = target[pointIndex];
                path.AddQuadCurveToPoint(controlPoint.X * ppu, controlPoint.Y * ppu, endPoint.X * ppu, endPoint.Y * ppu);
            }
            else if (type == PathOperation.Cubic)
            {
                var pointIndex = target.GetSegmentPointIndex(segmentIndex);
                var startPoint = target[pointIndex - 1];
                path.MoveToPoint(startPoint.X * ppu, startPoint.Y * ppu);
                var controlPoint1 = target[pointIndex++];
                var controlPoint2 = target[pointIndex++];
                var endPoint      = target[pointIndex];
                path.AddCurveToPoint(controlPoint1.X * ppu, controlPoint1.Y * ppu, controlPoint2.X * ppu, controlPoint2.Y * ppu, endPoint.X * ppu, endPoint.Y * ppu);
            }
            else if (type == PathOperation.Arc)
            {
                target.GetSegmentInfo(segmentIndex, out var pointIndex, out var arcAngleIndex, out var arcClockwiseIndex);

                var topLeft     = target[pointIndex++];
                var bottomRight = target[pointIndex++];
                var startAngle  = target.GetArcAngle(arcAngleIndex++);
                var endAngle    = target.GetArcAngle(arcAngleIndex++);
                var clockwise   = target.GetArcClockwise(arcClockwiseIndex++);

                var startAngleInRadians = Geometry.DegreesToRadians(-startAngle);
                var endAngleInRadians   = Geometry.DegreesToRadians(-endAngle);

                while (startAngleInRadians < 0)
                {
                    startAngleInRadians += (float)Math.PI * 2;
                }

                while (endAngleInRadians < 0)
                {
                    endAngleInRadians += (float)Math.PI * 2;
                }

                var cx     = (bottomRight.X + topLeft.X) / 2;
                var cy     = (bottomRight.Y + topLeft.Y) / 2;
                var width  = bottomRight.X - topLeft.X;
                var height = bottomRight.Y - topLeft.Y;
                var r      = width / 2;

                var transform = CGAffineTransform.MakeTranslation(cx * ppu, cy * ppu);
                transform = CGAffineTransform.Multiply(CGAffineTransform.MakeScale(1, height / width), transform);

                path.AddArc(transform, 0, 0, r * ppu, startAngleInRadians, endAngleInRadians, !clockwise);
            }

            return(path);
        }
Пример #31
0
        public static CGPath AsRotatedCGPath(this PathF target, PointF center, float ppu, float zoom, float angle)
        {
            ppu = ppu * zoom;
            var path = new CGPath();

            int pointIndex        = 0;
            int arcAngleIndex     = 0;
            int arcClockwiseIndex = 0;

            foreach (var type in target.SegmentTypes)
            {
                if (type == PathOperation.Move)
                {
                    var point = target.GetRotatedPoint(pointIndex++, center, angle);
                    path.MoveToPoint(point.X * ppu, point.Y * ppu);
                }
                else if (type == PathOperation.Line)
                {
                    var endPoint = target.GetRotatedPoint(pointIndex++, center, angle);
                    path.AddLineToPoint(endPoint.X * ppu, endPoint.Y * ppu);
                }
                else if (type == PathOperation.Quad)
                {
                    var controlPoint = target.GetRotatedPoint(pointIndex++, center, angle);
                    var endPoint     = target.GetRotatedPoint(pointIndex++, center, angle);
                    path.AddQuadCurveToPoint(
                        controlPoint.X * ppu,
                        controlPoint.Y * ppu,
                        endPoint.X * ppu,
                        endPoint.Y * ppu);
                }
                else if (type == PathOperation.Cubic)
                {
                    var controlPoint1 = target.GetRotatedPoint(pointIndex++, center, angle);
                    var controlPoint2 = target.GetRotatedPoint(pointIndex++, center, angle);
                    var endPoint      = target.GetRotatedPoint(pointIndex++, center, angle);
                    path.AddCurveToPoint(
                        controlPoint1.X * ppu,
                        controlPoint1.Y * ppu,
                        controlPoint2.X * ppu,
                        controlPoint2.Y * ppu,
                        endPoint.X * ppu,
                        endPoint.Y * ppu);
                }
                else if (type == PathOperation.Arc)
                {
                    var   topLeft     = target[pointIndex++];
                    var   bottomRight = target[pointIndex++];
                    float startAngle  = target.GetArcAngle(arcAngleIndex++);
                    float endAngle    = target.GetArcAngle(arcAngleIndex++);
                    var   clockwise   = target.GetArcClockwise(arcClockwiseIndex++);

                    var startAngleInRadians = Geometry.DegreesToRadians(-startAngle);
                    var endAngleInRadians   = Geometry.DegreesToRadians(-endAngle);

                    while (startAngleInRadians < 0)
                    {
                        startAngleInRadians += (float)Math.PI * 2;
                    }

                    while (endAngleInRadians < 0)
                    {
                        endAngleInRadians += (float)Math.PI * 2;
                    }

                    var cx     = (bottomRight.X + topLeft.X) / 2;
                    var cy     = (bottomRight.Y + topLeft.Y) / 2;
                    var width  = bottomRight.X - topLeft.X;
                    var height = bottomRight.Y - topLeft.Y;
                    var r      = width / 2;

                    var rotatedCenter = Geometry.RotatePoint(center, new PointF(cx, cy), angle);

                    var transform = CGAffineTransform.MakeTranslation(rotatedCenter.X * ppu, rotatedCenter.Y * ppu);
                    transform = CGAffineTransform.Multiply(CGAffineTransform.MakeScale(1, height / width), transform);

                    path.AddArc(transform, 0, 0, r * ppu, startAngleInRadians, endAngleInRadians, !clockwise);
                }
                else if (type == PathOperation.Close)
                {
                    path.CloseSubpath();
                }
            }

            return(path);
        }
Пример #32
0
        public static CGPath AsCGPath(
            this PathF target,
            float ox,
            float oy,
            float fx,
            float fy)
        {
            var path = new CGPath();

            int pointIndex        = 0;
            int arcAngleIndex     = 0;
            int arcClockwiseIndex = 0;

            foreach (var type in target.SegmentTypes)
            {
                if (type == PathOperation.Move)
                {
                    var point = target[pointIndex++];
                    path.MoveToPoint((ox + point.X * fx), (oy + point.Y * fy));
                }
                else if (type == PathOperation.Line)
                {
                    var endPoint = target[pointIndex++];
                    path.AddLineToPoint((ox + endPoint.X * fx), (oy + endPoint.Y * fy));
                }

                else if (type == PathOperation.Quad)
                {
                    var controlPoint = target[pointIndex++];
                    var endPoint     = target[pointIndex++];
                    path.AddQuadCurveToPoint(
                        (ox + controlPoint.X * fx),
                        (oy + controlPoint.Y * fy),
                        (ox + endPoint.X * fx),
                        (oy + endPoint.Y * fy));
                }
                else if (type == PathOperation.Cubic)
                {
                    var controlPoint1 = target[pointIndex++];
                    var controlPoint2 = target[pointIndex++];
                    var endPoint      = target[pointIndex++];
                    path.AddCurveToPoint(
                        (ox + controlPoint1.X * fx),
                        (oy + controlPoint1.Y * fy),
                        (ox + controlPoint2.X * fx),
                        (oy + controlPoint2.Y * fy),
                        (ox + endPoint.X * fx),
                        (oy + endPoint.Y * fy));
                }
                else if (type == PathOperation.Arc)
                {
                    var   topLeft     = target[pointIndex++];
                    var   bottomRight = target[pointIndex++];
                    float startAngle  = target.GetArcAngle(arcAngleIndex++);
                    float endAngle    = target.GetArcAngle(arcAngleIndex++);
                    var   clockwise   = target.GetArcClockwise(arcClockwiseIndex++);

                    var startAngleInRadians = Geometry.DegreesToRadians(-startAngle);
                    var endAngleInRadians   = Geometry.DegreesToRadians(-endAngle);

                    while (startAngleInRadians < 0)
                    {
                        startAngleInRadians += (float)Math.PI * 2;
                    }

                    while (endAngleInRadians < 0)
                    {
                        endAngleInRadians += (float)Math.PI * 2;
                    }

                    var cx     = (bottomRight.X + topLeft.X) / 2;
                    var cy     = (bottomRight.Y + topLeft.Y) / 2;
                    var width  = bottomRight.X - topLeft.X;
                    var height = bottomRight.Y - topLeft.Y;
                    var r      = width / 2;

                    var transform = CGAffineTransform.MakeTranslation(ox + cx, oy + cy);
                    transform = CGAffineTransform.Multiply(CGAffineTransform.MakeScale(1, height / width), transform);

                    path.AddArc(transform, 0, 0, r * fx, startAngleInRadians, endAngleInRadians, !clockwise);
                }
                else if (type == PathOperation.Close)
                {
                    path.CloseSubpath();
                }
            }

            return(path);
        }
Пример #33
0
        public void DrawDroplet(CGContext canvas, string label, bool biggie, SKPoint center, float padRadius, float radius, float textStrokeWidth, SKPaint fillPaint, float strokeWidth, float accentStrokeWidth, Swipe swipe)
        {
            float ratio = radius / padRadius;

            //strokeWidth = strokeWidth * ratio;
            textStrokeWidth   = textStrokeWidth * ratio;
            accentStrokeWidth = accentStrokeWidth * ratio;

            float pull         = 0.75f;
            float accentRadius = radius - (strokeWidth + accentStrokeWidth) / 2.0f;

            var path = new CGPath();

            path.MoveToPoint(CG.Point(swipe % new SKPoint(center.X, center.Y - radius)));
            // The parameters to CGPath.AddCurveToPoint are in the same order as in SKPath.CubicTo (despite what the Apple docs seem to say).
            path.AddCurveToPoint(CG.Point(swipe % new SKPoint(center.X + pull * radius, center.Y - radius)), CG.Point(swipe % new SKPoint(center.X + radius, center.Y - pull * radius)), CG.Point(swipe % new SKPoint(center.X + radius, center.Y)));
            path.AddCurveToPoint(CG.Point(swipe % new SKPoint(center.X + radius, center.Y + pull * radius)), CG.Point(swipe % new SKPoint(center.X + pull * radius, center.Y + radius)), CG.Point(swipe % new SKPoint(center.X, center.Y + radius)));
            path.AddCurveToPoint(CG.Point(swipe % new SKPoint(center.X - pull * radius, center.Y + radius)), CG.Point(swipe % new SKPoint(center.X - radius, center.Y + pull * radius)), CG.Point(swipe % new SKPoint(center.X - radius, center.Y)));
            path.AddCurveToPoint(CG.Point(swipe % new SKPoint(center.X - radius, center.Y - pull * radius)), CG.Point(swipe % new SKPoint(center.X - pull * radius, center.Y - radius)), CG.Point(swipe % new SKPoint(center.X, center.Y - radius)));
            path.CloseSubpath();

            var darkPath = new CGPath();

            darkPath.MoveToPoint(CG.Point(swipe % new SKPoint(center.X + accentRadius, center.Y)));
            darkPath.AddCurveToPoint(CG.Point(swipe % new SKPoint(center.X + accentRadius, center.Y + pull * accentRadius)), CG.Point(swipe % new SKPoint(center.X + pull * accentRadius, center.Y + accentRadius)), CG.Point(swipe % new SKPoint(center.X, center.Y + accentRadius)));

            var lightPath = new CGPath();

            lightPath.MoveToPoint(CG.Point(swipe % new SKPoint(center.X - accentRadius, center.Y)));
            lightPath.AddCurveToPoint(CG.Point(swipe % new SKPoint(center.X - accentRadius, center.Y - pull * accentRadius)), CG.Point(swipe % new SKPoint(center.X - pull * accentRadius, center.Y - accentRadius)), CG.Point(swipe % new SKPoint(center.X, center.Y - accentRadius)));

            using (var strokePaint = new SKPaint {
                Style = SKPaintStyle.Stroke, Color = new SKColor(0, 0, 0, 191), StrokeWidth = swipe % strokeWidth, IsAntialias = true
            })
                using (var accentLightPaint = new SKPaint {
                    Style = SKPaintStyle.Stroke, Color = new SKColor(255, 255, 255, 191), StrokeWidth = swipe % accentStrokeWidth, StrokeCap = SKStrokeCap.Round, IsAntialias = true
                })
                    using (var accentDarkPaint = new SKPaint {
                        Style = SKPaintStyle.Stroke, Color = new SKColor(0, 0, 0, 95), StrokeWidth = swipe % accentStrokeWidth, StrokeCap = SKStrokeCap.Round, IsAntialias = true
                    })
                    {
                        canvas.AddPath(path);
                        canvas.SetFillColor(CG.Color(fillPaint.Color));
                        canvas.FillPath();

                        canvas.AddPath(darkPath);
                        canvas.SetStrokeColor(CG.Color(accentDarkPaint.Color));
                        canvas.SetLineWidth(accentDarkPaint.StrokeWidth);
                        canvas.SetLineJoin(CG.LineJoin(accentDarkPaint.StrokeJoin));
                        canvas.SetLineCap(CG.LineCap(accentDarkPaint.StrokeCap));
                        canvas.StrokePath();

                        canvas.AddPath(lightPath);
                        canvas.SetStrokeColor(CG.Color(accentLightPaint.Color));
                        canvas.SetLineWidth(accentLightPaint.StrokeWidth);
                        canvas.SetLineJoin(CG.LineJoin(accentLightPaint.StrokeJoin));
                        canvas.SetLineCap(CG.LineCap(accentLightPaint.StrokeCap));
                        canvas.StrokePath();

                        canvas.AddPath(path);
                        canvas.SetStrokeColor(CG.Color(strokePaint.Color));
                        canvas.SetLineWidth(strokePaint.StrokeWidth);
                        canvas.SetLineJoin(CG.LineJoin(strokePaint.StrokeJoin));
                        canvas.SetLineCap(CG.LineCap(strokePaint.StrokeCap));
                        canvas.StrokePath();
                    }

            DrawDropletLabel(canvas, label, center, radius, textStrokeWidth, biggie, swipe);
        }