private static void Subdivide(List <SKPoint> path, int desiredPointCount)
        {
            var desiredLength = path.Count + desiredPointCount;
            var step          = SKGeometry.Perimeter(path) / desiredPointCount;

            var i        = 0;
            var cursor   = 0.0f;
            var insertAt = step / 2f;

            while (path.Count < desiredLength)
            {
                var a       = path[i];
                var b       = path[(i + 1) % path.Count];
                var segment = SKGeometry.Distance(a, b);

                if (insertAt <= cursor + segment)
                {
                    path.Insert(i + 1, segment != 0 ? SKGeometry.PointAlong(a, b, (insertAt - cursor) / segment) : a);
                    insertAt += step;
                    continue;
                }

                cursor += segment;
                i++;
            }
        }
        private static void Rotate(List <SKPoint> from, List <SKPoint> to)
        {
            var bestOffset = 0;

            var min = float.PositiveInfinity;
            var len = from.Count;

            for (var offset = 0; offset < len; offset++)
            {
                var sumOfSquares = 0.0f;
                for (var i = 0; i < len; i++)
                {
                    var d = SKGeometry.Distance(from[(offset + i) % len], to[i]);
                    sumOfSquares += d * d;
                }

                if (sumOfSquares < min)
                {
                    min        = sumOfSquares;
                    bestOffset = offset;
                }
            }

            if (bestOffset != 0)
            {
                Rotate(from, bestOffset);
            }
        }
        private static void Bisect(List <SKPoint> ring, float maxSegmentLength)
        {
            // skip if we have asked that the path not be bisected
            if (maxSegmentLength <= 0)
            {
                return;
            }

            for (var i = 0; i < ring.Count; i++)
            {
                var a = ring[i];
                var b = i == ring.Count - 1 ? ring[0] : ring[i + 1];

                // could splice the whole set for a segment instead, but a bit messy
                while (SKGeometry.Distance(a, b) > maxSegmentLength)
                {
                    b = SKGeometry.PointAlong(a, b, 0.5f);
                    ring.Insert(i + 1, b);
                }
            }
        }
        private static List <SKPoint> NormalizePath(SKPath parsed, float maxSegmentLength)
        {
            var skipBisect = false;
            var points     = CreateLinearPathPoints(parsed);

            if (points == null)
            {
                points     = CreateCurvedPathPoints(parsed, maxSegmentLength);
                skipBisect = true;
            }

            // TODO:
            //// no duplicate closing point for now
            //if (points.Count > 1 && SKGeometry.Distance(points[0], points[points.Count - 1]) < 1e-9f)
            //{
            //	points.pop();
            //}

            // 3+ points to make a polygon
            if (points.Count < 3)
            {
                return(null);
            }

            // make all rings clockwise
            if (SKGeometry.Area(points) > 0)
            {
                points.Reverse();
            }

            if (!skipBisect && maxSegmentLength > 0)
            {
                Bisect(points, maxSegmentLength);
            }

            return(points);
        }