ftp://ftp.demon.nl/disk1/redhat-contrib/libc5/SRPMS/xscreensaver-2.14-1.src.rpm
[xscreensaver] / utils / erase.c
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!)
6  */
7
8 #include "utils.h"
9 #include "yarandom.h"
10 #include "usleep.h"
11 #include "resources.h"
12
13 #define NUM_MODES 8
14
15 void
16 erase_window(Display *dpy, Window window, GC gc,
17              int width, int height, int mode, int delay)
18 {
19   int *clear_lines;
20   int i, j, line, num_lines=0, granularity, max_num;
21
22   max_num = 2*height;
23   if(2*width>max_num)
24     max_num = 2*width;
25
26   clear_lines = (int *)calloc(max_num, sizeof(int));
27   if(clear_lines)
28     {
29       if(mode<0 || mode>=NUM_MODES)
30         mode = random()%NUM_MODES;
31       granularity = 25;
32       switch(mode)
33         {
34         case 0:                         /* clear random horizontal lines */
35           for(i = 0; i < height; i++)
36             clear_lines[i] = i;
37           for(i = 0; i < height; i++)
38             {
39               int t, r;
40               t = clear_lines[i];
41               r = random()%height;
42               clear_lines[i] = clear_lines[r];
43               clear_lines[r] = t;
44             }
45           num_lines = height;
46           break;
47
48         case 1:                         /* clear random vertical lines */
49           for(i = 0; i < width; i++)
50             clear_lines[i] = i+height;
51           for(i = 0; i < width; i++)
52             {
53               int t, r;
54               t = clear_lines[i];
55               r = random()%width;
56               clear_lines[i] = clear_lines[r];
57               clear_lines[r] = t;
58             }
59           num_lines = width;
60           break;
61
62         case 2:                                 /* 4 sequential wipes,
63                                                    L-R, T-B, R-L, B-T. */
64           for(i = 0; i < width/2; i++)
65             clear_lines[i] = i*2+height;
66           for(i = 0; i < height/2; i++)
67             clear_lines[i+width/2] = i*2;
68           for(i = 0; i < width/2; i++)
69             clear_lines[i+width/2+height/2] = width-i*2-(width%2?0:1)+height;
70           num_lines = width+height/2;
71           granularity = 4;
72           break;
73
74         case 3:                                 /* 4 parallel wipes,
75                                                    L-R, T-B, R-L, B-T. */
76           for(i = 0; i < max_num/4; i++)
77             {
78               clear_lines[i*4] = i*2;
79               clear_lines[i*4+1] = height-i*2-(height%2?0:1);
80               clear_lines[i*4+2] = height+i*2;
81               clear_lines[i*4+3] = height+width-i*2-(width%2?0:1);
82             }
83           num_lines = max_num;
84           granularity = 4;
85           break;
86
87         case 4:                                 /* flutter wipe L-R */
88           j = 0;
89           for(i = 0; i < width*2; i++)
90             {
91               line = (i/16)*16-(i%16)*15;
92               if(line>=0 && line<width)
93                 {
94                   clear_lines[j] = height+line;
95                   j++;
96                 }
97             }
98           num_lines = width;
99           granularity = 4;
100           break;
101
102         case 5:                                 /* flutter wipe R-L */
103           j = 0;
104           for(i = width*2; i >= 0; i--)
105             {
106               line = (i/16)*16-(i%16)*15;
107               if(line>=0 && line<width)
108                 {
109                   clear_lines[j] = height+line;
110                   j++;
111                 }
112             }
113           num_lines = width;
114           granularity = 4;
115           break;
116
117         case 6:                                 /* circle wipe */
118           {
119             int full = 360 * 64;
120             int inc = full / 64;
121             int start = random() % full;
122             int rad = (width > height ? width : height);
123             if (random() & 1)
124               inc = -inc;
125             for (i = (inc > 0 ? 0 : full);
126                  (inc > 0 ? i < full : i > 0);
127                  i += inc) {
128               XFillArc(dpy, window, gc,
129                        (width/2)-rad, (height/2)-rad, rad*2, rad*2,
130                        (i+start) % full, inc);
131               XFlush (dpy);
132               usleep (delay*granularity);
133             }
134           num_lines = 0;
135           }
136           break;
137
138         case 7:                                 /* three-circle wipe */
139           {
140             int full = 360 * 64;
141             int q = full / 3;
142             int inc = full / 180;
143             int start = random() % q;
144             int rad = (width > height ? width : height);
145             if (random() & 1)
146               inc = -inc;
147             for (i = (inc > 0 ? 0 : q);
148                  (inc > 0 ? i < q : i > 0);
149                  i += inc) {
150               XFillArc(dpy, window, gc,
151                        (width/2)-rad, (height/2)-rad, rad*2, rad*2,
152                        (i+start) % full, inc);
153               XFillArc(dpy, window, gc,
154                        (width/2)-rad, (height/2)-rad, rad*2, rad*2,
155                        (i+start+q) % full, inc);
156               XFillArc(dpy, window, gc,
157                        (width/2)-rad, (height/2)-rad, rad*2, rad*2,
158                        (i+start+q+q) % full, inc);
159               XFlush (dpy);
160               usleep (delay*granularity);
161             }
162           num_lines = 0;
163           }
164           break;
165
166         default:
167           abort();
168           break;
169         }
170
171       for (i = 0; i < num_lines; i++)
172         { 
173           if(clear_lines[i] < height)
174             XDrawLine (dpy, window, gc, 0, clear_lines[i], width, 
175                        clear_lines[i]);
176           else
177             XDrawLine (dpy, window, gc, clear_lines[i]-height, 0,
178                        clear_lines[i]-height, height);
179           XFlush (dpy);
180           if ((i % granularity) == 0)
181             {
182               usleep (delay*granularity);
183             }
184         }
185       
186       free(clear_lines);
187     }
188
189   XClearWindow (dpy, window);
190   XSync(dpy, False);
191 }
192
193
194 void
195 erase_full_window(Display *dpy, Window window)
196 {
197   XWindowAttributes xgwa;
198   XGCValues gcv;
199   GC erase_gc;
200   XColor black;
201   int erase_speed = get_integer_resource("eraseSpeed", "Integer");
202   int erase_mode = get_integer_resource("eraseMode", "Integer");
203   XGetWindowAttributes (dpy, window, &xgwa);
204   black.flags = DoRed|DoGreen|DoBlue;
205   black.red = black.green = black.blue = 0;
206   XAllocColor(dpy, xgwa.colormap, &black);
207   gcv.foreground = black.pixel;
208   erase_gc = XCreateGC (dpy, window, GCForeground, &gcv);
209   erase_window (dpy, window, erase_gc, xgwa.width, xgwa.height,
210                 erase_mode, erase_speed);
211   XFreeColors(dpy, xgwa.colormap, &black.pixel, 1, 0);
212   XFreeGC(dpy, erase_gc);
213 }