plotCubicBezier function
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;
}
}