http://ftp.x.org/contrib/applications/xscreensaver-2.23.tar.gz
[xscreensaver] / hacks / moire2.c
1 /* xscreensaver, Copyright (c) 1997 Jamie Zawinski <jwz@netscape.com>
2  *
3  * Permission to use, copy, modify, distribute, and sell this software and its
4  * documentation for any purpose is hereby granted without fee, provided that
5  * the above copyright notice appear in all copies and that both that
6  * copyright notice and this permission notice appear in supporting
7  * documentation.  No representations are made about the suitability of this
8  * software for any purpose.  It is provided "as is" without express or 
9  * implied warranty.
10  */
11
12 #include "screenhack.h"
13 #include <X11/Xutil.h>
14 #include <stdio.h>
15
16 static int ncolors;
17 static XColor *colors = 0;
18 static int fg_pixel, bg_pixel;
19 static Pixmap p0 = 0, p1 = 0, p2 = 0, p3 = 0;
20 static GC copy_gc = 0, erase_gc = 0, window_gc = 0;
21 static int width, height, size;
22 static int x1, x2, y1, y2, x3, y3;
23 static int dx1, dx2, dx3, dy1, dy2, dy3;
24 static int othickness, thickness;
25 static Bool do_three;
26
27 static void
28 init_moire2 (Display *dpy, Window window)
29 {
30   XWindowAttributes xgwa;
31   XGetWindowAttributes (dpy, window, &xgwa);
32
33   othickness = get_integer_resource("thickness", "Thickness");
34
35   if (mono_p)
36     ncolors = 2;
37   else
38     ncolors = get_integer_resource ("colors", "Colors");
39   if (ncolors < 2) ncolors = 2;
40   if (ncolors <= 2) mono_p = True;
41
42   if (mono_p)
43     colors = 0;
44   else
45     colors = (XColor *) malloc(sizeof(*colors) * (ncolors+1));
46
47   if (mono_p)
48     ;
49   else
50     make_smooth_colormap (dpy, xgwa.visual, xgwa.colormap, colors, &ncolors,
51                           True, 0, True);
52
53   bg_pixel = get_pixel_resource("background", "Background", dpy,
54                                 xgwa.colormap);
55   fg_pixel = get_pixel_resource("foreground", "Foreground", dpy,
56                                 xgwa.colormap);
57 }
58
59
60 static void
61 reset_moire2 (Display *dpy, Window window)
62 {
63   GC gc;
64   XWindowAttributes xgwa;
65   XGCValues gcv;
66   Bool xor;
67   XGetWindowAttributes (dpy, window, &xgwa);
68
69   do_three = (0 == (random() % 3));
70
71   width = xgwa.width;
72   height = xgwa.height;
73   size = width > height ? width : height;
74
75   if (p0) XFreePixmap(dpy, p0);
76   if (p1) XFreePixmap(dpy, p1);
77   if (p2) XFreePixmap(dpy, p2);
78   if (p3) XFreePixmap(dpy, p3);
79
80   p0 = XCreatePixmap(dpy, window, width, height, 1);
81   p1 = XCreatePixmap(dpy, window, width*2, height*2, 1);
82   p2 = XCreatePixmap(dpy, window, width*2, height*2, 1);
83   if (do_three)
84     p3 = XCreatePixmap(dpy, window, width*2, height*2, 1);
85   else
86     p3 = 0;
87
88   thickness = (othickness > 0 ? othickness : (1 + (random() % 4)));
89
90   gcv.foreground = 0;
91   gcv.line_width = (thickness == 1 ? 0 : thickness);
92   gc = XCreateGC (dpy, p1, GCForeground|GCLineWidth, &gcv);
93
94   XFillRectangle(dpy, p1, gc, 0, 0, width*2, height*2);
95   XFillRectangle(dpy, p2, gc, 0, 0, width*2, height*2);
96   if (do_three)
97     XFillRectangle(dpy, p3, gc, 0, 0, width*2, height*2);
98
99   XSetForeground(dpy, gc, 1);
100
101   xor = (do_three || (thickness == 1) || (random() & 1));
102
103   {
104     int i, ii, maxx, maxy;
105
106 #define FROB(P) do { \
107     maxx = (size*4); \
108     maxy = (size*4); \
109     if (0 == (random() % 5)) { \
110         float f = 1.0 + frand(0.05); \
111         if (random() & 1) maxx *= f; \
112         else maxy *= f; \
113       } \
114     ii = (thickness + 1 + (xor ? 0 : 1) + (random() % (4 * thickness)));  \
115     for (i = 0; i < (size*2); i += ii)  \
116       XDrawArc(dpy, (P), gc, i-size, i-size, maxx-i-i, maxy-i-i, 0, 360*64); \
117     if (0 == (random() % 5)) \
118       { \
119         XSetFunction(dpy, gc, GXxor); \
120         XFillRectangle(dpy, (P), gc, 0, 0, width*2, height*2); \
121         XSetFunction(dpy, gc, GXcopy); \
122       } \
123     } while(0)
124
125     FROB(p1);
126     FROB(p2);
127     if (do_three)
128       FROB(p3);
129 #undef FROB
130   }
131
132   XFreeGC(dpy, gc);
133
134   if (copy_gc) XFreeGC(dpy, copy_gc);
135   gcv.function = (xor ? GXxor : GXor);
136   gcv.foreground = 1;
137   gcv.background = 0;
138
139   copy_gc = XCreateGC (dpy, p0, GCFunction|GCForeground|GCBackground, &gcv);
140
141   gcv.foreground = 0;
142   if (erase_gc) XFreeGC(dpy, erase_gc);
143   erase_gc = XCreateGC (dpy, p0, GCForeground, &gcv);
144
145   gcv.foreground = fg_pixel;
146   gcv.background = bg_pixel;
147   if (window_gc) XFreeGC(dpy, window_gc);
148   window_gc = XCreateGC (dpy, window, GCForeground|GCBackground, &gcv);
149
150 #define FROB(N,DN,MAX) \
151   N = (MAX/2) + (random() % MAX); \
152   DN = ((1 + (random() % (7*thickness))) * ((random() & 1) ? 1 : -1))
153
154   FROB(x1,dx1,width);
155   FROB(x2,dx2,width);
156   FROB(x3,dx3,width);
157   FROB(y1,dy1,height);
158   FROB(y2,dy2,height);
159   FROB(y3,dy3,height);
160 #undef FROB
161 }
162
163
164
165 static void
166 moire2 (Display *dpy, Window window)
167 {
168 #define FROB(N,DN,MAX) \
169   N += DN; \
170   if (N <= 0) N = 0, DN = -DN; \
171   else if (N >= MAX) N = MAX, DN = -DN; \
172   else if (0 == (random() % 100)) DN = -DN; \
173   else if (0 == (random() % 50)) \
174     DN += (DN <= -20 ? 1 : (DN >= 20 ? -1 : ((random() & 1) ? 1 : -1)))
175
176   FROB(x1,dx1,width);
177   FROB(x2,dx2,width);
178   FROB(x3,dx3,width);
179   FROB(y1,dy1,height);
180   FROB(y2,dy2,height);
181   FROB(y3,dy3,height);
182 #undef FROB
183
184   XFillRectangle(dpy, p0, erase_gc, 0, 0, width, height);
185   XCopyArea(dpy, p1, p0, copy_gc, x1, y1, width, height, 0, 0);
186   XCopyArea(dpy, p2, p0, copy_gc, x2, y2, width, height, 0, 0);
187   if (do_three)
188     XCopyArea(dpy, p3, p0, copy_gc, x3, y3, width, height, 0, 0);
189
190   XSync(dpy, False);
191   XCopyPlane(dpy, p0, window, window_gc, 0, 0, width, height, 0, 0, 1L);
192   XSync(dpy, False);
193
194 #if 0
195   XCopyPlane(dpy, p1, window, window_gc, (width*2)/3, (height*2)/3,
196              width/2, height/2,
197              0, height/2, 1L);
198   XCopyPlane(dpy, p2, window, window_gc, (width*2)/3, (height*2)/3,
199              width/2, height/2,
200              width/2, height/2, 1L);
201 #endif
202 }
203
204
205
206 \f
207 char *progclass = "Moire2";
208
209 char *defaults [] = {
210   ".background:         black",
211   ".foreground:         white",
212   "*delay:              50000",
213   "*thickness:          0",
214   "*colors:             150",
215   "*colorShift:         5",
216   0
217 };
218
219 XrmOptionDescRec options [] = {
220   { "-delay",           ".delay",       XrmoptionSepArg, 0 },
221   { "-ncolors",         ".colors",      XrmoptionSepArg, 0 },
222   { "-thickness",       ".thickness",   XrmoptionSepArg, 0 },
223   { 0, 0, 0, 0 }
224 };
225
226 void
227 screenhack (Display *dpy, Window window)
228 {
229   int delay = get_integer_resource ("delay", "Integer");
230   int color_shift = get_integer_resource ("colorShift", "Integer");
231   int pix = 0;
232   Bool flip_a, flip_b;
233
234   if (color_shift <= 0) color_shift = 1;
235   init_moire2 (dpy, window);
236   while (1)
237     {
238       int iterations = 30 + (random() % 70) + (random() % 70);
239       reset_moire2 (dpy, window);
240
241       flip_a = mono_p ? False : (random() & 1);
242       flip_b = mono_p ? False : (random() & 1);
243
244       if (flip_b)
245         {
246           XSetForeground(dpy, window_gc, bg_pixel);
247           XSetBackground(dpy, window_gc, fg_pixel);
248         }
249       else
250         {
251           XSetForeground(dpy, window_gc, fg_pixel);
252           XSetBackground(dpy, window_gc, bg_pixel);
253         }
254
255       while (--iterations > 0)
256         {
257           int i;
258
259           if (!mono_p)
260             {
261               pix++;
262               pix = pix % ncolors;
263
264               if (flip_a)
265                 XSetBackground(dpy, window_gc, colors[pix].pixel);
266               else
267                 XSetForeground(dpy, window_gc, colors[pix].pixel);
268             }
269
270           for (i = 0; i < color_shift; i++)
271             {
272               moire2 (dpy, window);
273               if (delay)
274                 usleep(delay);
275             }
276         }
277     }
278 }