diff --git a/src/cacademo.c b/src/cacademo.c index 6754d5a..4564d4a 100644 --- a/src/cacademo.c +++ b/src/cacademo.c @@ -1,6 +1,7 @@ /* * cacademo various demo effects for libcaca * Copyright (c) 1998 Michele Bini + * 2003-2004 Jean-Yves Lamoureux * 2004 Sam Hocevar * All Rights Reserved * @@ -17,6 +18,7 @@ #if !defined(__KERNEL__) # include +# include # include # include # ifndef M_PI @@ -27,105 +29,53 @@ #include "cucul.h" #include "caca.h" -/* Virtual buffer size for dither-based demos */ -#define XSIZ 256 -#define YSIZ 256 -static unsigned char screen[XSIZ * YSIZ]; - -/* The plasma effect */ -#define TABLEX (XSIZ * 2) -#define TABLEY (YSIZ * 2) - -static unsigned char table[TABLEX * TABLEY]; - -static int main_plasma(int, char **); -static void do_plasma(unsigned char *, - double, double, double, double, double, double); +enum action { INIT, UPDATE, DRAW, FREE }; -/* The metaball effect */ -#define METASIZE 128 -#define METABALLS 12 -#define CROPBALL 200 /* Colour index where to crop balls */ - -static int main_ball(int, char **); -static void create_ball(void); -static void draw_ball(unsigned int, unsigned int); +void plasma(enum action, cucul_canvas_t *); +void metaballs(enum action, cucul_canvas_t *); +void moire(enum action, cucul_canvas_t *); -static unsigned char metaball[METASIZE * METASIZE]; - -/* The moiré effect */ -#define DISCSIZ 512 -#define DISCTHICKNESS 96 +void (*demo_list[])(enum action, cucul_canvas_t *) = +{ + plasma, + metaballs, + moire, +}; -static unsigned char disc[DISCSIZ * DISCSIZ]; +/* Common macros for dither-based demos */ +#define XSIZ 256 +#define YSIZ 256 -static int main_moir(int, char **); -static void put_disc(int, int); -static void draw_disc(int, char); -static void draw_line(int, int, char); +/* Global variables */ +static int frame = 0; int main(int argc, char **argv) { - switch(cucul_rand(0, 3)) - { - case 0: - return main_plasma(argc, argv); - case 1: - return main_ball(argc, argv); - case 2: - return main_moir(argc, argv); - } + static caca_display_t *dp; + static cucul_canvas_t *frontcv, *backcv, *mask; + int demo = 0, pause = 0; - return -1; -} + /* Set up two canvases, a mask, and attach a display to the front one */ + frontcv = cucul_create_canvas(0, 0); + backcv = cucul_create_canvas(0, 0); + mask = cucul_create_canvas(0, 0); -static int main_plasma(int argc, char **argv) -{ - cucul_canvas_t *cv, *c2, *mask; caca_display_t *dp; - unsigned int red[256], green[256], blue[256], alpha[256]; - double r[3], R[6]; - cucul_dither_t *dither; - int i, x, y, frame = 0, pause = 0; - - cv = cucul_create_canvas(0, 0); - if(!cv) - return 1; - dp = caca_create_display(cv); + dp = caca_create_display(frontcv); if(!dp) return 1; - caca_set_display_time(dp, 20000); - - c2 = cucul_create_canvas(cucul_get_canvas_width(cv), - cucul_get_canvas_height(cv)); - mask = cucul_create_canvas(cucul_get_canvas_width(cv), - cucul_get_canvas_height(cv)); - - /* Fill various tables */ - for(i = 0 ; i < 256; i++) - red[i] = green[i] = blue[i] = alpha[i] = 0; - - for(i = 0; i < 3; i++) - r[i] = (double)(cucul_rand(1, 1000)) / 60000 * M_PI; + cucul_set_canvas_size(backcv, cucul_get_canvas_width(frontcv), + cucul_get_canvas_height(frontcv)); + cucul_set_canvas_size(mask, cucul_get_canvas_width(frontcv), + cucul_get_canvas_height(frontcv)); - for(i = 0; i < 6; i++) - R[i] = (double)(cucul_rand(1, 1000)) / 10000; - - for(y = 0 ; y < TABLEY ; y++) - for(x = 0 ; x < TABLEX ; x++) - { - double tmp = (((double)((x - (TABLEX / 2)) * (x - (TABLEX / 2)) - + (y - (TABLEX / 2)) * (y - (TABLEX / 2)))) - * (M_PI / (TABLEX * TABLEX + TABLEY * TABLEY))); + caca_set_display_time(dp, 20000); - table[x + y * TABLEX] = (1.0 + sin(12.0 * sqrt(tmp))) * 256 / 6; - } + demo = cucul_rand(0, 3); - /* Create a libcucul dither */ - dither = cucul_create_dither(8, XSIZ, YSIZ, XSIZ, 0, 0, 0, 0); + demo_list[demo](INIT, NULL); - /* Main loop */ - for(;;) + for(;;) { caca_event_t ev; if(caca_get_event(dp, CACA_EVENT_KEY_PRESS, &ev, 0)) @@ -140,6 +90,74 @@ static int main_plasma(int argc, char **argv) if(pause) goto paused; + demo_list[demo](UPDATE, NULL); + frame++; +paused: + demo_list[demo](DRAW, frontcv); + cucul_set_color(frontcv, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLUE); + cucul_putstr(frontcv, cucul_get_canvas_width(frontcv) - 30, + cucul_get_canvas_height(frontcv) - 2, + " -=[ Powered by libcaca ]=- "); + caca_refresh_display(dp); + } +end: + demo_list[demo](FREE, NULL); + + caca_free_display(dp); + cucul_free_canvas(mask); + cucul_free_canvas(backcv); + cucul_free_canvas(frontcv); + + return 0; +} + +/* The plasma effect */ +#define TABLEX (XSIZ * 2) +#define TABLEY (YSIZ * 2) +static uint8_t table[TABLEX * TABLEY]; + +static void do_plasma(uint8_t *, + double, double, double, double, double, double); + +void plasma(enum action action, cucul_canvas_t *cv) +{ + static cucul_dither_t *dither; + static uint8_t *screen; + static unsigned int red[256], green[256], blue[256], alpha[256]; + static double r[3], R[6]; + + int i, x, y; + + switch(action) + { + case INIT: + screen = malloc(XSIZ * YSIZ * sizeof(uint8_t)); + + /* Fill various tables */ + for(i = 0 ; i < 256; i++) + red[i] = green[i] = blue[i] = alpha[i] = 0; + + for(i = 0; i < 3; i++) + r[i] = (double)(cucul_rand(1, 1000)) / 60000 * M_PI; + + for(i = 0; i < 6; i++) + R[i] = (double)(cucul_rand(1, 1000)) / 10000; + + for(y = 0 ; y < TABLEY ; y++) + for(x = 0 ; x < TABLEX ; x++) + { + double tmp = (((double)((x - (TABLEX / 2)) * (x - (TABLEX / 2)) + + (y - (TABLEX / 2)) * (y - (TABLEX / 2)))) + * (M_PI / (TABLEX * TABLEX + TABLEY * TABLEY))); + + table[x + y * TABLEX] = (1.0 + sin(12.0 * sqrt(tmp))) * 256 / 6; + } + + /* Create a libcucul dither */ + dither = cucul_create_dither(8, XSIZ, YSIZ, XSIZ, 0, 0, 0, 0); + break; + + case UPDATE: for(i = 0 ; i < 256; i++) { double z = ((double)i) / 256 * 6 * M_PI; @@ -159,36 +177,21 @@ static int main_plasma(int argc, char **argv) (1.0 + sin(((double)frame) * R[3])) / 2, (1.0 + sin(((double)frame) * R[4])) / 2, (1.0 + sin(((double)frame) * R[5])) / 2); - frame++; - -paused: + break; + case DRAW: cucul_dither_bitmap(cv, 0, 0, cucul_get_canvas_width(cv), cucul_get_canvas_height(cv), dither, screen); - - cucul_blit(c2, 0, 0, cv, NULL); - cucul_invert(c2); - - - cucul_blit(cv, 0, 0, c2, mask); - - cucul_set_color(cv, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLUE); - cucul_putstr(cv, cucul_get_canvas_width(cv) - 30, - cucul_get_canvas_height(cv) - 2, - " -=[ Powered by libcaca ]=- "); - caca_refresh_display(dp); + break; + case FREE: + free(screen); + cucul_free_dither(dither); + break; } - -end: - cucul_free_dither(dither); - caca_free_display(dp); - cucul_free_canvas(cv); - - return 0; } -static void do_plasma(unsigned char *pixels, double x_1, double y_1, +static void do_plasma(uint8_t *pixels, double x_1, double y_1, double x_2, double y_2, double x_3, double y_3) { unsigned int X1 = x_1 * (TABLEX / 2), @@ -198,91 +201,80 @@ static void do_plasma(unsigned char *pixels, double x_1, double y_1, X3 = x_3 * (TABLEX / 2), Y3 = y_3 * (TABLEY / 2); unsigned int y; - unsigned char * t1 = table + X1 + Y1 * TABLEX, - * t2 = table + X2 + Y2 * TABLEX, - * t3 = table + X3 + Y3 * TABLEX; + uint8_t * t1 = table + X1 + Y1 * TABLEX, + * t2 = table + X2 + Y2 * TABLEX, + * t3 = table + X3 + Y3 * TABLEX; for(y = 0; y < YSIZ; y++) { unsigned int x; - unsigned char * tmp = pixels + y * YSIZ; + uint8_t * tmp = pixels + y * YSIZ; unsigned int ty = y * TABLEX, tmax = ty + XSIZ; for(x = 0; ty < tmax; ty++, tmp++) tmp[0] = t1[ty] + t2[ty] + t3[ty]; } } -static int main_ball(int argc, char **argv) -{ - cucul_canvas_t *cv; caca_display_t *dp; - unsigned int r[256], g[256], b[256], a[256]; - float dd[METABALLS], di[METABALLS], dj[METABALLS], dk[METABALLS]; - unsigned int x[METABALLS], y[METABALLS]; - cucul_dither_t *cucul_dither; - float i = 10.0, j = 17.0, k = 11.0; - int p, frame = 0, pause = 0; - double frameOffset[360 + 80]; - - cv = cucul_create_canvas(0, 0); - if(!cv) - return 1; - dp = caca_create_display(cv); - if(!dp) - return 1; - - caca_set_display_time(dp, 20000); +/* The metaball effect */ +#define METASIZE (XSIZ/2) +#define METABALLS 12 +#define CROPBALL 200 /* Colour index where to crop balls */ +static uint8_t metaball[METASIZE * METASIZE]; - /* Make the palette eatable by libcaca */ - for(p = 0; p < 256; p++) - r[p] = g[p] = b[p] = a[p] = 0x0; - r[255] = g[255] = b[255] = 0xfff; +static void create_ball(void); +static void draw_ball(uint8_t *, unsigned int, unsigned int); - /* Create a libcucul dither smaller than our pixel buffer, so that we - * display only the interesting part of it */ - cucul_dither = cucul_create_dither(8, XSIZ - METASIZE, YSIZ - METASIZE, - XSIZ, 0, 0, 0, 0); +void metaballs(enum action action, cucul_canvas_t *cv) +{ + static cucul_dither_t *cucul_dither; + static uint8_t *screen; + static unsigned int r[256], g[256], b[256], a[256]; + static float dd[METABALLS], di[METABALLS], dj[METABALLS], dk[METABALLS]; + static unsigned int x[METABALLS], y[METABALLS]; + static float i = 10.0, j = 17.0, k = 11.0; + static double offset[360 + 80]; - /* Generate ball sprite */ - create_ball(); + int p, angle; - for(p = 0; p < METABALLS; p++) + switch(action) { - dd[p] = cucul_rand(0, 100); - di[p] = (float)cucul_rand(500, 4000) / 6000.0; - dj[p] = (float)cucul_rand(500, 4000) / 6000.0; - dk[p] = (float)cucul_rand(500, 4000) / 6000.0; - } + case INIT: + screen = malloc(XSIZ * YSIZ * sizeof(uint8_t)); - for(frame = 0; frame < 360 + 80; frame++) - frameOffset[frame] = 1.0 + sin((double)(frame * M_PI / 60)); + /* Make the palette eatable by libcaca */ + for(p = 0; p < 256; p++) + r[p] = g[p] = b[p] = a[p] = 0x0; + r[255] = g[255] = b[255] = 0xfff; - /* Go ! */ - for(;;) - { - caca_event_t ev; - if(caca_get_event(dp, CACA_EVENT_KEY_PRESS, &ev, 0)) + /* Create a libcucul dither smaller than our pixel buffer, so that we + * display only the interesting part of it */ + cucul_dither = cucul_create_dither(8, XSIZ - METASIZE, YSIZ - METASIZE, + XSIZ, 0, 0, 0, 0); + /* Generate ball sprite */ + create_ball(); + + for(p = 0; p < METABALLS; p++) { - switch(ev.data.key.ch) - { - case CACA_KEY_ESCAPE: goto end; - case ' ': pause = !pause; - } + dd[p] = cucul_rand(0, 100); + di[p] = (float)cucul_rand(500, 4000) / 6000.0; + dj[p] = (float)cucul_rand(500, 4000) / 6000.0; + dk[p] = (float)cucul_rand(500, 4000) / 6000.0; } - if(pause) - goto paused; + for(p = 0; p < 360 + 80; p++) + offset[p] = 1.0 + sin((double)(p * M_PI / 60)); + break; - frame++; - if(frame >= 360) - frame = 0; + case UPDATE: + angle = frame % 360; /* Crop the palette */ for(p = CROPBALL; p < 255; p++) { int t1, t2, t3; - double c1 = frameOffset[frame]; - double c2 = frameOffset[frame+40]; - double c3 = frameOffset[frame+80]; + double c1 = offset[angle]; + double c2 = offset[angle + 40]; + double c3 = offset[angle + 80]; t1 = p < 0x40 ? 0 : p < 0xc0 ? (p - 0x40) * 0x20 : 0xfff; t2 = p < 0xe0 ? 0 : (p - 0xe0) * 0x80; @@ -316,29 +308,21 @@ static int main_ball(int argc, char **argv) /* Here is all the trick. Maybe if you're that * clever you'll understand. */ for(p = 0; p < METABALLS; p++) - draw_ball(x[p], y[p]); + draw_ball(screen, x[p], y[p]); + break; -paused: - /* Draw our virtual buffer to screen, letting libcucul resize it */ + case DRAW: cucul_dither_bitmap(cv, 0, 0, cucul_get_canvas_width(cv), cucul_get_canvas_height(cv), cucul_dither, screen + (METASIZE / 2) * (1 + XSIZ)); - cucul_set_color(cv, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLUE); - cucul_putstr(cv, cucul_get_canvas_width(cv) - 30, - cucul_get_canvas_height(cv) - 2, - " -=[ Powered by libcaca ]=- "); + break; - caca_refresh_display(dp); + case FREE: + free(screen); + cucul_free_dither(cucul_dither); + break; } - - /* End, bye folks */ -end: - cucul_free_dither(cucul_dither); - caca_free_display(dp); - cucul_free_canvas(cv); - - return 0; } /* Generate ball sprite @@ -359,7 +343,7 @@ static void create_ball(void) } /* You missed the trick ? */ -static void draw_ball(unsigned int bx, unsigned int by) +static void draw_ball(uint8_t *screen, unsigned int bx, unsigned int by) { unsigned int color; unsigned int i, e = 0; @@ -383,52 +367,44 @@ static void draw_ball(unsigned int bx, unsigned int by) } } -static int main_moir(int argc, char **argv) -{ - cucul_canvas_t *cv; caca_display_t *dp; - unsigned int red[256], green[256], blue[256], alpha[256]; - cucul_dither_t *dither; - int i, x, y, frame = 0, pause = 0; +/* The moiré effect */ +#define DISCSIZ (XSIZ*2) +#define DISCTHICKNESS (XSIZ*15/40) +static uint8_t disc[DISCSIZ * DISCSIZ]; - cv = cucul_create_canvas(0, 0); - if(!cv) - return 1; - dp = caca_create_display(cv); - if(!dp) - return 1; +static void put_disc(uint8_t *, int, int); +static void draw_disc(int, char); +static void draw_line(int, int, char); - caca_set_display_time(dp, 20000); +void moire(enum action action, cucul_canvas_t *cv) +{ + static cucul_dither_t *dither; + static uint8_t *screen; + static unsigned int red[256], green[256], blue[256], alpha[256]; - /* Fill various tables */ - for(i = 0 ; i < 256; i++) - red[i] = green[i] = blue[i] = alpha[i] = 0; + int i, x, y; - red[0] = green[0] = blue[0] = 0x777; - red[1] = green[1] = blue[1] = 0xfff; + switch(action) + { + case INIT: + screen = malloc(XSIZ * YSIZ * sizeof(uint8_t)); - /* Fill the circle */ - for(i = DISCSIZ * 2; i > 0; i -= DISCTHICKNESS) - draw_disc(i, (i / DISCTHICKNESS) % 2); + /* Fill various tables */ + for(i = 0 ; i < 256; i++) + red[i] = green[i] = blue[i] = alpha[i] = 0; - /* Create a libcucul dither */ - dither = cucul_create_dither(8, XSIZ, YSIZ, XSIZ, 0, 0, 0, 0); + red[0] = green[0] = blue[0] = 0x777; + red[1] = green[1] = blue[1] = 0xfff; - /* Main loop */ - for(;;) - { - caca_event_t ev; - if(caca_get_event(dp, CACA_EVENT_KEY_PRESS, &ev, 0)) - { - switch(ev.data.key.ch) - { - case CACA_KEY_ESCAPE: goto end; - case ' ': pause = !pause; - } - } + /* Fill the circle */ + for(i = DISCSIZ * 2; i > 0; i -= DISCTHICKNESS) + draw_disc(i, (i / DISCTHICKNESS) % 2); - if(pause) - goto paused; + /* Create a libcucul dither */ + dither = cucul_create_dither(8, XSIZ, YSIZ, XSIZ, 0, 0, 0, 0); + break; + case UPDATE: memset(screen, 0, XSIZ * YSIZ); /* Set the palette */ @@ -445,35 +421,28 @@ static int main_moir(int argc, char **argv) /* Draw circles */ x = cos(0.07 * frame + 5.0) * 128.0 + (XSIZ / 2); y = sin(0.11 * frame) * 128.0 + (YSIZ / 2); - put_disc(x, y); + put_disc(screen, x, y); x = cos(0.13 * frame + 2.0) * 64.0 + (XSIZ / 2); y = sin(0.09 * frame + 1.0) * 64.0 + (YSIZ / 2); - put_disc(x, y); - - frame++; + put_disc(screen, x, y); + break; -paused: + case DRAW: cucul_dither_bitmap(cv, 0, 0, cucul_get_canvas_width(cv), cucul_get_canvas_height(cv), dither, screen); - cucul_set_color(cv, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLUE); - cucul_putstr(cv, cucul_get_canvas_width(cv) - 30, - cucul_get_canvas_height(cv) - 2, - " -=[ Powered by libcaca ]=- "); - caca_refresh_display(dp); - } - -end: - cucul_free_dither(dither); - caca_free_display(dp); - cucul_free_canvas(cv); + break; - return 0; + case FREE: + free(screen); + cucul_free_dither(dither); + break; + } } -static void put_disc(int x, int y) +static void put_disc(uint8_t *screen, int x, int y) { char *src = ((char*)disc) + (DISCSIZ / 2 - x) + (DISCSIZ / 2 - y) * DISCSIZ; int i, j;