plotCubicBezier function

void plotCubicBezier(
  1. Curve curve,
  2. SetPixel setPixel, {
  3. int width = 1,
})

Implementation

void plotCubicBezier(
  Curve curve,
  SetPixel setPixel, {
  int width = 1,
}) {
  double x0 = curve.point1.x;
  double y0 = curve.point1.y;
  final double x1 = curve.handle1.x;
  final double y1 = curve.handle1.y;
  final double x2 = curve.handle2.x;
  final double y2 = curve.handle2.y;
  double x3 = curve.point2.x;
  double y3 = curve.point2.y;

  /* plot any cubic Bezier curve */
  int n = 0;
  double i = 0;
  final double xc = x0 + x1 - x2 - x3;
  final double xa = xc - 4 * (x1 - x2);
  final double xb = x0 - x1 - x2 + x3;
  final double xd = xb + 4 * (x1 + x2);
  final double yc = y0 + y1 - y2 - y3;
  final double ya = yc - 4 * (y1 - y2);
  final double yb = y0 - y1 - y2 + y3;
  final double yd = yb + 4 * (y1 + y2);
  double fx0 = x0, fx1, fx2, fx3;
  double fy0 = y0, fy1, fy2, fy3;
  double t1 = xb * xb - xa * xc, t2;
  final List<double?> t = List.generate(7, (index) => null);
  /* sub-divide curve at gradient sign changes */
  if (xa == 0) {
    /* horizontal */
    if (xc.abs() < 2 * xb.abs()) {
      t[n++] = xc / (2.0 * xb); /* one change */
    }
  } else if (t1 > 0.0) {
    /* two changes */
    t2 = math.sqrt(t1);
    t1 = (xb - t2) / xa;
    if (t1.abs() < 1.0) {
      t[n++] = t1;
    }
    t1 = (xb + t2) / xa;
    if (t1.abs() < 1.0) {
      t[n++] = t1;
    }
  }
  t1 = yb * yb - ya * yc;
  if (ya == 0) {
    /* vertical */
    if (yc.abs() < 2 * yb.abs()) {
      t[n++] = yc / (2.0 * yb); /* one change */
    }
  } else if (t1 > 0.0) {
    /* two changes */
    t2 = math.sqrt(t1);
    t1 = (yb - t2) / ya;
    if (t1.abs() < 1.0) {
      t[n++] = t1;
    }
    t1 = (yb + t2) / ya;
    if (t1.abs() < 1.0) {
      t[n++] = t1;
    }
  }
  t1 = 2 * (xa * yb - xb * ya);
  t2 = xa * yc - xc * ya; /* divide at inflection point */
  i = t2 * t2 - 2 * t1 * (xb * yc - xc * yb);
  if (i > 0) {
    i = math.sqrt(i);
    t[n] = (t2 + i) / t1;
    if (t[n]!.abs() < 1.0) {
      n++;
    }
    t[n] = (t2 - i) / t1;
    if (t[n]!.abs() < 1.0) {
      n++;
    }
  }
  for (int i = 1; i < n; i++) {
    /* bubble sort of 4 points */
    if ((t1 = t[i - 1]!) > t[i]!) {
      t[i - 1] = t[i];
      t[i] = t1;
      i = 0;
    }
  }
  t1 = -1.0;
  t[n] = 1.0; /* begin / end points */
  for (int i = 0; i <= n; i++) {
    /* plot each segment separately */
    t2 = t[i]!; /* sub-divide at t[i-1], t[i] */
    fx1 = (t1 * (t1 * xb - 2 * xc) - t2 * (t1 * (t1 * xa - 2 * xb) + xc) + xd) / 8 - fx0;
    fy1 = (t1 * (t1 * yb - 2 * yc) - t2 * (t1 * (t1 * ya - 2 * yb) + yc) + yd) / 8 - fy0;
    fx2 = (t2 * (t2 * xb - 2 * xc) - t1 * (t2 * (t2 * xa - 2 * xb) + xc) + xd) / 8 - fx0;
    fy2 = (t2 * (t2 * yb - 2 * yc) - t1 * (t2 * (t2 * ya - 2 * yb) + yc) + yd) / 8 - fy0;
    fx0 -= fx3 = (t2 * (t2 * (3 * xb - t2 * xa) - 3 * xc) + xd) / 8;
    fy0 -= fy3 = (t2 * (t2 * (3 * yb - t2 * ya) - 3 * yc) + yd) / 8;
    x3 = (fx3 + 0.5).floorToDouble();
    y3 = (fy3 + 0.5).floorToDouble(); /* scale bounds */
    if (fx0 != 0.0) {
      fx1 *= fx0 = (x0 - x3) / fx0;
      fx2 *= fx0;
    }
    if (fy0 != 0.0) {
      fy1 *= fy0 = (y0 - y3) / fy0;
      fy2 *= fy0;
    }
    if (x0 != x3 || y0 != y3) {
      /* segment t1 - t2 */
      _plotCubicBezierSegWidth(
        Curve.fromList([
          [x0, y0],
          [x0 + fx1, y0 + fy1],
          [x0 + fx2, y0 + fy2],
          [x3, y3]
        ]),
        width,
        setPixel,
      );
    }
    x0 = x3;
    y0 = y3;
    fx0 = fx3;
    fy0 = fy3;
    t1 = t2;
  }
}