1 /* The Spiral Generator, Copyright (c) 2000
2 * by Rohit Singh <rohit_singh@hotmail.com>
4 * Contains code from / To be used with:
5 * xscreensaver, Copyright (c) 1992, 1995, 1996, 1997
6 * Jamie Zawinski <jwz@jwz.org>
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
16 * Modified (Dec 2001) by Matthew Strait <straitm@mathcs.carleton.edu>
17 * Added -subdelay and -alwaysfinish
18 * Prevented redrawing over existing lines
22 #include "screenhack.h"
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;
33 init_tsg (Display *dpy, Window window)
37 XWindowAttributes xgwa;
39 XGetWindowAttributes (dpy, window, &xgwa);
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);
49 go (Display *dpy, Window window,
50 int radius1, int radius2,
53 XWindowAttributes xgwa;
57 float firstx = 0, firsty = 0;
62 XGetWindowAttributes (dpy, window, &xgwa);
69 x1 = xmid + radius1 - radius2 + d;
73 for (theta = 1; /* theta < ( 360 * 100 ) */; theta++)
74 /* see below about alwaysfinish */
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. */
109 /*makes integers from the calculated values to do the drawing*/
113 /*stores the first values for later reference*/
120 XDrawLine (dpy, window, draw_gc, x1, y1, x2, y2);
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)
132 /* this will break after 36000 iterations if
133 the -alwaysfinish option is not specified */
134 if(!always_finish_p && theta > ( 360 * 100 ) )
137 /* usleeping every time is too slow */
139 usleep(sub_sleep_time);
144 #define min(a,b) ((a)<(b)?(a):(b))
147 getset (Display *dpy, Window window, XColor *color, Bool *got_color)
151 int radius, radius1, radius2;
153 XWindowAttributes xgwa;
157 XGetWindowAttributes (dpy, window, &xgwa);
159 height = xgwa.height;
160 cmap = xgwa.colormap;
162 radius = min (width, height) / 2;
164 XClearWindow (dpy, window);
167 for(counter = 0; counter < num_layers; counter++)
169 divisor = ((frand (3.0) + 1) * (((random() & 1) * 2) - 1));
172 radius2 = radius / divisor + 5;
173 distance = 100 + (random() % 200);
176 XSetForeground (dpy, draw_gc, default_fg_pixel);
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);
184 XSetForeground (dpy, draw_gc, default_fg_pixel);
187 go (dpy, window, radius1, -radius2, distance);
189 /* once again, with a parameter negated, just for kicks */
191 XSetForeground (dpy, draw_gc, default_fg_pixel);
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);
199 XSetForeground (dpy, draw_gc, default_fg_pixel);
202 go (dpy, window, radius1, radius2, distance);
207 getset_go (Display *dpy, Window window)
209 Bool free_color = False;
213 XWindowAttributes xgwa;
216 XGetWindowAttributes (dpy, window, &xgwa);
219 height = xgwa.height;
220 cmap = xgwa.colormap;
222 getset(dpy, window, &color, &free_color);
225 screenhack_handle_events (dpy);
226 sleep ( sleep_time );
228 screenhack_handle_events (dpy);
229 erase_full_window(dpy, window);
231 if (free_color) XFreeColors (dpy, cmap, &color.pixel, 1, 0);
233 screenhack_handle_events (dpy);
237 char *progclass = "XSpiroGraph";
239 char *defaults [] = {
240 ".background: black",
244 "*alwaysfinish: false",
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"},
256 int options_size = (sizeof (options) / sizeof (options[0]));
259 screenhack (Display *dpy, Window window)
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");
266 init_tsg (dpy, window);
268 getset_go (dpy, window);