mirror of
git://projects.qi-hardware.com/ben-blinkenlights.git
synced 2024-11-16 17:22:29 +02:00
ubb-la/gui.c: use powers of two for zoom and integer arithmetic (WIP)
This looks better and avoids the risk of math issues.
This commit is contained in:
parent
94e099eebc
commit
1b0a2cff51
111
ubb-la/gui.c
111
ubb-la/gui.c
@ -30,7 +30,7 @@
|
||||
#define CH_SKIP 16
|
||||
#define CH_HEIGHT 8
|
||||
|
||||
#define MAX_ZOOM 8
|
||||
#define MAX_ZOOM 3
|
||||
|
||||
|
||||
static SDL_Surface *surf;
|
||||
@ -77,34 +77,61 @@ static void change(int x, int ch)
|
||||
}
|
||||
|
||||
|
||||
static void level(int x, int ch, int v)
|
||||
static void level(int x0, int x1, int ch, int v)
|
||||
{
|
||||
pixelColor(surf, x, ch_y(ch, v), LEVEL_RGBA);
|
||||
if (x0 == x1)
|
||||
pixelColor(surf, x0, ch_y(ch, v), LEVEL_RGBA);
|
||||
else
|
||||
hlineColor(surf, x0, x1, ch_y(ch, v), LEVEL_RGBA);
|
||||
}
|
||||
|
||||
|
||||
static void show_buffer(const uint8_t *buf, int skip, int nibbles,
|
||||
static void show_buffer_zoom_in(const uint8_t *buf, int skip, int nibbles,
|
||||
int x0, int x1)
|
||||
{
|
||||
double f = (nibbles-skip)/(x1-x0+1.0);
|
||||
int f = (x1-x0)/(nibbles-skip);
|
||||
int x, i, j;
|
||||
int last[4] = { -1, -1, -1, -1};
|
||||
uint8_t v, bit;
|
||||
|
||||
fprintf(stderr, "in: %d-%d (%d) Sa %d-%d (%d) pix %d f (%d)\n",
|
||||
skip, nibbles, nibbles-skip, x0, x1, x1-x0, f, f*(nibbles-skip));
|
||||
x = x0;
|
||||
for (i = skip; i != nibbles; i++) {
|
||||
v = (buf[i >> 1] >> 4*(~i & 1)) & 0xf;
|
||||
for (j = 0; j != 4; j++) {
|
||||
bit = (v >> j) & 1;
|
||||
if (bit == last[j] || last[j] == -1) {
|
||||
level(x, x+f-1, j, bit);
|
||||
} else {
|
||||
change(x, j);
|
||||
level(x+1, x+f-1, j, bit);
|
||||
}
|
||||
last[j] = bit;
|
||||
}
|
||||
x += f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void show_buffer_zoom_out(const uint8_t *buf, int skip, int nibbles,
|
||||
int x0, int x1)
|
||||
{
|
||||
int f = (nibbles-skip)/(x1-x0);
|
||||
int x;
|
||||
int i = skip-1, n, j;
|
||||
int i = skip, n, j;
|
||||
int changes[4], last[4] = { -1, -1, -1, -1}, next[4];
|
||||
uint8_t v, bit;
|
||||
|
||||
for (x = x0; x != x1+1; x++) {
|
||||
n = (x-x0)*f+skip;
|
||||
if (i == n) {
|
||||
for (j = 0; j != 4; j++)
|
||||
level(x, j, last[j]);
|
||||
continue;
|
||||
}
|
||||
fprintf(stderr, "out: %d-%d (%d) Sa %d-%d (%d) pix %d f (%d)\n",
|
||||
skip, nibbles, nibbles-skip, x0, x1, x1-x0, f, f*(x1-x0));
|
||||
for (x = x0; x != x1; x++) {
|
||||
n = i+f;
|
||||
for (j = 0; j != 4; j++) {
|
||||
next[j] = last[j];
|
||||
changes[j] = 0;
|
||||
}
|
||||
while (i != n) {
|
||||
i++;
|
||||
v = (buf[i >> 1] >> 4*(~i & 1)) & 0xf;
|
||||
for (j = 0; j != 4; j++) {
|
||||
bit = (v >> j) & 1;
|
||||
@ -113,12 +140,13 @@ static void show_buffer(const uint8_t *buf, int skip, int nibbles,
|
||||
next[j] = bit;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
for (j = 0; j != 4; j++) {
|
||||
if (changes[j] > 1)
|
||||
bounce(x, j);
|
||||
else if (!changes[j] || last[j] == -1)
|
||||
level(x, j, next[j]);
|
||||
level(x, x, j, next[j]);
|
||||
else
|
||||
change(x, j);
|
||||
last[j] = next[j];
|
||||
@ -127,6 +155,45 @@ static void show_buffer(const uint8_t *buf, int skip, int nibbles,
|
||||
}
|
||||
|
||||
|
||||
static void show_buffer(const uint8_t *buf, int skip, int nibbles,
|
||||
int x0, int x1, int zoom, int pos)
|
||||
{
|
||||
int xm, w, p0, p1;
|
||||
int d;
|
||||
|
||||
xm = (x0+x1) >> 1;
|
||||
if (zoom < 0) {
|
||||
w = (nibbles-skip) >> -zoom;
|
||||
p0 = xm-(w >> 1);
|
||||
p1 = xm+((w+1) >> 1);
|
||||
if (p0 < x0) {
|
||||
skip += (x0-p0) << -zoom;
|
||||
p0 = x0;
|
||||
}
|
||||
if (p1 > x1) {
|
||||
nibbles -= (p1-x1) << -zoom;
|
||||
p1 = x1;
|
||||
}
|
||||
show_buffer_zoom_out(buf, skip, nibbles, p0, p1);
|
||||
} else {
|
||||
w = (nibbles-skip) << zoom;
|
||||
p0 = xm-(w >> 1);
|
||||
p1 = xm+((w+1) >> 1);
|
||||
if (p0 < x0) {
|
||||
d = ((x0-p0)+(1 << zoom)-1) >> zoom;
|
||||
skip += d;
|
||||
p0 += d << zoom;
|
||||
}
|
||||
if (p1 > x1) {
|
||||
d = ((p1-x1)+(1 << zoom)-1) >> zoom;
|
||||
nibbles -= d;
|
||||
p1 -= d << zoom;
|
||||
}
|
||||
show_buffer_zoom_in(buf, skip, nibbles, p0, p1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void update(void)
|
||||
{
|
||||
SDL_UnlockSurface(surf);
|
||||
@ -137,14 +204,16 @@ static void update(void)
|
||||
void gui(const uint8_t *buf, int skip, int nibbles)
|
||||
{
|
||||
SDL_Event event;
|
||||
int zoom = 0;
|
||||
int m, w;
|
||||
int pos = (skip+nibbles) >> 1;
|
||||
int zoom; /* < 0: zoom out; 0: 1 pixel = 1 sample; > 1: zoom in */
|
||||
int min_zoom = 0;
|
||||
|
||||
while (XRES-CH_XOFF < (nibbles-skip) >> -min_zoom)
|
||||
min_zoom--;
|
||||
zoom = min_zoom;
|
||||
while (1) {
|
||||
m = (nibbles-skip) >> 1;
|
||||
w = (nibbles-skip) >> zoom;
|
||||
clear();
|
||||
show_buffer(buf, m-(w >> 1), m+(w >> 1), CH_XOFF, XRES-1);
|
||||
show_buffer(buf, skip, nibbles, CH_XOFF, XRES, zoom, pos);
|
||||
update();
|
||||
|
||||
do {
|
||||
@ -157,7 +226,7 @@ void gui(const uint8_t *buf, int skip, int nibbles)
|
||||
zoom++;
|
||||
break;
|
||||
case SDLK_DOWN:
|
||||
if (zoom)
|
||||
if (zoom > min_zoom)
|
||||
zoom--;
|
||||
break;
|
||||
case SDLK_RETURN:
|
||||
|
Loading…
Reference in New Issue
Block a user