http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.01.tar.gz
[xscreensaver] / hacks / xspirograph.c
1 /* The Spiral Generator, Copyright (c) 2000 
2  * by Rohit Singh <rohit_singh@hotmail.com>
3  * 
4  * Contains code from / To be used with:
5  * xscreensaver, Copyright (c) 1992, 1995, 1996, 1997
6  * Jamie Zawinski <jwz@jwz.org>
7  *
8  * Permission to use, copy, modify, distribute, and sell this software and its
9  * documentation for any purpose is hereby granted without fee, provided that
10  * the above copyright notices appear in all copies and that both that
11  * copyright notices and this permission notice appear in supporting
12  * documentation.  No representations are made about the suitability of this
13  * software for any purpose.  It is provided "as is" without express or 
14  * implied warranty.
15  *
16  * Modified (Dec 2001) by Matthew Strait <straitm@mathcs.carleton.edu>
17  * Added -subdelay and -alwaysfinish
18  * Prevented redrawing over existing lines
19  */
20
21 #include <math.h>
22 #include "screenhack.h"
23 #include "erase.h"
24
25 static GC       draw_gc;
26 static int      sleep_time;
27 static int      sub_sleep_time;
28 static int      num_layers;
29 static unsigned int default_fg_pixel;
30 static Bool     always_finish_p;
31
32 static void
33 init_tsg (Display *dpy, Window window)
34 {
35   XGCValues     gcv;
36   Colormap      cmap;
37   XWindowAttributes xgwa;
38
39   XGetWindowAttributes (dpy, window, &xgwa);
40   cmap = xgwa.colormap;
41   gcv.foreground = default_fg_pixel =
42     get_pixel_resource ("foreground", "Foreground", dpy, cmap);
43   draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
44   gcv.foreground = get_pixel_resource ("background", "Background", dpy, cmap);
45 }
46
47
48 static void
49 go (Display *dpy, Window window,
50        int radius1, int radius2,
51        int d)
52 {
53   XWindowAttributes xgwa;
54   int width, height;
55   int xmid, ymid;
56   int x1, y1, x2, y2;
57   float firstx = 0, firsty = 0;
58   float tmpx, tmpy;
59   int theta;
60   int delta;
61
62   XGetWindowAttributes (dpy, window, &xgwa);
63   width  = xgwa.width;
64   height = xgwa.height;
65   delta = 1;
66   xmid = width / 2;
67   ymid = height / 2;
68
69   x1 = xmid + radius1 - radius2 + d;
70   y1 = ymid;
71
72
73   for (theta = 1; /* theta < ( 360 * 100 ) */; theta++) 
74                   /* see below about alwaysfinish */
75     {
76         tmpx = xmid + ((       radius1            /* * * * *            */
77                   - radius2        )             /* This algo simulates */
78                   * cos((      theta            /* the rotation of a    */
79                   * M_PI           )            /* circular disk inside */
80                   / 180           ))            /* a hollow circular    */
81                   + (              d            /* rim. A point on the  */
82                   * cos((((  radius1            /* disk dist d from the */
83                   * theta          )            /* centre, traces the   */
84                   - delta          )            /* path given by this   */
85                   / radius2        )            /* equation.            */
86                   *             M_PI            /* A deviation (error)  */
87                   / 180            )            /* of delta needs to be */
88                                    );           /* given, which greatly */
89                                                 /* adds to the beauty   */
90         tmpy = ymid + (                         /* of the figure.       */
91                      ( radius1 - radius2        /*                      */
92                       ) * sin                   /* Imperfection adds to */
93                        (                        /* beauty, symbolically */
94                         ( theta * M_PI          /* ...                  */
95                          ) / 180                /* Algo deduced by      */
96                           )                     /* Rohit Singh, Jan'00  */
97                            ) +                  /* based on a toy he    */
98                             ( d * sin           /* used to play with    */
99                              (                  /* when he was a kid.  */
100                               (                 /*            * * * * */
101                                (                
102                                 ( radius1 * theta
103                                  ) - delta
104                                   ) / radius2
105                                    ) * M_PI / 180
106                                     )
107                                      );
108         
109         /*makes integers from the calculated values to do the drawing*/
110         x2 = tmpx;
111         y2 = tmpy;
112
113         /*stores the first values for later reference*/
114         if(theta == 1)
115         {
116                 firstx = tmpx;
117                 firsty = tmpy;
118         }
119
120         XDrawLine (dpy, window, draw_gc, x1, y1, x2, y2);
121
122         x1 = x2;
123         y1 = y2;
124         XFlush (dpy);
125
126         /* compares the exact values calculated to the first
127            exact values calculated */
128         /* this will break when nothing new is being drawn */
129         if(tmpx == firstx && tmpy == firsty && theta != 1)
130                 break;
131
132         /* this will break after 36000 iterations if 
133            the -alwaysfinish option is not specified */
134         if(!always_finish_p && theta > ( 360 * 100 ) )
135                 break;
136
137         /* usleeping every time is too slow */
138         if(theta%100 == 0)
139                 usleep(sub_sleep_time);
140     }   
141 }
142
143
144 #define min(a,b) ((a)<(b)?(a):(b))
145
146 static void
147 getset (Display *dpy, Window window, XColor *color, Bool *got_color)
148 {
149   Colormap cmap;
150   int width, height;
151   int radius, radius1, radius2;
152   double divisor;
153   XWindowAttributes xgwa;
154   int distance;
155   int counter = 0;
156
157   XGetWindowAttributes (dpy, window, &xgwa);
158   width = xgwa.width;
159   height = xgwa.height;
160   cmap = xgwa.colormap;
161
162   radius = min (width, height) / 2;
163
164   XClearWindow (dpy, window);
165
166
167   for(counter = 0; counter < num_layers; counter++)
168   {
169     divisor = ((frand (3.0) + 1) * (((random() & 1) * 2) - 1));
170
171     radius1 = radius;
172     radius2 = radius / divisor + 5;
173     distance = 100 + (random() % 200);
174
175     if (mono_p)
176       XSetForeground (dpy, draw_gc, default_fg_pixel);
177     else
178     {
179       hsv_to_rgb (random () % 360, frand (1.0), frand (0.5) + 0.5,
180                   &color->red, &color->green, &color->blue);
181       if ((*got_color = XAllocColor (dpy, cmap, color)))
182         XSetForeground (dpy, draw_gc, color->pixel);
183       else
184         XSetForeground (dpy, draw_gc, default_fg_pixel);
185     }
186
187     go (dpy, window, radius1, -radius2, distance);
188
189     /* once again, with a parameter negated, just for kicks */
190     if (mono_p)
191       XSetForeground (dpy, draw_gc, default_fg_pixel);
192     else
193     {
194       hsv_to_rgb (random () % 360, frand (1.0), frand (0.5) + 0.5,
195                   &color->red, &color->green, &color->blue);
196       if ((*got_color = XAllocColor (dpy, cmap, color)))
197         XSetForeground (dpy, draw_gc, color->pixel);
198       else
199         XSetForeground (dpy, draw_gc, default_fg_pixel);
200     }
201
202     go (dpy, window, radius1, radius2, distance);
203   }
204 }
205
206 static void
207 getset_go (Display *dpy, Window window)
208 {
209   Bool          free_color = False;
210   XColor        color;
211   int           width;
212   int           height;
213   XWindowAttributes xgwa;
214   Colormap      cmap;
215
216   XGetWindowAttributes (dpy, window, &xgwa);
217
218   width  = xgwa.width;
219   height = xgwa.height;
220   cmap   = xgwa.colormap;
221
222   getset(dpy, window, &color, &free_color);
223
224   XSync (dpy, False);
225   screenhack_handle_events (dpy);
226   sleep ( sleep_time );
227
228   screenhack_handle_events (dpy);
229   erase_full_window(dpy, window);
230
231   if (free_color) XFreeColors (dpy, cmap, &color.pixel, 1, 0);
232   XSync (dpy, False);
233   screenhack_handle_events (dpy);
234   sleep (1);
235 }
236
237 char *progclass = "XSpiroGraph";
238
239 char *defaults [] = {
240   ".background:         black",
241   "*delay:              5",
242   "*subdelay:           0",
243   "*layers:             1",
244   "*alwaysfinish:       false",
245   0
246 };
247
248 XrmOptionDescRec options [] = {   
249   { "-delay",           ".delay",               XrmoptionSepArg, 0 },
250   { "-subdelay",        ".subdelay",            XrmoptionSepArg, 0 },
251   { "-layers",          ".layers",              XrmoptionSepArg, 0 },
252   { "-alwaysfinish",    ".alwaysfinish",        XrmoptionNoArg, "true"},
253   { "-noalwaysfinish",  ".alwaysfinish",        XrmoptionNoArg, "false"},
254   { 0, 0, 0, 0 }
255 };
256 int options_size = (sizeof (options) / sizeof (options[0]));
257
258 void
259 screenhack (Display *dpy, Window window)
260 {
261   sleep_time = get_integer_resource("delay", "Integer");
262   sub_sleep_time = get_integer_resource("subdelay", "Integer");
263   num_layers = get_integer_resource("layers", "Integer");
264   always_finish_p = get_boolean_resource ("alwaysfinish", "Boolean");
265   
266   init_tsg (dpy, window);
267   while (1)
268    getset_go (dpy, window);
269 }