URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [mw/] [src/] [demos/] [nanox/] [erase.c] - Rev 1765
Compare with Previous | Blame | View Log
/* erase.c: Erase the screen in various more or less interesting ways. * (c) 1997 by Johannes Keukelaar <johannes@nada.kth.se> * Permission to use in any way granted. Provided "as is" without expressed * or implied warranty. NO WARRANTY, NO EXPRESSION OF SUITABILITY FOR ANY * PURPOSE. (I.e.: Use in any way, but at your own risk!) */ #include <stdio.h> //#include <unistd.h> #define usleep(x) #include <stdlib.h> #include <math.h> #define MWINCLUDECOLORS #include "nano-X.h" #include "maze.h" #undef countof #define countof(x) (sizeof(x)/sizeof(*(x))) typedef void (*Eraser) (int width, int height, int delay, int granularity); typedef int Bool; static void random_lines (int width, int height, int delay, int granularity) { Bool horiz_p = (random() & 1); int max = (horiz_p ? height : width); int *lines = (int *) calloc(max, sizeof(*lines)); int i; for (i = 0; i < max; i++) lines[i] = i; for (i = 0; i < max; i++) { int t, r; t = lines[i]; r = random() % max; lines[i] = lines[r]; lines[r] = t; } for (i = 0; i < max; i++) { if (horiz_p) GrLine (wid, erase_gc, 0, lines[i], width, lines[i]); else GrLine (wid, erase_gc, lines[i], 0, lines[i], height); wait_sync (); if (delay > 0 && ((i % granularity) == 0)) usleep (delay * granularity); } free(lines); } static void venetian (int width, int height, int delay, int granularity) { Bool horiz_p = (random() & 1); Bool flip_p = (random() & 1); int max = (horiz_p ? height : width); int *lines = (int *) calloc(max, sizeof(*lines)); int i, j; granularity /= 6; j = 0; for (i = 0; i < max*2; i++) { int line = ((i / 16) * 16) - ((i % 16) * 15); if (line >= 0 && line < max) lines[j++] = (flip_p ? max - line : line); } for (i = 0; i < max; i++) { if (horiz_p) GrLine (wid, erase_gc, 0, lines[i], width, lines[i]); else GrLine (wid, erase_gc, lines[i], 0, lines[i], height); wait_sync (); if (delay > 0 && ((i % granularity) == 0)) usleep (delay * granularity); } free(lines); } static void triple_wipe (int width, int height, int delay, int granularity) { Bool flip_x = random() & 1; Bool flip_y = random() & 1; int max = width + (height / 2); int *lines = (int *)calloc(max, sizeof(int)); int i; for(i = 0; i < width/2; i++) lines[i] = i*2+height; for(i = 0; i < height/2; i++) lines[i+width/2] = i*2; for(i = 0; i < width/2; i++) lines[i+width/2+height/2] = width-i*2-(width%2?0:1)+height; granularity /= 6; for (i = 0; i < max; i++) { int x, y, x2, y2; if (lines[i] < height) x = 0, y = lines[i], x2 = width, y2 = y; else x = lines[i]-height, y = 0, x2 = x, y2 = height; if (flip_x) x = width-x, x2 = width-x2; if (flip_y) y = height-y, y2 = height-y2; GrLine (wid, erase_gc, x, y, x2, y2); wait_sync (); if (delay > 0 && ((i % granularity) == 0)) usleep (delay*granularity); } free(lines); } static void quad_wipe (int width, int height, int delay, int granularity) { Bool flip_x = random() & 1; Bool flip_y = random() & 1; int max = width + height; int *lines = (int *)calloc(max, sizeof(int)); int i; granularity /= 3; for (i = 0; i < max/4; i++) { lines[i*4] = i*2; lines[i*4+1] = height-i*2-(height%2?0:1); lines[i*4+2] = height+i*2; lines[i*4+3] = height+width-i*2-(width%2?0:1); } for (i = 0; i < max; i++) { int x, y, x2, y2; if (lines[i] < height) x = 0, y = lines[i], x2 = width, y2 = y; else x = lines[i]-height, y = 0, x2 = x, y2 = height; if (flip_x) x = width-x, x2 = width-x2; if (flip_y) y = height-y, y2 = height-y2; GrLine (wid, erase_gc, x, y, x2, y2); wait_sync (); if (delay > 0 && ((i % granularity) == 0)) usleep (delay*granularity); } free(lines); } #if 0 static void circle_wipe (int width, int height, int delay, int granularity) { int full = 360 * 64; int inc = full / 64; int start = random() % full; int rad = (width > height ? width : height); int i; if (random() & 1) inc = -inc; for (i = (inc > 0 ? 0 : full); (inc > 0 ? i < full : i > 0); i += inc) { GrArc(wid, erase_gc, (width/2)-rad, (height/2)-rad, rad*2, rad*2, (i+start) % full, inc); usleep (delay*granularity); } } #endif #if 0 static void three_circle_wipe (int width, int height, int delay, int granularity) { int i; int full = 360 * 64; int q = full / 6; int q2 = q * 2; int inc = full / 240; int start = random() % q; int rad = (width > height ? width : height); for (i = 0; i < q; i += inc) { GrArc(wid, erase_gc, (width/2)-rad, (height/2)-rad, rad*2, rad*2, (start+i) % full, inc); GrArc(wid, erase_gc, (width/2)-rad, (height/2)-rad, rad*2, rad*2, (start-i) % full, -inc); GrArc(wid, erase_gc, (width/2)-rad, (height/2)-rad, rad*2, rad*2, (start+q2+i) % full, inc); GrArc(wid, erase_gc, (width/2)-rad, (height/2)-rad, rad*2, rad*2, (start+q2-i) % full, -inc); GrArc(wid, erase_gc, (width/2)-rad, (height/2)-rad, rad*2, rad*2, (start+q2+q2+i) % full, inc); GrArc(wid, erase_gc, (width/2)-rad, (height/2)-rad, rad*2, rad*2, (start+q2+q2-i) % full, -inc); wait_sync (); usleep (delay*granularity); } } #endif static void squaretate (int width, int height, int delay, int granularity) { int steps = (((width > height ? width : width) * 2) / granularity); int i; Bool flip = random() & 1; #define DRAW() \ if (flip) { \ points[0].x = width-points[0].x; \ points[1].x = width-points[1].x; \ points[2].x = width-points[2].x; } \ GrFillPoly (wid, erase_gc, 3, points) for (i = 0; i < steps; i++) { GR_POINT points [3]; points[0].x = 0; points[0].y = 0; points[1].x = width; points[1].y = 0; points[2].x = 0; points[2].y = points[0].y + ((i * height) / steps); DRAW(); points[0].x = 0; points[0].y = 0; points[1].x = 0; points[1].y = height; points[2].x = ((i * width) / steps); points[2].y = height; DRAW(); points[0].x = width; points[0].y = height; points[1].x = 0; points[1].y = height; points[2].x = width; points[2].y = height - ((i * height) / steps); DRAW(); points[0].x = width; points[0].y = height; points[1].x = width; points[1].y = 0; points[2].x = width - ((i * width) / steps); points[2].y = 0; DRAW(); wait_sync (); if (delay > 0) usleep (delay * granularity); } #undef DRAW } /* from Frederick Roeber <roeber@netscape.com> */ static void fizzle (int width, int height, int delay, int granularity) { /* These dimensions must be prime numbers. They should be roughly the square root of the width and height. */ # define BX 31 # define BY 31 # define SIZE (BX*BY) int array[SIZE]; int i, j; GR_POINT *skews; int nx, ny; /* Distribute the numbers [0,SIZE) randomly in the array */ { int indices[SIZE]; for( i = 0; i < SIZE; i++ ) { array[i] = -1; indices[i] = i; } for( i = 0; i < SIZE; i++ ) { j = random()%(SIZE-i); array[indices[j]] = i; indices[j] = indices[SIZE-i-1]; } } /* nx, ny are the number of cells across and down, rounded up */ nx = width / BX + (0 == (width %BX) ? 0 : 1); ny = height / BY + (0 == (height%BY) ? 0 : 1); skews = (GR_POINT *)malloc(sizeof(GR_POINT) * (nx*ny)); if( (GR_POINT *)0 != skews ) { for( i = 0; i < nx; i++ ) { for( j = 0; j < ny; j++ ) { skews[j * nx + i].x = random()%BX; skews[j * nx + i].y = random()%BY; } } } # define SKEWX(cx, cy) (((GR_POINT *)0 == skews)?0:skews[cy*nx + cx].x) # define SKEWY(cx, cy) (((GR_POINT *)0 == skews)?0:skews[cy*nx + cx].y) for( i = 0; i < SIZE; i++ ) { int x = array[i] % BX; int y = array[i] / BX; { int iy, cy; for( iy = 0, cy = 0; iy < height; iy += BY, cy++ ) { int ix, cx; for( ix = 0, cx = 0; ix < width; ix += BX, cx++ ) { int xx = ix + (SKEWX(cx, cy) + x*((cx%(BX-1))+1))%BX; int yy = iy + (SKEWY(cx, cy) + y*((cy%(BY-1))+1))%BY; if (xx < width && yy < height) GrPoint(wid, erase_gc, xx, yy); } } } if( (BX-1) == (i%BX) ) { wait_sync (); usleep (delay*granularity); } } # undef SKEWX # undef SKEWY if( (GR_POINT *)0 != skews ) { free(skews); } # undef BX # undef BY # undef SIZE } /* from Rick Campbell <rick@campbellcentral.org> */ static void spiral (int width, int height, int delay, int granularity) { # define SPIRAL_ERASE_PI_2 (M_PI + M_PI) # define SPIRAL_ERASE_LOOP_COUNT (10) # define SPIRAL_ERASE_ARC_COUNT (360.0) # define SPIRAL_ERASE_ANGLE_INCREMENT (SPIRAL_ERASE_PI_2 / \ SPIRAL_ERASE_ARC_COUNT) # define SPIRAL_ERASE_DELAY (0) double angle; int arc_limit; int arc_max_limit; int length_step; GR_POINT points [3]; angle = 0.0; arc_limit = 1; arc_max_limit = (int) (ceil (sqrt ((width * width) + (height * height))) / 2.0); length_step = ((arc_max_limit + SPIRAL_ERASE_LOOP_COUNT - 1) / SPIRAL_ERASE_LOOP_COUNT); arc_max_limit += length_step; points [0].x = width / 2; points [0].y = height / 2; points [1].x = points [0].x + length_step; points [1].y = points [0].y; points [2].x = points [1].x; points [2].y = points [1].y; for (arc_limit = length_step; arc_limit < arc_max_limit; arc_limit += length_step) { int arc_length = length_step; int length_base = arc_limit; for (angle = 0.0; angle < SPIRAL_ERASE_PI_2; angle += SPIRAL_ERASE_ANGLE_INCREMENT) { arc_length = length_base + ((length_step * angle) / SPIRAL_ERASE_PI_2); points [1].x = points [2].x; points [1].y = points [2].y; points [2].x = points [0].x + (int)(cos (angle) * arc_length); points [2].y = points [0].y + (int)(sin (angle) * arc_length); GrFillPoly (wid, erase_gc, 3, points); # if (SPIRAL_ERASE_DELAY != 0) usleep (SPIRAL_ERASE_DELAY); # endif /* (SPIRAL_ERASE_DELAY != 0) */ } } # undef SPIRAL_ERASE_DELAY # undef SPIRAL_ERASE_ANGLE_INCREMENT # undef SPIRAL_ERASE_ARC_COUNT # undef SPIRAL_ERASE_LOOP_COUNT # undef SPIRAL_ERASE_PI_2 } #undef MAX #undef MIN #define MAX(a,b) ((a)>(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b)) /* from David Bagley <bagleyd@tux.org> */ static void random_squares(int width, int height, int delay, int granularity) { int randsize = MAX(1, MIN(width, height) / (16 + (random() % 32))); int max = (height / randsize + 1) * (width / randsize + 1); int *squares = (int *) calloc(max, sizeof (*squares)); int i; int columns = width / randsize + 1; /* Add an extra for roundoff */ for (i = 0; i < max; i++) squares[i] = i; for (i = 0; i < max; i++) { int t, r; t = squares[i]; r = random() % max; squares[i] = squares[r]; squares[r] = t; } for (i = 0; i < max; i++) { GrRect(wid, erase_gc, (squares[i] % columns) * randsize, (squares[i] / columns) * randsize, randsize, randsize); wait_sync (); if (delay > 0 && ((i % granularity) == 0)) usleep(delay * granularity); } free(squares); } /* I first saw something like this, albeit in reverse, in an early Tetris implementation for the Mac. -- Torbjörn Andersson <torbjorn@dev.eurotime.se> */ static void slide_lines (int width, int height, int delay, int granularity) { int slide_old_x, slide_new_x, clear_x; int x, y, dx, dy; /* This might need some tuning. The idea is to get sensible values no matter what the size of the window. Everything moves at constant speed. Should it accelerate instead? */ granularity *= 2; dy = MAX (1, height / granularity); dx = MAX (1, width / 100); for (x = 0; x < width; x += dx) { for (y = 0; y < height; y += dy) { if ((y / dy) & 1) { slide_old_x = x; slide_new_x = x + dx; clear_x = x; } else { slide_old_x = dx; slide_new_x = 0; clear_x = width - x - dx; } GrCopyArea (wid, erase_gc, slide_old_x, y, width - x - dx, dy, wid, slide_new_x, y, MWROP_SRCCOPY); GrRect (wid, erase_gc, clear_x, y, dx, dy); } wait_sync (); usleep(delay * 3); } } static Eraser erasers[] = { random_lines, venetian, triple_wipe, quad_wipe, /* circle_wipe, three_circle_wipe, // needs floating point */ squaretate, /* fizzle, // Too slow */ random_squares, spiral, slide_lines, }; void erase_full_window() { int granularity = 25; int delay = 0; int mode = random() % countof(erasers); (*(erasers[mode])) (WINDOW_WIDTH, WINDOW_HEIGHT, delay, granularity); GrRect (wid, erase_gc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); wait_sync (); }