The quadratic/cubic bézier curve code I find via google mostly works by subdividing the line into a series of points and connects them with straight lines. The rasterization
First of all, I'd like to say that the fastest and the most reliable way to render bezier curves is to approximate them by polyline via adaptive subdivision, then render the polyline. Approach by @markE with drawing many points sampled on the curve is rather fast, but it can skip pixels. Here I describe another approach, which is closest to line rasterization (though it is slow and hard to implement robustly).
I'll treat usually curve parameter as time. Here is the pseudocode:
This algorithm works until time parameter exceeds one. Also note that it has severe issues with curves exactly touching a side of a pixel. I suppose it is solvable with a special check.
Here is the main code:
double WhenEquals(double p0, double p1, double p2, double val, double minp) {
//p0 * (1-t)^2 + p1 * 2t(1 - t) + p2 * t^2 = val
double qa = p0 + p2 - 2 * p1;
double qb = p1 - p0;
double qc = p0 - val;
assert(fabs(qa) > EPS); //singular case must be handled separately
double qd = qb * qb - qa * qc;
if (qd < -EPS)
return INF;
qd = sqrt(max(qd, 0.0));
double t1 = (-qb - qd) / qa;
double t2 = (-qb + qd) / qa;
if (t2 < t1) swap(t1, t2);
if (t1 > minp + EPS)
return t1;
else if (t2 > minp + EPS)
return t2;
return INF;
}
void DrawCurve(const Bezier &curve) {
int cell[2];
for (int c = 0; c < 2; c++)
cell[c] = int(floor(curve.pts[0].a[c]));
DrawPixel(cell[0], cell[1]);
double param = 0.0;
while (1) {
int bc = -1, bs = -1;
double bestTime = 1.0;
for (int c = 0; c < 2; c++)
for (int s = 0; s < 2; s++) {
double crit = WhenEquals(
curve.pts[0].a[c],
curve.pts[1].a[c],
curve.pts[2].a[c],
cell[c] + s, param
);
if (crit < bestTime) {
bestTime = crit;
bc = c, bs = s;
}
}
if (bc < 0)
break;
param = bestTime;
cell[bc] += (2*bs - 1);
DrawPixel(cell[0], cell[1]);
}
}
Full code is available here. It uses loadbmp.h, here it is.