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