source: trunk/third/xscreensaver/hacks/helix.c @ 20148

Revision 20148, 8.4 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20147, which included commits to RCS files with non-trunk default branches.
Line 
1/* xscreensaver, Copyright (c) 1992, 1995, 1996, 1997
2 *  Jamie Zawinski <jwz@jwz.org>
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation.  No representations are made about the suitability of this
9 * software for any purpose.  It is provided "as is" without express or
10 * implied warranty.
11 */
12
13/* Algorithm from a Mac program by Chris Tate, written in 1988 or so. */
14
15/* 18-Sep-97: Johannes Keukelaar (johannes@nada.kth.se): Improved screen
16 *            eraser.
17 * 10-May-97: merged ellipse code by Dan Stromberg <strombrg@nis.acs.uci.edu>
18 *            as found in xlockmore 4.03a10.
19 * 1992:      jwz created.
20 */
21
22/* 25 April 2002: Matthew Strait <straitm@mathcs.carleton.edu> added
23-subdelay option so the drawing process can be watched */
24
25#include <math.h>
26#include "screenhack.h"
27#include "erase.h"
28
29static double sins [360];
30static double coss [360];
31
32static GC draw_gc;
33static unsigned int default_fg_pixel;
34static int sleep_time;
35static int subdelay;
36
37static void
38init_helix (Display *dpy, Window window)
39{
40  int i;
41  XGCValues gcv;
42  XWindowAttributes xgwa;
43  Colormap cmap;
44  XGetWindowAttributes (dpy, window, &xgwa);
45  cmap = xgwa.colormap;
46  gcv.foreground = default_fg_pixel =
47    get_pixel_resource ("foreground", "Foreground", dpy, cmap);
48  draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
49  gcv.foreground = get_pixel_resource ("background", "Background", dpy, cmap);
50
51  for (i = 0; i < 360; i++)
52    {
53      sins [i] = sin ((((double) i) / 180.0) * M_PI);
54      coss [i] = cos ((((double) i) / 180.0) * M_PI);
55    }
56}
57
58static int
59gcd (int a, int b)
60{
61  while (b > 0)
62    {
63      int tmp;
64      tmp = a % b;
65      a = b;
66      b = tmp;
67    }
68  return (a < 0 ? -a : a);
69}
70
71static void
72helix (Display *dpy, Window window,
73       int radius1, int radius2, int d_angle,
74       int factor1, int factor2, int factor3, int factor4)
75{
76  XWindowAttributes xgwa;
77  int width, height;
78  int xmid, ymid;
79  int x1, y1, x2, y2, angle, limit;
80  int i;
81
82  XClearWindow (dpy, window);
83  XGetWindowAttributes (dpy, window, &xgwa);
84  width = xgwa.width;
85  height = xgwa.height;
86
87  xmid = width / 2;
88  ymid = height / 2;
89  x1 = xmid;
90  y1 = ymid + radius2;
91  x2 = xmid;
92  y2 = ymid + radius1;
93  angle = 0;
94  limit = 1 + (360 / gcd (360, d_angle));
95 
96  for (i = 0; i < limit; i++)
97    {
98      int tmp;
99#define pmod(x,y) (tmp=((x) % (y)), (tmp >= 0 ? tmp : (tmp + (y))))
100
101      x1 = xmid + (((double) radius1) * sins [pmod ((angle * factor1), 360)]);
102      y1 = ymid + (((double) radius2) * coss [pmod ((angle * factor2), 360)]);
103      XDrawLine (dpy, window, draw_gc, x1, y1, x2, y2);
104      x2 = xmid + (((double) radius2) * sins [pmod ((angle * factor3), 360)]);
105      y2 = ymid + (((double) radius1) * coss [pmod ((angle * factor4), 360)]);
106      XDrawLine (dpy, window, draw_gc, x1, y1, x2, y2);
107      angle += d_angle;
108
109      /* if we sleep every time, it's too slow */
110      if(subdelay && i%16 == 0) usleep(subdelay);
111
112      XFlush (dpy);
113    }
114}
115
116static void
117trig (Display *dpy, Window window,
118      int d_angle, int factor1, int factor2,
119      int offset, int d_angle_offset, int dir, int density)
120{
121  XWindowAttributes xgwa;
122  int width, height;
123  int xmid, ymid;
124  int x1, y1, x2, y2;
125  int tmp, angle;
126  Colormap cmap;
127
128  XClearWindow (dpy, window);
129  XGetWindowAttributes (dpy, window, &xgwa);
130  cmap = xgwa.colormap;
131  width = xgwa.width;
132  height = xgwa.height;
133
134  xmid = width / 2;
135  ymid = height / 2;
136
137  while (d_angle >= -360 && d_angle <= 360)
138    {
139      angle = d_angle + d_angle_offset;
140      x1 = (sins [pmod(angle * factor1, 360)] * xmid) + xmid;
141      y1 = (coss [pmod(angle * factor1, 360)] * ymid) + ymid;
142      x2 = (sins [pmod(angle * factor2 + offset, 360)] * xmid) + xmid;
143      y2 = (coss [pmod(angle * factor2 + offset, 360)] * ymid) + ymid;
144      XDrawLine(dpy, window, draw_gc, x1, y1, x2, y2);
145      tmp = (int) 360 / (2 * density * factor1 * factor2);
146      if (tmp == 0)     /* Do not want it getting stuck... */
147        tmp = 1;        /* Would not need if floating point */
148      d_angle += dir * tmp;
149
150      /* this draws faster, so we sleep somewhat more often */
151      if(subdelay && d_angle%4 == 0) usleep(subdelay);
152     
153      /* without this, the subdelay effect is lost */
154      XFlush (dpy);
155    }
156}
157
158#define min(a,b) ((a)<(b)?(a):(b))
159
160static void
161random_helix (Display *dpy, Window window, XColor *color, Bool *got_color)
162{
163  Colormap cmap;
164  int width, height;
165  int radius, radius1, radius2, d_angle, factor1, factor2, factor3, factor4;
166  double divisor;
167  XWindowAttributes xgwa;
168  XGetWindowAttributes (dpy, window, &xgwa);
169  width = xgwa.width;
170  height = xgwa.height;
171  cmap = xgwa.colormap;
172
173  radius = min (width, height) / 2;
174
175  d_angle = 0;
176  factor1 = 2;
177  factor2 = 2;
178  factor3 = 2;
179  factor4 = 2;
180
181  divisor = ((frand (3.0) + 1) * (((random() & 1) * 2) - 1));
182
183  if ((random () & 1) == 0)
184    {
185      radius1 = radius;
186      radius2 = radius / divisor;
187    }
188  else
189    {
190      radius2 = radius;
191      radius1 = radius / divisor;
192    }
193
194  while (gcd (360, d_angle) >= 2)
195    d_angle = random () % 360;
196
197#define random_factor()                         \
198  (((random() % 7) ? ((random() & 1) + 1) : 3)  \
199   * (((random() & 1) * 2) - 1))
200
201  while (gcd (gcd (gcd (factor1, factor2), factor3), factor4) != 1)
202    {
203      factor1 = random_factor ();
204      factor2 = random_factor ();
205      factor3 = random_factor ();
206      factor4 = random_factor ();
207    }
208
209  if (mono_p)
210    XSetForeground (dpy, draw_gc, default_fg_pixel);
211  else
212    {
213      hsv_to_rgb (random () % 360, frand (1.0), frand (0.5) + 0.5,
214                  &color->red, &color->green, &color->blue);
215      if ((*got_color = XAllocColor (dpy, cmap, color)))
216        XSetForeground (dpy, draw_gc, color->pixel);
217      else
218        XSetForeground (dpy, draw_gc, default_fg_pixel);
219    }
220  helix (dpy, window, radius1, radius2, d_angle,
221         factor1, factor2, factor3, factor4);
222}
223
224static void
225random_trig (Display *dpy, Window window, XColor *color, Bool *got_color)
226{
227  Colormap cmap;
228  int width, height;
229  int radius, d_angle, factor1, factor2;
230  int offset, d_angle_offset, dir, density;
231
232  XWindowAttributes xgwa;
233  XGetWindowAttributes (dpy, window, &xgwa);
234  width = xgwa.width;
235  height = xgwa.height;
236  cmap = xgwa.colormap;
237
238  radius = min (width, height) / 2;
239
240  d_angle = 0;
241  factor1 = (random() % 8) + 1;
242  do {
243    factor2 = (random() % 8) + 1;
244  } while (factor1 == factor2);
245
246  dir = (random() & 1) ? 1 : -1;
247  d_angle_offset = random() % 360;
248  offset = ((random() % ((360 / 4) - 1)) + 1) / 4;
249  density = 1 << ((random() % 4) + 4);  /* Higher density, higher angles */
250
251  if (mono_p)
252    XSetForeground (dpy, draw_gc, default_fg_pixel);
253  else
254    {
255      hsv_to_rgb (random () % 360, frand (1.0), frand (0.5) + 0.5,
256                  &color->red, &color->green, &color->blue);
257      if ((*got_color = XAllocColor (dpy, cmap, color)))
258        XSetForeground (dpy, draw_gc, color->pixel);
259      else
260        XSetForeground (dpy, draw_gc, default_fg_pixel);
261    }
262  trig (dpy, window, d_angle, factor1, factor2,
263        offset, d_angle_offset, dir, density);
264}
265
266static void
267random_helix_or_trig (Display *dpy, Window window)
268{
269  Bool free_color = False;
270  XColor color;
271  int width, height;
272  XWindowAttributes xgwa;
273  Colormap cmap;
274  XGetWindowAttributes (dpy, window, &xgwa);
275  width = xgwa.width;
276  height = xgwa.height;
277  cmap = xgwa.colormap;
278
279  if (random() & 1)
280    random_helix(dpy, window, &color, &free_color);
281  else
282    random_trig(dpy, window, &color, &free_color);
283
284  XSync (dpy, False);
285  screenhack_handle_events (dpy);
286  sleep ( sleep_time );
287
288  screenhack_handle_events (dpy);
289  erase_full_window(dpy, window);
290
291  if (free_color) XFreeColors (dpy, cmap, &color.pixel, 1, 0);
292  XSync (dpy, False);
293  screenhack_handle_events (dpy);
294  sleep (1);
295}
296
297
298char *progclass = "Helix";
299
300char *defaults [] = {
301  ".background: black",
302  "*delay:      5",
303  "*subdelay:   0",
304  0
305};
306
307XrmOptionDescRec options [] = {   
308  { "-delay",           ".delay",               XrmoptionSepArg, 0 },
309  { "-subdelay",        ".subdelay",            XrmoptionSepArg, 0 },
310  { 0,                  0,                      0,               0 },
311};
312int options_size = (sizeof (options) / sizeof (options[0]));
313
314void
315screenhack (Display *dpy, Window window)
316{
317  sleep_time = get_integer_resource("delay", "Integer");
318  subdelay = get_integer_resource("subdelay", "Integer");
319  init_helix (dpy, window);
320  while (1)
321    random_helix_or_trig (dpy, window);
322}
Note: See TracBrowser for help on using the repository browser.