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 XDrawPoint(dpy, window, gc, xx, yy);
356 if( (BX-1) == (i%BX) ) {
358 usleep (delay*granularity);
365 if( (XPoint *)0 != skews ) {
375 /* from Rick Campbell <rick@campbellcentral.org> */
377 spiral (Display *display, Window window, GC context,
378 int width, int height, int delay, int granularity)
380 # define SPIRAL_ERASE_PI_2 (M_PI + M_PI)
381 # define SPIRAL_ERASE_LOOP_COUNT (10)
382 # define SPIRAL_ERASE_ARC_COUNT (360.0)
383 # define SPIRAL_ERASE_ANGLE_INCREMENT (SPIRAL_ERASE_PI_2 / \
384 SPIRAL_ERASE_ARC_COUNT)
385 # define SPIRAL_ERASE_DELAY (0)
395 arc_max_limit = (int) (ceil (sqrt ((width * width) + (height * height)))
397 length_step = ((arc_max_limit + SPIRAL_ERASE_LOOP_COUNT - 1) /
398 SPIRAL_ERASE_LOOP_COUNT);
399 arc_max_limit += length_step;
400 points [0].x = width / 2;
401 points [0].y = height / 2;
402 points [1].x = points [0].x + length_step;
403 points [1].y = points [0].y;
404 points [2].x = points [1].x;
405 points [2].y = points [1].y;
407 for (arc_limit = length_step;
408 arc_limit < arc_max_limit;
409 arc_limit += length_step)
411 int arc_length = length_step;
412 int length_base = arc_limit;
413 for (angle = 0.0; angle < SPIRAL_ERASE_PI_2;
414 angle += SPIRAL_ERASE_ANGLE_INCREMENT)
416 arc_length = length_base + ((length_step * angle) /
418 points [1].x = points [2].x;
419 points [1].y = points [2].y;
420 points [2].x = points [0].x + (int)(cos (angle) * arc_length);
421 points [2].y = points [0].y + (int)(sin (angle) * arc_length);
422 XFillPolygon (display, window, context, points, 3, Convex,
424 # if (SPIRAL_ERASE_DELAY != 0)
425 usleep (SPIRAL_ERASE_DELAY);
426 # endif /* (SPIRAL_ERASE_DELAY != 0) */
429 # undef SPIRAL_ERASE_DELAY
430 # undef SPIRAL_ERASE_ANGLE_INCREMENT
431 # undef SPIRAL_ERASE_ARC_COUNT
432 # undef SPIRAL_ERASE_LOOP_COUNT
433 # undef SPIRAL_ERASE_PI_2
439 #define MAX(a,b) ((a)>(b)?(a):(b))
440 #define MIN(a,b) ((a)<(b)?(a):(b))
442 /* from David Bagley <bagleyd@tux.org> */
444 random_squares(Display * dpy, Window window, GC gc,
445 int width, int height, int delay, int granularity)
447 int randsize = MAX(1, MIN(width, height) / (16 + (random() % 32)));
448 int max = (height / randsize + 1) * (width / randsize + 1);
449 int *squares = (int *) calloc(max, sizeof (*squares));
451 int columns = width / randsize + 1; /* Add an extra for roundoff */
453 for (i = 0; i < max; i++)
456 for (i = 0; i < max; i++)
461 squares[i] = squares[r];
465 for (i = 0; i < max; i++)
467 XFillRectangle(dpy, window, gc,
468 (squares[i] % columns) * randsize,
469 (squares[i] / columns) * randsize,
473 if (delay > 0 && ((i % granularity) == 0))
474 usleep(delay * granularity);
479 /* I first saw something like this, albeit in reverse, in an early Tetris
480 implementation for the Mac.
481 -- Torbjörn Andersson <torbjorn@dev.eurotime.se>
485 slide_lines (Display * dpy, Window window, GC gc, int width, int height,
486 int delay, int granularity)
488 int slide_old_x, slide_new_x, clear_x;
491 /* This might need some tuning. The idea is to get sensible values no
492 matter what the size of the window.
494 Everything moves at constant speed. Should it accelerate instead? */
498 dy = MAX (1, height / granularity);
499 dx = MAX (1, width / 100);
501 for (x = 0; x < width; x += dx)
503 for (y = 0; y < height; y += dy)
508 slide_new_x = x + dx;
515 clear_x = width - x - dx;
518 XCopyArea (dpy, window, window, gc, slide_old_x, y, width - x - dx,
520 XClearArea (dpy, window, clear_x, y, dx, dy, False);
528 static Eraser erasers[] = {
544 erase_window(Display *dpy, Window window, GC gc,
545 int width, int height, int mode, int delay)
547 int granularity = 25;
549 if (mode < 0 || mode >= countof(erasers))
550 mode = random() % countof(erasers);
551 (*(erasers[mode])) (dpy, window, gc, width, height, delay, granularity);
552 XClearWindow (dpy, window);
558 erase_full_window(Display *dpy, Window window)
560 XWindowAttributes xgwa;
564 int erase_speed, erase_mode;
567 s = get_string_resource("eraseSpeed", "Integer");
569 erase_speed = get_integer_resource("eraseSpeed", "Integer");
574 s = get_string_resource("eraseMode", "Integer");
576 erase_mode = get_integer_resource("eraseMode", "Integer");
581 XGetWindowAttributes (dpy, window, &xgwa);
582 black.flags = DoRed|DoGreen|DoBlue;
583 black.red = black.green = black.blue = 0;
584 XAllocColor(dpy, xgwa.colormap, &black);
585 gcv.foreground = black.pixel;
586 erase_gc = XCreateGC (dpy, window, GCForeground, &gcv);
587 erase_window (dpy, window, erase_gc, xgwa.width, xgwa.height,
588 erase_mode, erase_speed);
589 XFreeColors(dpy, xgwa.colormap, &black.pixel, 1, 0);
590 XFreeGC(dpy, erase_gc);
596 #include "screenhack.h"
598 char *progclass = "Erase";
599 char *defaults [] = {
603 XrmOptionDescRec options [] = {{0}};
604 int options_size = 0;
607 screenhack (dpy, window)
615 XWindowAttributes xgwa;
616 XGetWindowAttributes (dpy, window, &xgwa);
617 white.flags = DoRed|DoGreen|DoBlue;
618 white.red = white.green = white.blue = 0xFFFF;
619 XAllocColor(dpy, xgwa.colormap, &white);
620 gcv.foreground = white.pixel;
621 gc = XCreateGC (dpy, window, GCForeground, &gcv);
625 XFillRectangle(dpy, window, gc, 0, 0, 1280, 1024);
628 erase_full_window(dpy, window);