computeLength method

double computeLength(
  1. Point start
)

Computes an approximation of the arc length of this cubic starting from start.

Implementation

double computeLength(Point start) {
  // Mike Reed just made this up! The nerve of him.
  // One difference from Skia is just setting a default tolerance of 3. This
  // is good enough for a particular test SVG that has this curve:
  // M65 33c0 17.673-14.326 32-32 32S1 50.673 1 33C1 15.327 15.326 1 33 1s32 14.327 32 32z
  // Lower values end up getting the end points wrong when dashing a path.
  const double tolerance = 1 / 2 * 3;

  double _compute(
    Point p1,
    Point cp1,
    Point cp2,
    Point p2,
    double distance,
  ) {
    // If it's "too curvy," cut it in half
    if (Point.distance(cp1, Point.lerp(p1, p2, 1 / 3)) > tolerance ||
        Point.distance(cp2, Point.lerp(p1, p2, 2 / 3)) > tolerance) {
      final List<Point> points = subdivide(p1, cp1, cp2, p2, .5);
      distance = _compute(
        points[0],
        points[1],
        points[2],
        points[3],
        distance,
      );
      distance = _compute(
        points[3],
        points[4],
        points[5],
        points[6],
        distance,
      );
    } else {
      // It's collinear enough to just treat as a line.
      distance += Point.distance(p1, p2);
    }
    return distance;
  }

  return _compute(start, Point(x1, y1), Point(x2, y2), Point(x3, y3), 0);
}