1 /* erase.c: Erase the screen in various more or less interesting ways.
2 * (c) 1997 by Johannes Keukelaar <johannes@nada.kth.se>
3 * Permission to use in any way granted. Provided "as is" without expressed
4 * or implied warranty. NO WARRANTY, NO EXPRESSION OF SUITABILITY FOR ANY
5 * PURPOSE. (I.e.: Use in any way, but at your own risk!)
11 #include "resources.h"
14 #define countof(x) (sizeof(x)/sizeof(*(x)))
16 typedef void (*Eraser) (Display *dpy, Window window, GC gc,
17 int width, int height, int delay, int granularity);
21 random_lines (Display *dpy, Window window, GC gc,
22 int width, int height, int delay, int granularity)
24 Bool horiz_p = (random() & 1);
25 int max = (horiz_p ? height : width);
26 int *lines = (int *) calloc(max, sizeof(*lines));
29 for (i = 0; i < max; i++)
32 for (i = 0; i < max; i++)
41 for (i = 0; i < max; i++)
44 XDrawLine (dpy, window, gc, 0, lines[i], width, lines[i]);
46 XDrawLine (dpy, window, gc, lines[i], 0, lines[i], height);
49 if (delay > 0 && ((i % granularity) == 0))
50 usleep (delay * granularity);
57 venetian (Display *dpy, Window window, GC gc,
58 int width, int height, int delay, int granularity)
60 Bool horiz_p = (random() & 1);
61 Bool flip_p = (random() & 1);
62 int max = (horiz_p ? height : width);
63 int *lines = (int *) calloc(max, sizeof(*lines));
69 for (i = 0; i < max*2; i++)
71 int line = ((i / 16) * 16) - ((i % 16) * 15);
72 if (line >= 0 && line < max)
73 lines[j++] = (flip_p ? max - line : line);
76 for (i = 0; i < max; i++)
79 XDrawLine (dpy, window, gc, 0, lines[i], width, lines[i]);
81 XDrawLine (dpy, window, gc, lines[i], 0, lines[i], height);
84 if (delay > 0 && ((i % granularity) == 0))
85 usleep (delay * granularity);
92 triple_wipe (Display *dpy, Window window, GC gc,
93 int width, int height, int delay, int granularity)
95 Bool flip_x = random() & 1;
96 Bool flip_y = random() & 1;
97 int max = width + (height / 2);
98 int *lines = (int *)calloc(max, sizeof(int));
101 for(i = 0; i < width/2; i++)
102 lines[i] = i*2+height;
103 for(i = 0; i < height/2; i++)
104 lines[i+width/2] = i*2;
105 for(i = 0; i < width/2; i++)
106 lines[i+width/2+height/2] = width-i*2-(width%2?0:1)+height;
110 for (i = 0; i < max; i++)
113 if (lines[i] < height)
114 x = 0, y = lines[i], x2 = width, y2 = y;
116 x = lines[i]-height, y = 0, x2 = x, y2 = height;
119 x = width-x, x2 = width-x2;
121 y = height-y, y2 = height-y2;
123 XDrawLine (dpy, window, gc, x, y, x2, y2);
125 if (delay > 0 && ((i % granularity) == 0))
126 usleep (delay*granularity);
133 quad_wipe (Display *dpy, Window window, GC gc,
134 int width, int height, int delay, int granularity)
136 Bool flip_x = random() & 1;
137 Bool flip_y = random() & 1;
138 int max = width + height;
139 int *lines = (int *)calloc(max, sizeof(int));
144 for (i = 0; i < max/4; i++)
147 lines[i*4+1] = height-i*2-(height%2?0:1);
148 lines[i*4+2] = height+i*2;
149 lines[i*4+3] = height+width-i*2-(width%2?0:1);
152 for (i = 0; i < max; i++)
155 if (lines[i] < height)
156 x = 0, y = lines[i], x2 = width, y2 = y;
158 x = lines[i]-height, y = 0, x2 = x, y2 = height;
161 x = width-x, x2 = width-x2;
163 y = height-y, y2 = height-y2;
165 XDrawLine (dpy, window, gc, x, y, x2, y2);
167 if (delay > 0 && ((i % granularity) == 0))
168 usleep (delay*granularity);
176 circle_wipe (Display *dpy, Window window, GC gc,
177 int width, int height, int delay, int granularity)
181 int start = random() % full;
182 int rad = (width > height ? width : height);
186 for (i = (inc > 0 ? 0 : full);
187 (inc > 0 ? i < full : i > 0);
190 XFillArc(dpy, window, gc,
191 (width/2)-rad, (height/2)-rad, rad*2, rad*2,
192 (i+start) % full, inc);
194 usleep (delay*granularity);
200 three_circle_wipe (Display *dpy, Window window, GC gc,
201 int width, int height, int delay, int granularity)
207 int inc = full / 240;
208 int start = random() % q;
209 int rad = (width > height ? width : height);
211 for (i = 0; i < q; i += inc)
213 XFillArc(dpy, window, gc, (width/2)-rad, (height/2)-rad, rad*2, rad*2,
214 (start+i) % full, inc);
215 XFillArc(dpy, window, gc, (width/2)-rad, (height/2)-rad, rad*2, rad*2,
216 (start-i) % full, -inc);
218 XFillArc(dpy, window, gc, (width/2)-rad, (height/2)-rad, rad*2, rad*2,
219 (start+q2+i) % full, inc);
220 XFillArc(dpy, window, gc, (width/2)-rad, (height/2)-rad, rad*2, rad*2,
221 (start+q2-i) % full, -inc);
223 XFillArc(dpy, window, gc, (width/2)-rad, (height/2)-rad, rad*2, rad*2,
224 (start+q2+q2+i) % full, inc);
225 XFillArc(dpy, window, gc, (width/2)-rad, (height/2)-rad, rad*2, rad*2,
226 (start+q2+q2-i) % full, -inc);
229 usleep (delay*granularity);
235 squaretate (Display *dpy, Window window, GC gc,
236 int width, int height, int delay, int granularity)
238 int steps = (((width > height ? width : width) * 2) / granularity);
240 Bool flip = random() & 1;
244 points[0].x = width-points[0].x; \
245 points[1].x = width-points[1].x; \
246 points[2].x = width-points[2].x; } \
247 XFillPolygon (dpy, window, gc, points, 3, Convex, CoordModeOrigin)
249 for (i = 0; i < steps; i++)
257 points[2].y = points[0].y + ((i * height) / steps);
263 points[1].y = height;
264 points[2].x = ((i * width) / steps);
265 points[2].y = height;
269 points[0].y = height;
271 points[1].y = height;
273 points[2].y = height - ((i * height) / steps);
277 points[0].y = height;
280 points[2].x = width - ((i * width) / steps);
286 usleep (delay * granularity);
292 /* from Frederick Roeber <roeber@netscape.com> */
294 fizzle (Display *dpy, Window window, GC gc,
295 int width, int height, int delay, int granularity)
297 /* These dimensions must be prime numbers. They should be roughly the
298 square root of the width and height. */
301 # define SIZE (BX*BY)
308 /* Distribute the numbers [0,SIZE) randomly in the array */
312 for( i = 0; i < SIZE; i++ ) {
317 for( i = 0; i < SIZE; i++ ) {
318 j = random()%(SIZE-i);
319 array[indices[j]] = i;
320 indices[j] = indices[SIZE-i-1];
324 /* nx, ny are the number of cells across and down, rounded up */
325 nx = width / BX + (0 == (width %BX) ? 0 : 1);
326 ny = height / BY + (0 == (height%BY) ? 0 : 1);
327 skews = (XPoint *)malloc(sizeof(XPoint) * (nx*ny));
328 if( (XPoint *)0 != skews ) {
329 for( i = 0; i < nx; i++ ) {
330 for( j = 0; j < ny; j++ ) {
331 skews[j * nx + i].x = random()%BX;
332 skews[j * nx + i].y = random()%BY;
337 # define SKEWX(cx, cy) (((XPoint *)0 == skews)?0:skews[cy*nx + cx].x)
338 # define SKEWY(cx, cy) (((XPoint *)0 == skews)?0:skews[cy*nx + cx].y)
340 for( i = 0; i < SIZE; i++ ) {
341 int x = array[i] % BX;
342 int y = array[i] / BX;
346 for( iy = 0, cy = 0; iy < height; iy += BY, cy++ ) {
348 for( ix = 0, cx = 0; ix < width; ix += BX, cx++ ) {
349 int xx = ix + (SKEWX(cx, cy) + x*((cx%(BX-1))+1))%BX;
350 int yy = iy + (SKEWY(cx, cy) + y*((cy%(BY-1))+1))%BY;
351 if (xx < width && yy < height)
352 XDrawPoint(dpy, window, gc, xx, yy);
357 if( (BX-1) == (i%BX) ) {
359 usleep (delay*granularity);
366 if( (XPoint *)0 != skews ) {
376 /* from Rick Campbell <rick@campbellcentral.org> */
378 spiral (Display *display, Window window, GC context,
379 int width, int height, int delay, int granularity)
381 # define SPIRAL_ERASE_PI_2 (M_PI + M_PI)
382 # define SPIRAL_ERASE_LOOP_COUNT (10)
383 # define SPIRAL_ERASE_ARC_COUNT (360.0)
384 # define SPIRAL_ERASE_ANGLE_INCREMENT (SPIRAL_ERASE_PI_2 / \
385 SPIRAL_ERASE_ARC_COUNT)
386 # define SPIRAL_ERASE_DELAY (0)
396 arc_max_limit = (int) (ceil (sqrt ((width * width) + (height * height)))
398 length_step = ((arc_max_limit + SPIRAL_ERASE_LOOP_COUNT - 1) /
399 SPIRAL_ERASE_LOOP_COUNT);
400 arc_max_limit += length_step;
401 points [0].x = width / 2;
402 points [0].y = height / 2;
403 points [1].x = points [0].x + length_step;
404 points [1].y = points [0].y;
405 points [2].x = points [1].x;
406 points [2].y = points [1].y;
408 for (arc_limit = length_step;
409 arc_limit < arc_max_limit;
410 arc_limit += length_step)
412 int arc_length = length_step;
413 int length_base = arc_limit;
414 for (angle = 0.0; angle < SPIRAL_ERASE_PI_2;
415 angle += SPIRAL_ERASE_ANGLE_INCREMENT)
417 arc_length = length_base + ((length_step * angle) /
419 points [1].x = points [2].x;
420 points [1].y = points [2].y;
421 points [2].x = points [0].x + (int)(cos (angle) * arc_length);
422 points [2].y = points [0].y + (int)(sin (angle) * arc_length);
423 XFillPolygon (display, window, context, points, 3, Convex,
425 # if (SPIRAL_ERASE_DELAY != 0)
426 usleep (SPIRAL_ERASE_DELAY);
427 # endif /* (SPIRAL_ERASE_DELAY != 0) */
430 # undef SPIRAL_ERASE_DELAY
431 # undef SPIRAL_ERASE_ANGLE_INCREMENT
432 # undef SPIRAL_ERASE_ARC_COUNT
433 # undef SPIRAL_ERASE_LOOP_COUNT
434 # undef SPIRAL_ERASE_PI_2
440 #define MAX(a,b) ((a)>(b)?(a):(b))
441 #define MIN(a,b) ((a)<(b)?(a):(b))
443 /* from David Bagley <bagleyd@tux.org> */
445 random_squares(Display * dpy, Window window, GC gc,
446 int width, int height, int delay, int granularity)
448 int randsize = MAX(1, MIN(width, height) / (16 + (random() % 32)));
449 int max = (height / randsize + 1) * (width / randsize + 1);
450 int *squares = (int *) calloc(max, sizeof (*squares));
452 int columns = width / randsize + 1; /* Add an extra for roundoff */
454 for (i = 0; i < max; i++)
457 for (i = 0; i < max; i++)
462 squares[i] = squares[r];
466 for (i = 0; i < max; i++)
468 XFillRectangle(dpy, window, gc,
469 (squares[i] % columns) * randsize,
470 (squares[i] / columns) * randsize,
474 if (delay > 0 && ((i % granularity) == 0))
475 usleep(delay * granularity);
480 /* I first saw something like this, albeit in reverse, in an early Tetris
481 implementation for the Mac.
482 -- Torbjörn Andersson <torbjorn@dev.eurotime.se>
486 slide_lines (Display * dpy, Window window, GC gc, int width, int height,
487 int delay, int granularity)
489 int slide_old_x, slide_new_x, clear_x;
492 /* This might need some tuning. The idea is to get sensible values no
493 matter what the size of the window.
495 Everything moves at constant speed. Should it accelerate instead? */
499 dy = MAX (1, height / granularity);
500 dx = MAX (1, width / 100);
502 for (x = 0; x < width; x += dx)
504 for (y = 0; y < height; y += dy)
509 slide_new_x = x + dx;
516 clear_x = width - x - dx;
519 XCopyArea (dpy, window, window, gc, slide_old_x, y, width - x - dx,
521 XClearArea (dpy, window, clear_x, y, dx, dy, False);
529 static Eraser erasers[] = {
545 erase_window(Display *dpy, Window window, GC gc,
546 int width, int height, int mode, int delay)
548 int granularity = 25;
550 if (mode < 0 || mode >= countof(erasers))
551 mode = random() % countof(erasers);
552 (*(erasers[mode])) (dpy, window, gc, width, height, delay, granularity);
553 XClearWindow (dpy, window);
559 erase_full_window(Display *dpy, Window window)
561 XWindowAttributes xgwa;
565 int erase_speed, erase_mode;
568 s = get_string_resource("eraseSpeed", "Integer");
570 erase_speed = get_integer_resource("eraseSpeed", "Integer");
575 s = get_string_resource("eraseMode", "Integer");
577 erase_mode = get_integer_resource("eraseMode", "Integer");
582 XGetWindowAttributes (dpy, window, &xgwa);
583 black.flags = DoRed|DoGreen|DoBlue;
584 black.red = black.green = black.blue = 0;
585 XAllocColor(dpy, xgwa.colormap, &black);
586 gcv.foreground = black.pixel;
587 erase_gc = XCreateGC (dpy, window, GCForeground, &gcv);
588 erase_window (dpy, window, erase_gc, xgwa.width, xgwa.height,
589 erase_mode, erase_speed);
590 XFreeColors(dpy, xgwa.colormap, &black.pixel, 1, 0);
591 XFreeGC(dpy, erase_gc);
597 #include "screenhack.h"
599 char *progclass = "Erase";
600 char *defaults [] = {
604 XrmOptionDescRec options [] = {{0}};
605 int options_size = 0;
608 screenhack (dpy, window)
616 XWindowAttributes xgwa;
617 XGetWindowAttributes (dpy, window, &xgwa);
618 white.flags = DoRed|DoGreen|DoBlue;
619 white.red = white.green = white.blue = 0xFFFF;
620 XAllocColor(dpy, xgwa.colormap, &white);
621 gcv.foreground = white.pixel;
622 gc = XCreateGC (dpy, window, GCForeground, &gcv);
626 XFillRectangle(dpy, window, gc, 0, 0, 1280, 1024);
629 erase_full_window(dpy, window);