TFT_eSPI/examples/Anti-aliased/Anti-aliased_Clock_v3/AA_functions.ino

186 lines
4.2 KiB
C++

// Anti-aliased functions - for test purposes only
// TODO: optimise and incorporate in TFT_eSPI
// Support
#define iround(X) ((uint16_t)(((float)(X))+0.5))
// Alphablend specified color with sprite background pixel and plot in sprite at x,y
void plotPixel(int16_t x, int16_t y, uint16_t color, float alpha) {
if (alpha > 0.996) { face.drawPixel(x, y, color); return; }
alpha = alpha * ALPHA_GAIN;
// Clip alpha
if (alpha > 255) alpha = 255;
//Blend color with background and plot
face.drawPixel(x, y, face.alphaBlend((uint8_t)alpha, color, face.readPixel(x, y)));
}
// AA circle outline
void drawCircleAA( int16_t x, int16_t y, int16_t radius, uint16_t color ) {
drawRoundRectangleAntialiased(x - radius, y - radius, radius << 1, radius << 1, radius, radius, color);
}
// AA filled circle
void fillCircleAA( int16_t x, int16_t y, int16_t radius, uint16_t color ) {
drawRoundRectangleAntialiased(x - radius, y - radius, radius << 1, radius << 1, radius, radius, color);
face.fillCircle(x, y, radius, color);
}
// AA circle and rounded rectangle support
void drawRoundRectangleAntialiased(int16_t x, int16_t y, int16_t width, int16_t height, int16_t rx, int16_t ry, uint16_t color) {
int16_t i;
int32_t a2, b2, ds, dt, dxt, t, s, d;
int16_t xp, yp, xs, ys, dyt, od, xx, yy, xc2, yc2;
float cp;
float sab;
float weight, iweight;
if ((rx < 0) || (ry < 0)) {
return;
}
// Temporary - should really draw a box if corner radius is zero...
if (rx == 0) {
face.drawFastVLine(x, y - ry, y + ry, color);
return;
}
if (ry == 0) {
face.drawFastHLine(x - rx, y, x + rx, color);
return;
}
a2 = rx * rx;
b2 = ry * ry;
ds = a2 << 1;
dt = b2 << 1;
xc2 = x << 1;
yc2 = y << 1;
sab = sqrt((float)(a2 + b2));
od = (int)iround(sab * 0.01) + 1;
dxt = (int)iround((float)a2 / sab) + od;
t = 0;
s = -2 * a2 * ry;
d = 0;
xp = x + rx;
yp = y;
// Sides - may need to reduce color brightness to visually match anti-aliased corners
face.drawFastHLine(x + rx, y + height, 2 * rx - width + 1, color);
face.drawFastHLine(x + rx, y, 2 * rx - width + 1, color);
face.drawFastVLine(x + width, y + ry, 2 * ry - height + 1, color);
face.drawFastVLine(x, y + ry, 2 * ry - height + 1, color);
for (i = 1; i <= dxt; i++) {
xp--;
d += t - b2;
if (d >= 0) {
ys = yp - 1;
} else if ((d - s - a2) > 0) {
if (((d << 1) - 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;
if (s != 0) {
cp = (float) abs(d) / (float) abs(s);
if (cp > 1.0) {
cp = 1.0f;
}
} else {
cp = 1.0f;
}
weight = cp;
iweight = 1 - weight;
xx = xc2 - xp;
plotPixel(xp, yp, color, iweight);
plotPixel(xx + width, yp, color, iweight);
plotPixel(xp, ys, color, weight);
plotPixel(xx + width, ys, color, weight);
yy = yc2 - yp;
plotPixel(xp, yy + height, color, iweight);
plotPixel(xx + width, yy + height, color, iweight);
yy = yc2 - ys;
plotPixel(xp, yy + height, color, weight);
plotPixel(xx + width, yy + height, color, weight);
}
dyt = (int)iround((float)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 (((d << 1) + 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;
if (t != 0) {
cp = (float) abs(d) / (float) abs(t);
if (cp > 1.0) {
cp = 1.0f;
}
} else {
cp = 1.0f;
}
weight = cp;
iweight = 1 - weight;
xx = xc2 - xp;
yy = yc2 - yp;
plotPixel(xp, yp, color, iweight);
plotPixel(xx + width, yp, color, iweight);
plotPixel(xp, yy + height, color, iweight);
plotPixel(xx + width, yy + height, color, iweight);
xx = xc2 - xs;
plotPixel(xs, yp, color, weight);
plotPixel(xx + width, yp, color, weight);
plotPixel(xs, yy + height, color, weight);
plotPixel(xx + width, yy + height, color, weight);
}
}