plotEllipseRectAA function
Implementation
void plotEllipseRectAA(double x0, double y0, double x1, double y1, SetPixel setPixel) {
/* draw a black anti-aliased rectangular ellipse on white background */
double a = (x1 - x0).abs();
final double b = (y1 - y0).abs();
int b1 = b.floor() & 1; /* diameter */
double dx = 4 * (a - 1) * b * b;
double dy = 4 * (b1 + 1) * a * a; /* error increment */
double ed;
double i;
var err = b1 * a * a - dx + dy; /* error of 1.step */
if (a == 0 || b == 0) {
return plotLine(x0, y0, x1, y1, setPixel);
}
if (x0 > x1) {
x0 = x1;
x1 += a;
} /* if called with swapped points */
if (y0 > y1) {
y0 = y1; /* .. exchange them */
}
y0 += (b.floor() + 1) >> 1;
y1 = y0 - b1; /* starting pixel */
a = 8 * a * a;
b1 = 8 * b.floor() * b.floor();
for (;;) {
/* approximate ed=Math.sqrt(dx*dx+dy*dy) */
i = math.min(dx, dy);
ed = math.max(dx, dy);
if (y0 == y1 + 1 && err > dy && a > b1) {
ed = 255 * 4 / a; /* x-tip */
} else {
ed = 255 / (ed + 2 * ed * i * i / (4 * ed * ed + i * i)); /* approximation */
}
i = ed * (err + dx - dy).abs(); /* get intensity value by pixel err */
setPixel(x0, y0, i.round());
setPixel(x0, y1, i.round());
setPixel(x1, y0, i.round());
setPixel(x1, y1, i.round());
final bool f = 2 * err + dy >= 0;
if (f) {
/* x step, remember condition */
if (x0 >= x1) {
break;
}
i = ed * (err + dx);
if (i < 256) {
setPixel(x0, y0 + 1, i.round());
setPixel(x0, y1 - 1, i.round());
setPixel(x1, y0 + 1, i.round());
setPixel(x1, y1 - 1, i.round());
} /* do error increment later since values are still needed */
}
if (2 * err <= dx) {
/* y step */
i = ed * (dy - err);
if (i < 256) {
setPixel(x0 + 1, y0, i.round());
setPixel(x1 - 1, y0, i.round());
setPixel(x0 + 1, y1, i.round());
setPixel(x1 - 1, y1, i.round());
}
y0++;
y1--;
err += dy += a;
}
if (f) {
x0++;
x1--;
err -= dx -= b1;
} /* x error increment */
}
if (--x0 == x1++) {
/* too early stop of flat ellipses */
while (y0 - y1 < b) {
i = 255 * 4 * (err + dx).abs() / b1; /* -> finish tip of ellipse */
setPixel(x0, ++y0, i.round());
setPixel(x1, y0, i.round());
setPixel(x0, --y1, i.round());
setPixel(x1, y1, i.round());
err += dy += a;
}
}
}