/// <summary>Draw a pie meter</summary>
        private void PaintPie(SKImageInfo info, SKCanvas canvas, bool handles = false)
        {
            float arcWidth = (info.Width / 15.0F) * 1.0F;

            // always draw a background ring
            using (SKPath path = new SKPath())
            {
                path.AddArc(this.OuterRect, 0, 360);
                canvas.DrawPath(path, new SKPaint()
                {
                    Color = _disabled, StrokeWidth = this.ArcLineWidth, Style = SKPaintStyle.Stroke, IsAntialias = true
                });
            }

            // calc the sum
            float total = this.Value1 + this.Value2;

            // bail if both are 0
            if (total <= 0.0)
            {
                return;
            }

            // calc the sweep angle
            float sweep = (this.Value1 / total) * 360.0F;

            // calc the angles, 0 is to the right, start from overhead
            float rewardSweep     = (sweep > 360.0) ? 360.0F : sweep;
            float bonusStartAngle = QuickCalc.Revolution(270.0F + rewardSweep);

            // draw arc 1
            using (SKPath path = new SKPath())
            {
                using (SKPaint arcPaint = new SKPaint {
                    Style = SKPaintStyle.Stroke, Color = this.ArcColor1.ToSKColor(), StrokeWidth = this.ArcLineWidth, IsAntialias = true
                })
                {
                    path.AddArc(this.OuterRect, 270, rewardSweep);
                    canvas.DrawPath(path, arcPaint);
                }
            }

            // draw arc 2
            using (SKPath path = new SKPath())
            {
                using (SKPaint arcPaint = new SKPaint {
                    Style = SKPaintStyle.Stroke, Color = this.ArcColor2.ToSKColor(), StrokeWidth = this.ArcLineWidth, IsAntialias = true
                })
                {
                    path.AddArc(this.OuterRect, bonusStartAngle, 360 - rewardSweep);
                    canvas.DrawPath(path, arcPaint);
                }
            }

            if (!handles)
            {
                return;
            }

            // draw handles
            using (SKPaint handlePaint = new SKPaint()
            {
                Color = this.ArcColor1.ToSKColor(), StrokeCap = SKStrokeCap.Round, StrokeWidth = this.ArcLineWidth * 2, IsAntialias = true
            })
            {
                canvas.DrawPoint(this.VerticalCenter, this.OuterRect.Top, handlePaint);

                // where's the other handle?
                float rad = QuickCalc.Deg2Rad(QuickCalc.Revolution(360 - rewardSweep + 90));
                Tuple <float, float> pt = QuickCalc.Transform(rad, this.OuterRect.Width / 2.0F);

                handlePaint.Color = this.ArcColor2.ToSKColor();
                canvas.DrawPoint(pt.Item1 + info.Rect.MidX, info.Rect.MidY - pt.Item2, handlePaint);
            }
        }
        /// <summary>Draw a progress meter</summary>
        /// <remarks>
        /// Value 1 is the part and Value 2 is the total possible
        /// Value 1 can exceed value 2 for mutiple revolutions
        /// </remarks>
        private void PaintProgress(SKImageInfo info, SKCanvas canvas)
        {
            // set up the gradient colors
            SKColor[] colors = new SKColor[2] {
                this.ArcColor1.ToSKColor(), this.ArcColor2.ToSKColor()
            };

            // sweep is in DEG -> normalize the sweep angle between 0 and 360
            //float sweep = QuickCalc.Revolution( ( this.Value1 / this.Value2 ) * 360.0F );
            //sweep = ( sweep > 360.0 ) ? 360.0F : sweep;
            float sweep = (this.Value1 % this.Value2 / this.Value2) * 360.0F;

            // we have to roate the drawing canvas 90 degrees CCW
            canvas.RotateDegrees(-90, info.Width / 2, info.Height / 2);

            // no value
            if (this.Value1 <= 0.0)
            {
                // draw background ring
                using (SKPath path = new SKPath())
                {
                    using (SKPaint bkgPaint = new SKPaint()
                    {
                        Color = _disabled, StrokeWidth = this.ArcLineWidth, Style = SKPaintStyle.Stroke, IsAntialias = true
                    })
                    {
                        path.AddArc(this.OuterRect, 0, 360.0F);
                        canvas.DrawPath(path, bkgPaint);
                    }
                }
            }
            // less than 1 revolution
            else if (this.Value1 < this.Value2)
            {
                // draw background ring
                using (SKPath path = new SKPath())
                {
                    using (SKPaint bkgPaint = new SKPaint()
                    {
                        Color = _disabled, StrokeWidth = this.ArcLineWidth, Style = SKPaintStyle.Stroke, IsAntialias = true
                    })
                    {
                        path.AddArc(this.OuterRect, 0, 360.0F);
                        canvas.DrawPath(path, bkgPaint);
                    }
                }

                // draw the partial arc
                using (SKPath path = new SKPath())
                {
                    using (SKPaint arcPaint = new SKPaint {
                        Style = SKPaintStyle.Stroke, Color = this.ArcColor1.ToSKColor()
                    })
                    {
                        arcPaint.StrokeWidth = this.ArcLineWidth;
                        arcPaint.StrokeCap   = SKStrokeCap.Butt;
                        arcPaint.IsAntialias = true;
                        arcPaint.Shader      = SKShader.CreateSweepGradient(this.Origin, colors, new Single[] { 0, 1 }, SKShaderTileMode.Clamp, 0, sweep);

                        // create an arc to sweep along
                        path.AddArc(this.OuterRect, 0, sweep);
                        canvas.DrawPath(path, arcPaint);
                    }
                }
            }
            else             // 1 or more revolution
            {
                // draw background ring
                using (SKPath path = new SKPath())
                {
                    using (SKPaint bkgPaint = new SKPaint()
                    {
                        Color = this.ArcColor1.ToSKColor(), StrokeWidth = this.ArcLineWidth
                    })
                    {
                        bkgPaint.Style       = SKPaintStyle.Stroke;
                        bkgPaint.IsAntialias = true;

                        path.AddArc(this.OuterRect, 0, 360.0F);
                        canvas.DrawPath(path, bkgPaint);
                    }
                }

                // rotate the canvas by the sweep angle so we always start at 0
                canvas.RotateDegrees(sweep - 180, info.Width / 2, info.Height / 2);

                // draw the partial gradiant arc
                using (SKPath path = new SKPath())
                {
                    using (SKPaint arcPaint = new SKPaint {
                        Style = SKPaintStyle.Stroke
                    })
                    {
                        arcPaint.Color       = this.ArcColor2.ToSKColor();
                        arcPaint.StrokeWidth = this.ArcLineWidth;
                        arcPaint.StrokeCap   = SKStrokeCap.Butt;
                        arcPaint.IsAntialias = true;

                        // sweep gradient uses start angle to end angle
                        arcPaint.Shader = SKShader.CreateSweepGradient(this.Origin, colors, new Single[] { 0, 1 }, SKShaderTileMode.Clamp, 0, 180);

                        // create an arc to sweep along - uses start angle and then how many degrees to rotate from start
                        path.AddArc(this.OuterRect, 0, 180);
                        canvas.DrawPath(path, arcPaint);
                    }
                }

                canvas.RotateDegrees(-(sweep - 180), info.Width / 2, info.Height / 2);
            }

            // calc pts for the trailing handle
            Tuple <float, float> pt1 = QuickCalc.Transform(QuickCalc.Deg2Rad(sweep + (this.ArcLineWidth * 0.075F)), this.OuterRect.Width / 2.0F);
            Tuple <float, float> pt2 = QuickCalc.Transform(QuickCalc.Deg2Rad(sweep), this.OuterRect.Width / 2.0F);

            // draw the trailing point with shadow
            using (SKPaint handlePaint = new SKPaint()
            {
                Color = this.BackgroundColor.ToSKColor()
            })
            {
                handlePaint.StrokeCap   = SKStrokeCap.Round;
                handlePaint.StrokeWidth = this.ArcLineWidth * 2;
                handlePaint.IsAntialias = true;

                // shadow
                canvas.DrawPoint(pt1.Item1 + info.Rect.MidX, info.Rect.MidY + pt1.Item2, handlePaint);

                // change color
                handlePaint.Color = this.ArcColor2.ToSKColor();

                // handle
                canvas.DrawPoint(pt2.Item1 + info.Rect.MidX, info.Rect.MidY + pt2.Item2, handlePaint);
            }

            // rotate it all back
            canvas.RotateDegrees(90, info.Width / 2, info.Height / 2);
        }