ftp://ftp.zenez.com/pub/SCO/Skunk96/UnixWare/FreeBird/x11/utils/xscreensaver-1.18...
[xscreensaver] / hacks / helix.c
1 /* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@lucid.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 <math.h>
14 #if __STDC__
15 #include <values.h>
16 #endif
17
18 static double sins [360];
19 static double coss [360];
20
21 static GC draw_gc, erase_gc;
22 static unsigned int default_fg_pixel;
23
24 static void
25 init_helix (dpy, window)
26      Display *dpy;
27      Window window;
28 {
29   int i;
30   XGCValues gcv;
31   XWindowAttributes xgwa;
32   Colormap cmap;
33   XGetWindowAttributes (dpy, window, &xgwa);
34   cmap = xgwa.colormap;
35   gcv.foreground = default_fg_pixel =
36     get_pixel_resource ("foreground", "Foreground", dpy, cmap);
37   draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
38   gcv.foreground = get_pixel_resource ("background", "Background", dpy, cmap);
39   erase_gc = XCreateGC (dpy, window, GCForeground, &gcv);
40
41   for (i = 0; i < 360; i++)
42     {
43       sins [i] = sin ((((double) i) / 180.0) * M_PI);
44       coss [i] = cos ((((double) i) / 180.0) * M_PI);
45     }
46 }
47
48 static int
49 gcd (a, b)
50      int a, b;
51 {
52   while (b > 0)
53     {
54       int tmp;
55       tmp = a % b;
56       a = b;
57       b = tmp;
58     }
59   return (a < 0 ? -a : a);
60 }
61
62 static void
63 helix (dpy, window,
64        radius1, radius2, d_angle,
65        factor1, factor2, factor3, factor4)
66      Display *dpy;
67      Window window;
68      int radius1, radius2, d_angle;
69      int factor1, factor2, factor3, factor4;
70 {
71   XWindowAttributes xgwa;
72   int width, height;
73   int xmid, ymid;
74   int x1, y1, x2, y2, angle, limit;
75   int i;
76
77   XClearWindow (dpy, window);
78   XGetWindowAttributes (dpy, window, &xgwa);
79   width = xgwa.width;
80   height = xgwa.height;
81
82   xmid = width / 2;
83   ymid = height / 2;
84   x1 = xmid;
85   y1 = ymid + radius2;
86   x2 = xmid;
87   y2 = ymid + radius1;
88   angle = 0;
89   limit = 1 + (360 / gcd (360, d_angle));
90   
91   for (i = 0; i < limit; i++)
92     {
93       int tmp;
94 #define pmod(x,y) (tmp = (x % y), (tmp >= 0 ? tmp : tmp + y))
95       x1 = xmid + (((double) radius1) * sins [pmod ((angle * factor1), 360)]);
96       y1 = ymid + (((double) radius2) * coss [pmod ((angle * factor2), 360)]);
97       XDrawLine (dpy, window, draw_gc, x1, y1, x2, y2);
98       x2 = xmid + (((double) radius2) * sins [pmod ((angle * factor3), 360)]);
99       y2 = ymid + (((double) radius1) * coss [pmod ((angle * factor4), 360)]);
100       XDrawLine (dpy, window, draw_gc, x1, y1, x2, y2);
101       angle += d_angle;
102       XFlush (dpy);
103     }
104 }
105
106 #define min(a,b) ((a)<(b)?(a):(b))
107
108 static void
109 random_helix (dpy, window)
110      Display *dpy;
111      Window window;
112 {
113   Colormap cmap;
114   int width, height;
115   int radius, radius1, radius2, d_angle, factor1, factor2, factor3, factor4;
116   double divisor;
117   XColor color;
118   int i, got_color = 0;
119   XWindowAttributes xgwa;
120   XGetWindowAttributes (dpy, window, &xgwa);
121   width = xgwa.width;
122   height = xgwa.height;
123   cmap = xgwa.colormap;
124
125   radius = min (width, height) / 2;
126
127   d_angle = 0;
128   factor1 = 2;
129   factor2 = 2;
130   factor3 = 2;
131   factor4 = 2;
132
133   divisor = ((frand (3.0) + 1) * (((random() & 1) * 2) - 1));
134
135   if ((random () & 1) == 0)
136     {
137       radius1 = radius;
138       radius2 = radius / divisor;
139     }
140   else
141     {
142       radius2 = radius;
143       radius1 = radius / divisor;
144     }
145
146   while (gcd (360, d_angle) >= 2)
147     d_angle = random () % 360;
148
149 #define random_factor()                         \
150   (((random() % 7) ? ((random() & 1) + 1) : 3)  \
151    * (((random() & 1) * 2) - 1))
152
153   while (gcd (gcd (gcd (factor1, factor2), factor3), factor4) != 1)
154     {
155       factor1 = random_factor ();
156       factor2 = random_factor ();
157       factor3 = random_factor ();
158       factor4 = random_factor ();
159     }
160
161   if (mono_p)
162     XSetForeground (dpy, draw_gc, default_fg_pixel);
163   else
164     {
165       hsv_to_rgb (random () % 360, frand (1.0), frand (0.5) + 0.5,
166                   &color.red, &color.green, &color.blue);
167       if ((got_color = XAllocColor (dpy, cmap, &color)))
168         XSetForeground (dpy, draw_gc, color.pixel);
169       else
170         XSetForeground (dpy, draw_gc, default_fg_pixel);
171     }
172   helix (dpy, window, radius1, radius2, d_angle,
173          factor1, factor2, factor3, factor4);
174
175   XSync (dpy, True);
176   sleep (5);
177
178   for (i = 0; i < height; i++)
179     {
180       int y = (random () % height);
181       XDrawLine (dpy, window, erase_gc, 0, y, width, y);
182       XFlush (dpy);
183       if ((i % 50) == 0)
184         usleep (10000);
185     }
186   XClearWindow (dpy, window);
187   if (got_color) XFreeColors (dpy, cmap, &color.pixel, 1, 0);
188   XSync (dpy, True);
189   sleep (1);
190 }
191
192 \f
193 char *progclass = "Helix";
194
195 char *defaults [] = {
196   "*background: black",
197   0
198 };
199
200 XrmOptionDescRec options [] = { 0 };
201 int options_size = 0;
202
203 void
204 screenhack (dpy, window)
205      Display *dpy;
206      Window window;
207 {
208   init_helix (dpy, window);
209   while (1)
210     random_helix (dpy, window);
211 }