applyTo method

dynamic applyTo(
  1. Path path
)

Implementation

applyTo(Path path) {
  // initial point of a sub-path, absolute position, updated on MoveTo
  double ix = 0;
  double iy = 0;
  // current point, absolute position
  double x = 0;
  double y = 0;
  // control point for bezier curve, absolute position
  double? cx;
  double? cy;
  _CSSPathCommandType? preType;

  for (var command in _commands) {
    final params = command.params;
    final type = command.type;

    if (preType != null && preType.category != type.category) {
      // reset control point for bezier curve when category is changed
      cx = null;
      cy = null;
    }

    switch (type) {
      case _CSSPathCommandType.M:
        if (command.isSubSequent) {
          // sub sequent command treated as line to
          path.lineTo(x = params[0], y = params[1]);
        } else {
          path.moveTo(ix = x = params[0], iy = y = params[1]);
        }
        break;
      case _CSSPathCommandType.m:
        if (command.isSubSequent) {
          path.relativeLineTo(params[0], params[1]);
          x += params[0];
          y += params[1];
        } else {
          path.relativeMoveTo(params[0], params[1]);
          ix = x += params[0];
          iy = y += params[1];
        }
        break;
      case _CSSPathCommandType.L:
        path.lineTo(x = params[0], y = params[1]);
        break;
      case _CSSPathCommandType.l:
        path.relativeLineTo(params[0], params[1]);
        x += params[0];
        y += params[1];
        break;
      case _CSSPathCommandType.H:
        path.lineTo(x = params[0], y);
        break;
      case _CSSPathCommandType.h:
        x += params[0];
        path.relativeLineTo(params[0], 0);
        break;
      case _CSSPathCommandType.V:
        path.lineTo(x, y = params[0]);
        break;
      case _CSSPathCommandType.v:
        y += params[0];
        path.relativeLineTo(0, params[0]);
        break;
      case _CSSPathCommandType.A:
        path.arcToPoint(
            Offset(x = params[5], y = params[6]),
            radius: Radius.elliptical(params[0], params[1]),
          rotation: params[2],
          largeArc: params[3] == 1,
          clockwise: params[4] == 1,
        );
        break;
      case _CSSPathCommandType.a:
        x += params[5];
        y += params[6];
        path.relativeArcToPoint(Offset(params[5], params[6]),
          radius: Radius.elliptical(params[0], params[1]),
          rotation: params[2],
          largeArc: params[3] == 1,
          clockwise: params[4] == 1);
        break;

      case _CSSPathCommandType.C:
        path.cubicTo(params[0], params[1], cx = params[2], cy = params[3], x = params[4], y = params[5]);
        break;
      case _CSSPathCommandType.c:
        path.relativeCubicTo(params[0], params[1], params[2], params[3], params[4], params[5]);
        cx = x + params[2];
        cy = y + params[3];
        x += params[4];
        y += params[5];
        break;

      case _CSSPathCommandType.S:
        path.cubicTo(cx ?? x, cy ?? y, cx = params[0], cy = params[1], x = params[2], y = params[3]);
        break;

      case _CSSPathCommandType.s:
        path.relativeCubicTo(cx != null ? cx - x : 0, cy != null ? cy - y : 0, params[0], params[1], params[2], params[3]);
        cx = x + params[0];
        cy = y + params[1];
        x += params[2];
        y += params[3];
        break;

      case _CSSPathCommandType.Q:
        path.quadraticBezierTo(cx = params[0], cy = params[1], x = params[2], y = params[3]);
        break;
      case _CSSPathCommandType.q:
        path.relativeQuadraticBezierTo(params[0], params[1], params[2], params[3]);
        cx = x + params[0];
        cy = y + params[1];
        x += params[2];
        y += params[3];
        break;

      case _CSSPathCommandType.T:
        cx ??= x;
        cy ??= y;
        path.quadraticBezierTo(cx, cy, x = params[0], y = params[1]);
        break;

      case _CSSPathCommandType.t:
        path.relativeQuadraticBezierTo(cx != null ? cx - x : 0, cy != null ? cy - y : 0, params[0], params[1]);
        x += params[0];
        y += params[1];
        cx ??= x;
        cy ??= y;
        break;

      case _CSSPathCommandType.Z:
      case _CSSPathCommandType.z:
        path.close();
        x = ix;
        y = iy;
        break;
    }

    if (type.isBezierCurve) {
      // reflect control point based on the end point
      assert(cx != null);
      assert(cy != null);
      cx = x + (x - cx!);
      cy = y + (y - cy!);
    }

    preType = type;
  }
}