generateOuterDynamicPath method

DynamicPath generateOuterDynamicPath(
  1. Rect rect
)
override

Implementation

DynamicPath generateOuterDynamicPath(Rect rect) {
  List<DynamicNode> nodes = [];

  double scale = min(rect.width, rect.height) / 2;
  double cornerRadius = this.cornerRadius.toPX(constraint: scale / 2);
  double insetRadius = this.insetRadius.toPX(constraint: scale / 2);

  final int vertices = corners * 2;
  final double alpha = (2 * pi) / vertices;

  final double centerX = scale;
  final double centerY = scale;

  double inset = this.inset.toPX(constraint: scale);
  inset = inset.clamp(0.0, scale * 0.999);
  double sideLength = getThirdSideLength(scale, scale - inset, alpha);
  double beta = getThirdAngle(sideLength, scale, scale - inset);
  double gamma = alpha + beta;

  cornerRadius = cornerRadius.clamp(0, sideLength * tan(beta));

  double avalSideLength = max(sideLength - cornerRadius / tan(beta), 0.0);
  if (gamma <= pi / 2) {
    insetRadius = insetRadius.clamp(0, avalSideLength * tan(gamma));
  } else {
    insetRadius = insetRadius.clamp(0, avalSideLength * tan(pi - gamma));
  }

  for (int i = 0; i < vertices; i++) {
    double r;
    double omega = -pi / 2 + alpha * i;
    if (i.isEven) {
      r = scale - cornerRadius / sin(beta);
      Offset center =
          Offset((r * cos(omega)) + centerX, (r * sin(omega)) + centerY);
      double sweepAngle = 2 * (pi / 2 - beta);
      Offset start = arcToCubicBezier(
              Rect.fromCircle(center: center, radius: cornerRadius),
              omega - sweepAngle / 2,
              sweepAngle)
          .first;
      Offset end = arcToCubicBezier(
              Rect.fromCircle(center: center, radius: cornerRadius),
              omega - sweepAngle / 2,
              sweepAngle)
          .last;

      switch (cornerStyle) {
        case CornerStyle.rounded:
          nodes.addArc(Rect.fromCircle(center: center, radius: cornerRadius),
              omega - sweepAngle / 2, sweepAngle,
              splitTimes: 1);
          break;
        case CornerStyle.concave:
          nodes.addStyledCorner(
              center, cornerRadius, omega - sweepAngle / 2, sweepAngle,
              splitTimes: 1, style: CornerStyle.concave);
          break;
        case CornerStyle.straight:
          nodes.add(DynamicNode(position: start));
          nodes.add(DynamicNode(position: (start + end) / 2));
          nodes.add(DynamicNode(position: end));
          break;
        case CornerStyle.cutout:
          nodes.add(DynamicNode(position: start));
          nodes.add(DynamicNode(position: center));
          nodes.add(DynamicNode(position: end));
          break;
      }
    } else {
      double sweepAngle = pi - 2 * gamma;
      if (gamma <= pi / 2) {
        r = scale - inset + insetRadius / sin(gamma);
        Offset center =
            Offset((r * cos(omega)) + centerX, (r * sin(omega)) + centerY);
        Offset start = arcToCubicBezier(
                Rect.fromCircle(center: center, radius: insetRadius),
                omega + sweepAngle / 2 + pi,
                -sweepAngle)
            .first;
        Offset end = arcToCubicBezier(
                Rect.fromCircle(center: center, radius: insetRadius),
                omega + sweepAngle / 2 + pi,
                -sweepAngle)
            .last;

        switch (insetStyle) {
          case CornerStyle.rounded:
            nodes.addArc(Rect.fromCircle(center: center, radius: insetRadius),
                omega + sweepAngle / 2 + pi, -sweepAngle,
                splitTimes: 1);
            break;
          case CornerStyle.concave:
            r = scale - inset;
            Offset center = Offset(
                (r * cos(omega)) + centerX, (r * sin(omega)) + centerY);
            double newSweep = ((pi - sweepAngle)).clampAngleWithin();
            double newStart =
                ((omega + sweepAngle / 2 + pi + sweepAngle / 2) +
                        newSweep / 2)
                    .clampAngleWithin();
            nodes.addArc(
                Rect.fromCircle(
                    center: center,
                    radius: insetRadius * tan(sweepAngle / 2)),
                newStart,
                newSweep,
                splitTimes: 1);
            break;
          case CornerStyle.straight:
            nodes.add(DynamicNode(position: start));
            nodes.add(DynamicNode(position: (start + end) / 2));
            nodes.add(DynamicNode(position: end));
            break;
          case CornerStyle.cutout:
            nodes.add(DynamicNode(position: start));
            nodes.add(DynamicNode(position: center));
            nodes.add(DynamicNode(position: end));
            break;
        }
      } else {
        sweepAngle = -sweepAngle;
        r = scale - inset - insetRadius / sin(gamma);
        Offset center =
            Offset((r * cos(omega)) + centerX, (r * sin(omega)) + centerY);
        Offset start = arcToCubicBezier(
                Rect.fromCircle(center: center, radius: insetRadius),
                omega - sweepAngle / 2,
                sweepAngle)
            .first;
        Offset end = arcToCubicBezier(
                Rect.fromCircle(center: center, radius: insetRadius),
                omega - sweepAngle / 2,
                sweepAngle)
            .last;

        switch (insetStyle) {
          case CornerStyle.rounded:
            nodes.addArc(Rect.fromCircle(center: center, radius: insetRadius),
                omega - sweepAngle / 2, sweepAngle,
                splitTimes: 1);
            break;
          case CornerStyle.concave:
            nodes.addStyledCorner(
                center, insetRadius, omega - sweepAngle / 2, sweepAngle,
                splitTimes: 1, style: CornerStyle.concave);

            break;
          case CornerStyle.straight:
            nodes.add(DynamicNode(position: start));
            nodes.add(DynamicNode(position: (start + end) / 2));
            nodes.add(DynamicNode(position: end));
            break;
          case CornerStyle.cutout:
            nodes.add(DynamicNode(position: start));
            nodes.add(DynamicNode(position: center));
            nodes.add(DynamicNode(position: end));
            break;
        }
      }
    }
  }

  return DynamicPath(size: Size(2 * scale, 2 * scale), nodes: nodes)
    ..resize(rect.size);
}