public LinkedChainPage()
        {
            Title = "Linked Chain";

            SKCanvasView canvasView = new SKCanvasView();

            canvasView.PaintSurface += OnCanvasViewPaintSurface;
            Content = canvasView;

            // Create the path for the individual links
            SKRect outer = new SKRect(-linkRadius, -linkRadius, linkRadius, linkRadius);
            SKRect inner = outer;

            inner.Inflate(-linkThickness, -linkThickness);

            using (SKPath linkPath = new SKPath())
            {
                linkPath.AddArc(outer, 55, 160);
                linkPath.ArcTo(inner, 215, -160, false);
                linkPath.Close();

                linkPath.AddArc(outer, 235, 160);
                linkPath.ArcTo(inner, 395, -160, false);
                linkPath.Close();

                // Set that path as the 1D path effect for linksPaint
                linksPaint.PathEffect =
                    SKPathEffect.Create1DPath(linkPath, 1.3f * linkRadius, 0,
                                              SKPath1DPathEffectStyle.Rotate);
            }
        }
        void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
        {
            SKImageInfo info    = args.Info;
            SKSurface   surface = args.Surface;
            SKCanvas    canvas  = surface.Canvas;

            canvas.Clear();

            float width          = info.Width / 3;
            float verticalMargin = width / 2 + 150;

            using (SKPath conveyerPath = new SKPath())
            {
                // Straight verticals capped by semicircles on top and bottom
                conveyerPath.MoveTo(width, verticalMargin);
                conveyerPath.ArcTo(width / 2, width / 2, 0, SKPathArcSize.Large,
                                   SKPathDirection.Clockwise, 2 * width, verticalMargin);
                conveyerPath.LineTo(2 * width, info.Height - verticalMargin);
                conveyerPath.ArcTo(width / 2, width / 2, 0, SKPathArcSize.Large,
                                   SKPathDirection.Clockwise, width, info.Height - verticalMargin);
                conveyerPath.Close();

                // Draw the conveyor belt itself
                canvas.DrawPath(conveyerPath, conveyerPaint);

                // Calculate spacing based on length of conveyer path
                float length = 2 * (info.Height - 2 * verticalMargin) +
                               2 * ((float)Math.PI * width / 2);

                // Value will be somewhere around 200
                float spacing = length / (float)Math.Round(length / 200);

                // Now animate the phase; t is 0 to 1 every 2 seconds
                TimeSpan timeSpan = new TimeSpan(DateTime.Now.Ticks);
                float    t        = (float)(timeSpan.TotalSeconds % 2 / 2);
                float    phase    = -t * spacing;

                // Create the buckets PathEffect
                using (SKPathEffect bucketsPathEffect =
                           SKPathEffect.Create1DPath(bucketPath, spacing, phase,
                                                     SKPath1DPathEffectStyle.Rotate))
                {
                    // Set it to the Paint object and draw the path again
                    bucketsPaint.PathEffect = bucketsPathEffect;
                    canvas.DrawPath(conveyerPath, bucketsPaint);
                }
            }
        }
        public TextPathEffectPage()
        {
            Title = "Text Path Effect";

            SKCanvasView canvasView = new SKCanvasView();

            canvasView.PaintSurface += OnCanvasViewPaintSurface;
            Content = canvasView;

            // Get the bounds of textPathPaint
            SKRect textPathPaintBounds;

            textPathPaint.MeasureText(character, ref textPathPaintBounds);

            // Create textPath centered around (0, 0)
            SKPath textPath = textPathPaint.GetTextPath(character,
                                                        -textPathPaintBounds.MidX,
                                                        -textPathPaintBounds.MidY);

            // Create the path effect
            pathEffect = SKPathEffect.Create1DPath(textPath, littleSize, 0,
                                                   SKPath1DPathEffectStyle.Translate);
        }
        public CatsInFramePage()
        {
            Title = "Cats in Frame";

            SKCanvasView canvasView = new SKCanvasView();

            canvasView.PaintSurface += OnCanvasViewPaintSurface;
            Content = canvasView;

            // Move (0, 0) point to center of cat path
            catPath.Transform(SKMatrix.MakeTranslation(-240, -175));

            // Now catPath is 400 by 250
            // Scale it down to 160 by 100
            catPath.Transform(SKMatrix.MakeScale(0.40f, 0.40f));

            // Get the outlines of the contours of the cat path
            SKPath outlinedCatPath = new SKPath();

            catStroke.GetFillPath(catPath, outlinedCatPath);

            // Create a 2D path effect from those outlines
            SKPathEffect fillEffect = SKPathEffect.Create2DPath(
                new SKMatrix {
                ScaleX = 170, ScaleY = 110,
                TransX = 75, TransY = 80,
                Persp2 = 1
            },
                outlinedCatPath);

            // Create a 1D path effect from the scallop path
            SKPathEffect strokeEffect =
                SKPathEffect.Create1DPath(scallopPath, 75, 0, SKPath1DPathEffectStyle.Rotate);

            // Set the sum the effects to frame paint
            framePaint.PathEffect = SKPathEffect.CreateSum(fillEffect, strokeEffect);
        }