From 1b0a2cff51fe179afebd2fa954fa6223851629ad Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Wed, 30 Jan 2013 20:35:30 -0300 Subject: [PATCH] ubb-la/gui.c: use powers of two for zoom and integer arithmetic (WIP) This looks better and avoids the risk of math issues. --- ubb-la/gui.c | 111 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 90 insertions(+), 21 deletions(-) diff --git a/ubb-la/gui.c b/ubb-la/gui.c index c0482aa..5c7a7c2 100644 --- a/ubb-la/gui.c +++ b/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: