Implementation
bool aaellipseRgba(
Pointer<SdlRenderer> renderer,
double x,
double y,
double rx,
double ry,
int r,
int g,
int b,
int a, {
int blendMode = SDL_BLENDMODE_BLEND,
}) {
var result = true;
int i;
double a2;
double b2;
double ds;
double dt;
double dxt;
double t;
double s;
double d;
double xp;
double yp;
double xs;
double ys;
double dyt;
double od;
double xx;
double yy;
double xc2;
double yc2;
double cp;
double sab;
int weight;
int iweight;
/*
* Sanity check radii
*/
if ((rx < 0) || (ry < 0)) {
return false;
}
/*
* Special cases for rx=0 and/or ry=0: draw a hline/vline/pixel
*/
if (rx == 0) {
if (ry == 0) {
return pixelRgba(renderer, x, y, r, g, b, a, blendMode: blendMode);
} else {
return vlineRgba(
renderer,
x,
y - ry,
y + ry,
r,
g,
b,
a,
blendMode: blendMode,
);
}
} else {
if (ry == 0) {
return hlineRgba(
renderer,
x - rx,
x + rx,
y,
r,
g,
b,
a,
blendMode: blendMode,
);
}
}
/* Variable setup */
a2 = rx * rx;
b2 = ry * ry;
ds = 2 * a2;
dt = 2 * b2;
xc2 = 2 * x;
yc2 = 2 * y;
sab = math.sqrt(a2 + b2);
od = (sab * 0.01).toInt() + 1; /* introduce some overdraw */
dxt = (a2 ~/ sab) + od;
t = 0;
s = -2 * a2 * ry;
d = 0;
xp = x;
yp = y - ry;
/* Draw */
result = true;
if (result) {
result = sdlSetRenderDrawBlendMode(renderer, blendMode);
}
/* "End points" */
if (result) {
result = pixelRgba(renderer, xp, yp, r, g, b, a, blendMode: blendMode);
}
if (result) {
result = pixelRgba(
renderer,
xc2 - xp,
yp,
r,
g,
b,
a,
blendMode: blendMode,
);
}
if (result) {
result = pixelRgba(
renderer,
xp,
yc2 - yp,
r,
g,
b,
a,
blendMode: blendMode,
);
}
if (result) {
result = pixelRgba(
renderer,
xc2 - xp,
yc2 - yp,
r,
g,
b,
a,
blendMode: blendMode,
);
}
for (i = 1; i <= dxt; i++) {
xp--;
d += t - b2;
if (d >= 0) {
ys = yp - 1;
} else if ((d - s - a2) > 0) {
if ((2 * d - s - a2) >= 0) {
ys = yp + 1;
} else {
ys = yp;
yp++;
d -= s + a2;
s += ds;
}
} else {
yp++;
ys = yp + 1;
d -= s + a2;
s += ds;
}
t -= dt;
/* Calculate alpha */
if (s != 0) {
cp = d.abs() / s.abs();
if (cp > 1.0) {
cp = 1.0;
}
} else {
cp = 1.0;
}
/* Calculate weights */
weight = (cp * 255).toInt();
iweight = 255 - weight;
/* Upper half */
xx = xc2 - xp;
if (result) {
result = pixelRgbaWeight(
renderer,
xp,
yp,
r,
g,
b,
a,
iweight,
blendMode: blendMode,
);
}
if (result) {
result = pixelRgbaWeight(
renderer,
xx,
yp,
r,
g,
b,
a,
iweight,
blendMode: blendMode,
);
}
if (result) {
result = pixelRgbaWeight(
renderer,
xp,
ys,
r,
g,
b,
a,
weight,
blendMode: blendMode,
);
}
if (result) {
result = pixelRgbaWeight(
renderer,
xx,
ys,
r,
g,
b,
a,
weight,
blendMode: blendMode,
);
}
/* Lower half */
yy = yc2 - yp;
if (result) {
result = pixelRgbaWeight(
renderer,
xp,
yy,
r,
g,
b,
a,
iweight,
blendMode: blendMode,
);
}
if (result) {
result = pixelRgbaWeight(
renderer,
xx,
yy,
r,
g,
b,
a,
iweight,
blendMode: blendMode,
);
}
yy = yc2 - ys;
if (result) {
result = pixelRgbaWeight(
renderer,
xp,
yy,
r,
g,
b,
a,
weight,
blendMode: blendMode,
);
}
if (result) {
result = pixelRgbaWeight(
renderer,
xx,
yy,
r,
g,
b,
a,
weight,
blendMode: blendMode,
);
}
}
/* Replaces original approximation code dyt = abs(yp - yc); */
dyt = b2 ~/ sab + od;
for (i = 1; i <= dyt; i++) {
yp++;
d -= s + a2;
if (d <= 0) {
xs = xp + 1;
} else if ((d + t - b2) < 0) {
if ((2 * d + t - b2) <= 0) {
xs = xp - 1;
} else {
xs = xp;
xp--;
d += t - b2;
t -= dt;
}
} else {
xp--;
xs = xp - 1;
d += t - b2;
t -= dt;
}
s += ds;
/* Calculate alpha */
if (t != 0) {
cp = d.abs() / t.abs();
if (cp > 1.0) {
cp = 1.0;
}
} else {
cp = 1.0;
}
/* Calculate weight */
weight = (cp * 255).toInt();
iweight = 255 - weight;
/* Left half */
xx = xc2 - xp;
yy = yc2 - yp;
if (result) {
result = pixelRgbaWeight(
renderer,
xp,
yp,
r,
g,
b,
a,
iweight,
blendMode: blendMode,
);
}
if (result) {
result = pixelRgbaWeight(
renderer,
xx,
yp,
r,
g,
b,
a,
iweight,
blendMode: blendMode,
);
}
if (result) {
result = pixelRgbaWeight(
renderer,
xp,
yy,
r,
g,
b,
a,
iweight,
blendMode: blendMode,
);
}
if (result) {
result = pixelRgbaWeight(
renderer,
xx,
yy,
r,
g,
b,
a,
iweight,
blendMode: blendMode,
);
}
/* Right half */
xx = xc2 - xs;
if (result) {
result = pixelRgbaWeight(
renderer,
xs,
yp,
r,
g,
b,
a,
weight,
blendMode: blendMode,
);
}
if (result) {
result = pixelRgbaWeight(
renderer,
xx,
yp,
r,
g,
b,
a,
weight,
blendMode: blendMode,
);
}
if (result) {
result = pixelRgbaWeight(
renderer,
xs,
yy,
r,
g,
b,
a,
weight,
blendMode: blendMode,
);
}
if (result) {
result = pixelRgbaWeight(
renderer,
xx,
yy,
r,
g,
b,
a,
weight,
blendMode: blendMode,
);
}
}
return result;
}