framebuffer-ng: rework paintBoxRel and paintBoxFrame

rework similar to framebuffer.cpp in order to make sure the visual
appearance is identical
This commit is contained in:
Stefan Seyfried
2013-05-24 23:14:35 +02:00
parent 0c56de9801
commit 78620c257f

View File

@@ -86,6 +86,85 @@ inline unsigned int make16color(uint16_t r, uint16_t g, uint16_t b, uint16_t t,
return ((t << 24) & 0xFF000000) | ((r << 8) & 0xFF0000) | ((g << 0) & 0xFF00) | (b >> 8 & 0xFF);
}
/* this table contains the x coordinates for a quarter circle (the bottom right quarter) with fixed
radius of 540 px which is the half of the max HD graphics size of 1080 px. So with that table we
ca draw boxes with round corners and als circles by just setting dx = dy = radius (max 540). */
static const int q_circle[541] = {
540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540,
540, 540, 540, 540, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539,
539, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 537, 537, 537, 537, 537, 537, 537,
537, 537, 536, 536, 536, 536, 536, 536, 536, 536, 535, 535, 535, 535, 535, 535, 535, 535, 534, 534,
534, 534, 534, 534, 533, 533, 533, 533, 533, 533, 532, 532, 532, 532, 532, 532, 531, 531, 531, 531,
531, 531, 530, 530, 530, 530, 529, 529, 529, 529, 529, 529, 528, 528, 528, 528, 527, 527, 527, 527,
527, 526, 526, 526, 526, 525, 525, 525, 525, 524, 524, 524, 524, 523, 523, 523, 523, 522, 522, 522,
522, 521, 521, 521, 521, 520, 520, 520, 519, 519, 519, 518, 518, 518, 518, 517, 517, 517, 516, 516,
516, 515, 515, 515, 515, 514, 514, 514, 513, 513, 513, 512, 512, 512, 511, 511, 511, 510, 510, 510,
509, 509, 508, 508, 508, 507, 507, 507, 506, 506, 506, 505, 505, 504, 504, 504, 503, 503, 502, 502,
502, 501, 501, 500, 500, 499, 499, 499, 498, 498, 498, 497, 497, 496, 496, 496, 495, 495, 494, 494,
493, 493, 492, 492, 491, 491, 490, 490, 490, 489, 489, 488, 488, 487, 487, 486, 486, 485, 485, 484,
484, 483, 483, 482, 482, 481, 481, 480, 480, 479, 479, 478, 478, 477, 477, 476, 476, 475, 475, 474,
473, 473, 472, 472, 471, 471, 470, 470, 469, 468, 468, 467, 466, 466, 465, 465, 464, 464, 463, 462,
462, 461, 460, 460, 459, 459, 458, 458, 457, 456, 455, 455, 454, 454, 453, 452, 452, 451, 450, 450,
449, 449, 448, 447, 446, 446, 445, 445, 444, 443, 442, 441, 441, 440, 440, 439, 438, 437, 436, 436,
435, 435, 434, 433, 432, 431, 431, 430, 429, 428, 427, 427, 426, 425, 425, 424, 423, 422, 421, 421,
420, 419, 418, 417, 416, 416, 415, 414, 413, 412, 412, 411, 410, 409, 408, 407, 406, 405, 404, 403,
403, 402, 401, 400, 399, 398, 397, 397, 395, 394, 393, 393, 392, 391, 390, 389, 388, 387, 386, 385,
384, 383, 382, 381, 380, 379, 378, 377, 376, 375, 374, 373, 372, 371, 369, 368, 367, 367, 365, 364,
363, 362, 361, 360, 358, 357, 356, 355, 354, 353, 352, 351, 350, 348, 347, 346, 345, 343, 342, 341,
340, 339, 337, 336, 335, 334, 332, 331, 329, 328, 327, 326, 324, 323, 322, 321, 319, 317, 316, 315,
314, 312, 310, 309, 308, 307, 305, 303, 302, 301, 299, 297, 296, 294, 293, 291, 289, 288, 287, 285,
283, 281, 280, 278, 277, 275, 273, 271, 270, 268, 267, 265, 263, 261, 259, 258, 256, 254, 252, 250,
248, 246, 244, 242, 240, 238, 236, 234, 232, 230, 228, 225, 223, 221, 219, 217, 215, 212, 210, 207,
204, 202, 200, 197, 195, 192, 190, 187, 184, 181, 179, 176, 173, 170, 167, 164, 160, 157, 154, 150,
147, 144, 140, 136, 132, 128, 124, 120, 115, 111, 105, 101, 95, 89, 83, 77, 69, 61, 52, 40,
23};
static inline bool calcCorners(int *ofs, int *ofl, int *ofr, const int& dy, const int& line, const int& radius,
const bool& tl, const bool& tr, const bool& bl, const bool& br)
{
/* just a multiplicator for all math to reduce rounding errors */
#define MUL 32768
int scl, _ofs = 0;
bool ret = false;
if (ofl != NULL) *ofl = 0;
if (ofr != NULL) *ofr = 0;
int scf = 540 * MUL / radius;
/* one of the top corners */
if (line < radius && (tl || tr)) {
/* uper round corners */
scl = scf * (radius - line) / MUL;
if ((scf * (radius - line) % MUL) >= (MUL / 2)) /* round up */
scl++;
_ofs = radius - (q_circle[scl] * MUL / scf);
if (ofl != NULL && tl) *ofl = _ofs;
if (ofr != NULL && tr) *ofr = _ofs;
}
/* one of the bottom corners */
else if ((line >= dy - radius) && (bl || br)) {
/* lower round corners */
scl = scf * (radius - (dy - (line + 1))) / MUL;
if ((scf * (radius - (dy - (line + 1))) % MUL) >= (MUL / 2)) /* round up */
scl++;
_ofs = radius - (q_circle[scl] * MUL / scf);
if (ofl != NULL && bl) *ofl = _ofs;
if (ofr != NULL && br) *ofr = _ofs;
}
else
ret = true;
if (ofs != NULL) *ofs = _ofs;
return ret;
}
static inline int limitRadius(const int& dx, const int& dy, const int& radius)
{
int m = std::min(dx, dy);
if (radius > m)
return m;
if (radius > 540)
return 540;
return radius;
}
CFrameBuffer::CFrameBuffer()
: active ( true )
{
@@ -559,106 +638,49 @@ void CFrameBuffer::paletteSet(struct fb_cmap *map)
void CFrameBuffer::paintBoxRel(const int x, const int y, const int dx, const int dy, const fb_pixel_t col, int radius, int type)
{
/* draw a filled rectangle (with additional round corners) */
if (!getActive())
return;
/* draw a filled rectangle (with additional round corners) */
if (!getActive())
return;
int corner_tl = (type & CORNER_TOP_LEFT) ? 1 : 0;
int corner_tr = (type & CORNER_TOP_RIGHT) ? 1 : 0;
int corner_bl = (type & CORNER_BOTTOM_LEFT) ? 1 : 0;
int corner_br = (type & CORNER_BOTTOM_RIGHT) ? 1 : 0;
bool corner_tl = !!(type & CORNER_TOP_LEFT);
bool corner_tr = !!(type & CORNER_TOP_RIGHT);
bool corner_bl = !!(type & CORNER_BOTTOM_LEFT);
bool corner_br = !!(type & CORNER_BOTTOM_RIGHT);
/* this table contains the x coordinates for a quarter circle (the bottom right quarter) with fixed
radius of 540 px which is the half of the max HD graphics size of 1080 px. So with that table we
ca draw boxes with round corners and als circles by just setting dx = dy = radius (max 540). */
static const int q_circle[541] = {
540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540,
540, 540, 540, 540, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539,
539, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 537, 537, 537, 537, 537, 537, 537,
537, 537, 536, 536, 536, 536, 536, 536, 536, 536, 535, 535, 535, 535, 535, 535, 535, 535, 534, 534,
534, 534, 534, 534, 533, 533, 533, 533, 533, 533, 532, 532, 532, 532, 532, 532, 531, 531, 531, 531,
531, 531, 530, 530, 530, 530, 529, 529, 529, 529, 529, 529, 528, 528, 528, 528, 527, 527, 527, 527,
527, 526, 526, 526, 526, 525, 525, 525, 525, 524, 524, 524, 524, 523, 523, 523, 523, 522, 522, 522,
522, 521, 521, 521, 521, 520, 520, 520, 519, 519, 519, 518, 518, 518, 518, 517, 517, 517, 516, 516,
516, 515, 515, 515, 515, 514, 514, 514, 513, 513, 513, 512, 512, 512, 511, 511, 511, 510, 510, 510,
509, 509, 508, 508, 508, 507, 507, 507, 506, 506, 506, 505, 505, 504, 504, 504, 503, 503, 502, 502,
502, 501, 501, 500, 500, 499, 499, 499, 498, 498, 498, 497, 497, 496, 496, 496, 495, 495, 494, 494,
493, 493, 492, 492, 491, 491, 490, 490, 490, 489, 489, 488, 488, 487, 487, 486, 486, 485, 485, 484,
484, 483, 483, 482, 482, 481, 481, 480, 480, 479, 479, 478, 478, 477, 477, 476, 476, 475, 475, 474,
473, 473, 472, 472, 471, 471, 470, 470, 469, 468, 468, 467, 466, 466, 465, 465, 464, 464, 463, 462,
462, 461, 460, 460, 459, 459, 458, 458, 457, 456, 455, 455, 454, 454, 453, 452, 452, 451, 450, 450,
449, 449, 448, 447, 446, 446, 445, 445, 444, 443, 442, 441, 441, 440, 440, 439, 438, 437, 436, 436,
435, 435, 434, 433, 432, 431, 431, 430, 429, 428, 427, 427, 426, 425, 425, 424, 423, 422, 421, 421,
420, 419, 418, 417, 416, 416, 415, 414, 413, 412, 412, 411, 410, 409, 408, 407, 406, 405, 404, 403,
403, 402, 401, 400, 399, 398, 397, 397, 395, 394, 393, 393, 392, 391, 390, 389, 388, 387, 386, 385,
384, 383, 382, 381, 380, 379, 378, 377, 376, 375, 374, 373, 372, 371, 369, 368, 367, 367, 365, 364,
363, 362, 361, 360, 358, 357, 356, 355, 354, 353, 352, 351, 350, 348, 347, 346, 345, 343, 342, 341,
340, 339, 337, 336, 335, 334, 332, 331, 329, 328, 327, 326, 324, 323, 322, 321, 319, 317, 316, 315,
314, 312, 310, 309, 308, 307, 305, 303, 302, 301, 299, 297, 296, 294, 293, 291, 289, 288, 287, 285,
283, 281, 280, 278, 277, 275, 273, 271, 270, 268, 267, 265, 263, 261, 259, 258, 256, 254, 252, 250,
248, 246, 244, 242, 240, 238, 236, 234, 232, 230, 228, 225, 223, 221, 219, 217, 215, 212, 210, 207,
204, 202, 200, 197, 195, 192, 190, 187, 184, 181, 179, 176, 173, 170, 167, 164, 160, 157, 154, 150,
147, 144, 140, 136, 132, 128, 124, 120, 115, 111, 105, 101, 95, 89, 83, 77, 69, 61, 52, 40,
23};
checkFbArea(x, y, dx, dy, true);
int line = 0;
if ((type) && (radius))
{
#define MUL 32768 /* just an multiplicator for all math to reduce rounding errors */
int ofs, scf, scl, ofl, ofr;
if (!type || !radius)
{
accel->paintRect(x, y, dx, dy, col);
checkFbArea(x, y, dx, dy, false);
return;
}
/* limit the radius */
if (radius > dx)
radius = dx;
if (radius > dy)
radius = dy;
if (radius > 540)
radius = 540;
radius = limitRadius(dx, dy, radius);
if (radius < 1) /* dx or dy = 0... */
radius = 1; /* avoid div by zero below */
scf = (540 * MUL) / radius;
while (line < dy)
{
ofl = ofr = 0;
if (line < radius && (type & CORNER_TOP)) /* one of the top corners */
{
/* uper round corners */
scl = scf * (radius - line) / MUL;
if ((scf * (radius - line) % MUL) >= (MUL / 2)) /* round up */
scl++;
ofs = radius - (q_circle[scl] * MUL / scf);
// ofl = corner_tl * ofs; // might depend on the arch if multiply is faster or not
ofl = corner_tl ? ofs : 0;
ofr = corner_tr ? ofs : 0;
}
else if ((line >= dy - radius) && (type & CORNER_BOTTOM)) /* one of the bottom corners */
{
/* lower round corners */
scl = scf * (radius - (dy - (line + 1))) / MUL;
if ((scf * (radius - (dy - (line + 1))) % MUL) >= (MUL / 2)) /* round up */
scl++;
ofs = radius - (q_circle[scl] * MUL / scf);
ofl = corner_bl ? ofs : 0;
ofr = corner_br ? ofs : 0;
}
else
{
int height = dy - ((corner_tl|corner_tr) + (corner_bl|corner_br)) * radius;
accel->paintRect(x, y + line, dx, height, col);
line += height;
continue;
}
accel->paintLine(x + ofl, y + line, x + dx - ofr, y + line, col);
line++;
int line = 0;
while (line < dy) {
int ofl, ofr;
if (calcCorners(NULL, &ofl, &ofr, dy, line, radius,
corner_tl, corner_tr, corner_bl, corner_br))
{
int height = dy - ((corner_tl || corner_tr)?radius: 0 ) - ((corner_bl || corner_br) ? radius : 0);
accel->paintRect(x, y + line, dx, height, col);
line += height;
continue;
}
if (dx - ofr - ofl < 1) {
//printf("FB-NG::%s:%d x %d y %d dx %d dy %d l %d r %d\n", __func__, __LINE__, x,y,dx,dy, ofl, ofr);
line++;
continue;
}
accel->paintLine(x + ofl, y + line, x + dx - ofr, y + line, col);
line++;
}
}
else
{
accel->paintRect(x, y + line, dx, dy - line, col);
}
checkFbArea(x, y, dx, dy, false);
}
void CFrameBuffer::paintPixel(const int x, const int y, const fb_pixel_t col)
@@ -924,59 +946,64 @@ void CFrameBuffer::paintBoxFrame(const int sx, const int sy, const int dx, const
return;
int radius = rad;
int c_radius = rad << 1;
bool corner_tl = !!(type & CORNER_TOP_LEFT);
bool corner_tr = !!(type & CORNER_TOP_RIGHT);
bool corner_bl = !!(type & CORNER_BOTTOM_LEFT);
bool corner_br = !!(type & CORNER_BOTTOM_RIGHT);
paintBoxRel(sx + rad , sy , dx - c_radius, px, col); // upper horizontal
paintBoxRel(sx + rad , sy + dy - px, dx - c_radius, px, col); // lower horizontal
paintBoxRel(sx , sy + rad , px, dy - c_radius , col); // left vertical
paintBoxRel(sx + dx - px, sy + rad , px, dy - c_radius , col); // right vertical
int r_tl = 0, r_tr = 0, r_bl = 0, r_br = 0;
if (type && radius) {
int x_rad = radius - 1;
if (corner_tl) r_tl = x_rad;
if (corner_tr) r_tr = x_rad;
if (corner_bl) r_bl = x_rad;
if (corner_br) r_br = x_rad;
}
paintBoxRel(sx + r_tl, sy , dx - r_tl - r_tr, px, col); // top horizontal
paintBoxRel(sx + r_bl, sy + dy - px, dx - r_bl - r_br, px, col); // bottom horizontal
paintBoxRel(sx , sy + r_tl, px, dy - r_tl - r_bl, col); // left vertical
paintBoxRel(sx + dx - px, sy + r_tr, px, dy - r_tr - r_br, col); // right vertical
if (!radius)
{
if (!radius || !type)
return;
}
int x1 = sx + radius;
int y1 = sy + radius;
int x2 = sx + dx - radius -1;
int y2 = sy + dy - radius -1;
radius = limitRadius(dx, dy, radius);
if (radius < 1) /* dx or dy = 0... */
radius = 1; /* avoid div by zero below */
int line = 0;
while (line < dy) {
int ofs = 0, ofs_i = 0;
// inner box
if ((line >= px) && (line < (dy - px)))
calcCorners(&ofs_i, NULL, NULL, dy - 2 * px, line - px, radius - px,
corner_tl, corner_tr, corner_bl, corner_br);
// outer box
calcCorners(&ofs, NULL, NULL, dy, line, radius, corner_tl, corner_tr, corner_bl, corner_br);
int f = 1 - radius;
int ddF_x = 1;
int ddF_y = - c_radius;
int x = 0;
int y = radius;
while(x < y)
{
// ddF_x == 2 * x + 1;
// ddF_y == -2 * y;
// f == x*x + y*y - radius*radius + 2*x - y + 1;
if(f >= 0)
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
int width = 0;
while (width <= px)
{
paintPixel(x2 + x , y1 - y + width, col); // 1. oct
paintPixel(x2 + y - width, y1 - x , col); // 2. oct
paintPixel(x2 + y - width, y2 + x , col); // 3. oct
paintPixel(x2 + x , y2 + y - width, col); // 4. oct
paintPixel(x1 - x , y2 + y - width, col); // 5. oct
paintPixel(x1 - y + width, y2 + x , col); // 6. oct
paintPixel(x1 - y + width, y1 - x , col); // 7. oct
paintPixel(x1 - x , y1 - y + width, col); // 8. oct
width++;
int _y = sy + line;
if (line < px || line >= (dy - px)) {
// left
if ((corner_tl && line < radius) || (corner_bl && line >= dy - radius))
accel->paintLine(sx + ofs, _y, sx + ofs + radius, _y, col);
// right
if ((corner_tr && line < radius) || (corner_br && line >= dy - radius))
accel->paintLine(sx + dx - radius, _y, sx + dx - ofs, _y, col);
}
else if (line < (dy - px)) {
int _dx = (ofs_i - ofs) + px;
// left
if ((corner_tl && line < radius) || (corner_bl && line >= dy - radius))
accel->paintLine(sx + ofs, _y, sx + ofs + _dx, _y, col);
// right
if ((corner_tr && line < radius) || (corner_br && line >= dy - radius))
accel->paintLine(sx + dx - ofs_i - px, _y, sx + dx - ofs_i - px + _dx, _y, col);
}
if (line == radius && dy > 2 * radius)
// line outside the rounded corners
line = dy - radius;
else
line++;
}
}
void CFrameBuffer::useBackground(bool ub)