pathFromCubics function

Path pathFromCubics({
  1. required Path path,
  2. required int startAngle,
  3. required bool repeatPath,
  4. required bool closePath,
  5. required List<Cubic> cubics,
  6. required double rotationPivotX,
  7. required double rotationPivotY,
})

Returns a Path for a Cubic list.

path is a Path to reset and set with the new path data.

startAngle is an angle (in degrees) to rotate the Path to start drawing from. If startAngle is non zero, then caller has to use the returned Path, as path transformation creates a new path.

repeatPath is whether or not to repeat the Path twice before closing it. This flag is useful when the caller would like to draw parts of the path while offsetting the start and stop positions (for example, when phasing and rotating a path to simulate a motion as a Star circular progress indicator advances).

closePath is whether or not to close the created Path.

cubics is list of Cubics to build path from.

rotationPivotX is the rotation pivot on the X axis.

rotationPivotY is the rotation pivot on the Y axis.

Implementation

Path pathFromCubics({
  required Path path,
  required int startAngle,
  required bool repeatPath,
  required bool closePath,
  required List<Cubic> cubics,
  required double rotationPivotX,
  required double rotationPivotY,
}) {
  var first = true;
  Cubic? firstCubic;

  path.reset();

  for (final cubic in cubics) {
    if (first) {
      path.moveTo(cubic.anchor0X, cubic.anchor0Y);
      if (startAngle != 0) {
        firstCubic = cubic;
      }
      first = false;
    }

    path.cubicTo(
      cubic.control0X,
      cubic.control0Y,
      cubic.control1X,
      cubic.control1Y,
      cubic.anchor1X,
      cubic.anchor1Y,
    );
  }

  if (repeatPath) {
    var firstInRepeat = true;
    for (final cubic in cubics) {
      if (firstInRepeat) {
        path.lineTo(cubic.anchor0X, cubic.anchor0Y);
        firstInRepeat = false;
      }

      path.cubicTo(
        cubic.control0X,
        cubic.control0Y,
        cubic.control1X,
        cubic.control1Y,
        cubic.anchor1X,
        cubic.anchor1Y,
      );
    }
  }

  if (closePath) {
    path.close();
  }

  if (startAngle != 0 && firstCubic != null) {
    final angleToFirstCubic = math.atan2(
      cubics[0].anchor0Y - rotationPivotY,
      cubics[0].anchor0X - rotationPivotX,
    );
    // Rotate the Path to to start from the given angle.
    path = path.transform(
      (Matrix4.identity()
            ..rotateZ(
              -angleToFirstCubic + (startAngle * math.pi / 180),
            ))
          .storage,
    );
  }

  return path;
}