-/* xscreensaver, Copyright (c) 1992, 1995, 1996, 1997
- * Jamie Zawinski <jwz@netscape.com>
+/* xscreensaver, Copyright (c) 1992-2008 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* 1992: jwz created.
*/
+/* 25 April 2002: Matthew Strait <straitm@mathcs.carleton.edu> added
+-subdelay option so the drawing process can be watched */
+
#include <math.h>
#include "screenhack.h"
#include "erase.h"
-static double sins [360];
-static double coss [360];
+enum draw_state { HELIX, DRAW_HELIX, TRIG, DRAW_TRIG, LINGER, ERASE };
-static GC draw_gc;
-static unsigned int default_fg_pixel;
-static int sleep_time;
+struct state {
+ enum draw_state dstate;
+ double sins [360];
+ double coss [360];
-static void
-init_helix (Display *dpy, Window window)
+ GC draw_gc;
+ unsigned int default_fg_pixel;
+ int sleep_time;
+ int subdelay;
+ eraser_state *eraser;
+
+ int width, height;
+ Colormap cmap;
+
+ int x1, y1, x2, y2, angle, i;
+
+ int radius1, radius2, d_angle, factor1, factor2, factor3, factor4;
+ int d_angle_offset;
+ int offset, dir, density;
+};
+
+static void *
+helix_init (Display *dpy, Window window)
{
+ struct state *st = (struct state *) calloc (1, sizeof(*st));
int i;
XGCValues gcv;
XWindowAttributes xgwa;
- Colormap cmap;
+
+ st->sleep_time = get_integer_resource(dpy, "delay", "Integer");
+ st->subdelay = get_integer_resource(dpy, "subdelay", "Integer");
+
XGetWindowAttributes (dpy, window, &xgwa);
- cmap = xgwa.colormap;
- gcv.foreground = default_fg_pixel =
- get_pixel_resource ("foreground", "Foreground", dpy, cmap);
- draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
- gcv.foreground = get_pixel_resource ("background", "Background", dpy, cmap);
+ st->width = xgwa.width;
+ st->height = xgwa.height;
+ st->cmap = xgwa.colormap;
+ gcv.foreground = st->default_fg_pixel =
+ get_pixel_resource (dpy, st->cmap, "foreground", "Foreground");
+ st->draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+ gcv.foreground = get_pixel_resource (dpy, st->cmap, "background", "Background");
for (i = 0; i < 360; i++)
{
- sins [i] = sin ((((double) i) / 180.0) * M_PI);
- coss [i] = cos ((((double) i) / 180.0) * M_PI);
+ st->sins [i] = sin ((((double) i) / 180.0) * M_PI);
+ st->coss [i] = cos ((((double) i) / 180.0) * M_PI);
}
+
+ st->dstate = (random() & 1) ? HELIX : TRIG;
+
+ return st;
}
static int
}
static void
-helix (Display *dpy, Window window,
- int radius1, int radius2, int d_angle,
- int factor1, int factor2, int factor3, int factor4)
+helix (Display *dpy, Window window, struct state *st)
{
- XWindowAttributes xgwa;
- int width, height;
- int xmid, ymid;
- int x1, y1, x2, y2, angle, limit;
- int i;
+ int xmid = st->width / 2;
+ int ymid = st->height / 2;
+ int limit = 1 + (360 / gcd (360, st->d_angle));
- XClearWindow (dpy, window);
- XGetWindowAttributes (dpy, window, &xgwa);
- width = xgwa.width;
- height = xgwa.height;
-
- xmid = width / 2;
- ymid = height / 2;
- x1 = xmid;
- y1 = ymid + radius2;
- x2 = xmid;
- y2 = ymid + radius1;
- angle = 0;
- limit = 1 + (360 / gcd (360, d_angle));
+ if (st->i == 0)
+ {
+ st->x1 = xmid;
+ st->y1 = ymid + st->radius2;
+ st->x2 = xmid;
+ st->y2 = ymid + st->radius1;
+ st->angle = 0;
+ }
- for (i = 0; i < limit; i++)
+/* for (st->i = 0; st->i < limit; st->i++)*/
{
int tmp;
#define pmod(x,y) (tmp=((x) % (y)), (tmp >= 0 ? tmp : (tmp + (y))))
- x1 = xmid + (((double) radius1) * sins [pmod ((angle * factor1), 360)]);
- y1 = ymid + (((double) radius2) * coss [pmod ((angle * factor2), 360)]);
- XDrawLine (dpy, window, draw_gc, x1, y1, x2, y2);
- x2 = xmid + (((double) radius2) * sins [pmod ((angle * factor3), 360)]);
- y2 = ymid + (((double) radius1) * coss [pmod ((angle * factor4), 360)]);
-
- XDrawLine (dpy, window, draw_gc, x1, y1, x2, y2);
- angle += d_angle;
- XFlush (dpy);
+ st->x1 = xmid + (((double) st->radius1) * st->sins [pmod ((st->angle * st->factor1), 360)]);
+ st->y1 = ymid + (((double) st->radius2) * st->coss [pmod ((st->angle * st->factor2), 360)]);
+ XDrawLine (dpy, window, st->draw_gc, st->x1, st->y1, st->x2, st->y2);
+ st->x2 = xmid + (((double) st->radius2) * st->sins [pmod ((st->angle * st->factor3), 360)]);
+ st->y2 = ymid + (((double) st->radius1) * st->coss [pmod ((st->angle * st->factor4), 360)]);
+ XDrawLine (dpy, window, st->draw_gc, st->x1, st->y1, st->x2, st->y2);
+ st->angle += st->d_angle;
}
+ st->i++;
+
+ if (st->i >= limit)
+ st->dstate = LINGER;
}
static void
-trig (Display *dpy, Window window,
- int d_angle, int factor1, int factor2,
- int offset, int d_angle_offset, int dir, int density)
+trig (Display *dpy, Window window, struct state *st)
{
- XWindowAttributes xgwa;
- int width, height;
- int xmid, ymid;
- int x1, y1, x2, y2;
- int tmp, angle;
- Colormap cmap;
+ int xmid = st->width / 2;
+ int ymid = st->height / 2;
- XClearWindow (dpy, window);
- XGetWindowAttributes (dpy, window, &xgwa);
- cmap = xgwa.colormap;
- width = xgwa.width;
- height = xgwa.height;
-
- xmid = width / 2;
- ymid = height / 2;
-
- while (d_angle >= -360 && d_angle <= 360)
+/* while (st->d_angle >= -360 && st->d_angle <= 360)*/
{
- angle = d_angle + d_angle_offset;
- x1 = (sins [pmod(angle * factor1, 360)] * xmid) + xmid;
- y1 = (coss [pmod(angle * factor1, 360)] * ymid) + ymid;
- x2 = (sins [pmod(angle * factor2 + offset, 360)] * xmid) + xmid;
- y2 = (coss [pmod(angle * factor2 + offset, 360)] * ymid) + ymid;
- XDrawLine(dpy, window, draw_gc, x1, y1, x2, y2);
- tmp = (int) 360 / (2 * density * factor1 * factor2);
+ int tmp;
+ int angle = st->d_angle + st->d_angle_offset;
+ st->x1 = (st->sins [pmod(angle * st->factor1, 360)] * xmid) + xmid;
+ st->y1 = (st->coss [pmod(angle * st->factor1, 360)] * ymid) + ymid;
+ st->x2 = (st->sins [pmod(angle * st->factor2 + st->offset, 360)] * xmid) + xmid;
+ st->y2 = (st->coss [pmod(angle * st->factor2 + st->offset, 360)] * ymid) + ymid;
+ XDrawLine(dpy, window, st->draw_gc, st->x1, st->y1, st->x2, st->y2);
+ tmp = (int) 360 / (2 * st->density * st->factor1 * st->factor2);
if (tmp == 0) /* Do not want it getting stuck... */
tmp = 1; /* Would not need if floating point */
- d_angle += dir * tmp;
+ st->d_angle += st->dir * tmp;
}
+
+ if (st->d_angle < -360 || st->d_angle > 360)
+ st->dstate = LINGER;
}
+
#define min(a,b) ((a)<(b)?(a):(b))
static void
-random_helix (Display *dpy, Window window, XColor *color, Bool *got_color)
+random_helix (Display *dpy, Window window, struct state *st,
+ XColor *color, Bool *got_color)
{
- Colormap cmap;
- int width, height;
- int radius, radius1, radius2, d_angle, factor1, factor2, factor3, factor4;
+ int radius;
double divisor;
- XWindowAttributes xgwa;
- XGetWindowAttributes (dpy, window, &xgwa);
- width = xgwa.width;
- height = xgwa.height;
- cmap = xgwa.colormap;
- radius = min (width, height) / 2;
+ radius = min (st->width, st->height) / 2;
- d_angle = 0;
- factor1 = 2;
- factor2 = 2;
- factor3 = 2;
- factor4 = 2;
+ st->i = 0;
+ st->d_angle = 0;
+ st->factor1 = 2;
+ st->factor2 = 2;
+ st->factor3 = 2;
+ st->factor4 = 2;
divisor = ((frand (3.0) + 1) * (((random() & 1) * 2) - 1));
if ((random () & 1) == 0)
{
- radius1 = radius;
- radius2 = radius / divisor;
+ st->radius1 = radius;
+ st->radius2 = radius / divisor;
}
else
{
- radius2 = radius;
- radius1 = radius / divisor;
+ st->radius2 = radius;
+ st->radius1 = radius / divisor;
}
- while (gcd (360, d_angle) >= 2)
- d_angle = random () % 360;
+ while (gcd (360, st->d_angle) >= 2)
+ st->d_angle = random () % 360;
#define random_factor() \
(((random() % 7) ? ((random() & 1) + 1) : 3) \
* (((random() & 1) * 2) - 1))
- while (gcd (gcd (gcd (factor1, factor2), factor3), factor4) != 1)
+ while (gcd (gcd (gcd (st->factor1, st->factor2), st->factor3), st->factor4) != 1)
{
- factor1 = random_factor ();
- factor2 = random_factor ();
- factor3 = random_factor ();
- factor4 = random_factor ();
+ st->factor1 = random_factor ();
+ st->factor2 = random_factor ();
+ st->factor3 = random_factor ();
+ st->factor4 = random_factor ();
}
if (mono_p)
- XSetForeground (dpy, draw_gc, default_fg_pixel);
+ XSetForeground (dpy, st->draw_gc, st->default_fg_pixel);
else
{
hsv_to_rgb (random () % 360, frand (1.0), frand (0.5) + 0.5,
&color->red, &color->green, &color->blue);
- if ((*got_color = XAllocColor (dpy, cmap, color)))
- XSetForeground (dpy, draw_gc, color->pixel);
+ if ((*got_color = XAllocColor (dpy, st->cmap, color)))
+ XSetForeground (dpy, st->draw_gc, color->pixel);
else
- XSetForeground (dpy, draw_gc, default_fg_pixel);
+ XSetForeground (dpy, st->draw_gc, st->default_fg_pixel);
}
- helix (dpy, window, radius1, radius2, d_angle,
- factor1, factor2, factor3, factor4);
+
+ XClearWindow (dpy, window);
}
static void
-random_trig (Display *dpy, Window window, XColor *color, Bool *got_color)
+random_trig (Display *dpy, Window window, struct state *st,
+ XColor *color, Bool *got_color)
{
- Colormap cmap;
- int width, height;
- int radius, d_angle, factor1, factor2;
- int offset, d_angle_offset, dir, density;
-
- XWindowAttributes xgwa;
- XGetWindowAttributes (dpy, window, &xgwa);
- width = xgwa.width;
- height = xgwa.height;
- cmap = xgwa.colormap;
-
- radius = min (width, height) / 2;
-
- d_angle = 0;
- factor1 = (random() % 8) + 1;
+ st->d_angle = 0;
+ st->factor1 = (random() % 8) + 1;
do {
- factor2 = (random() % 8) + 1;
- } while (factor1 == factor2);
+ st->factor2 = (random() % 8) + 1;
+ } while (st->factor1 == st->factor2);
- dir = (random() & 1) ? 1 : -1;
- d_angle_offset = random() % 360;
- offset = ((random() % ((360 / 4) - 1)) + 1) / 4;
- density = 1 << ((random() % 4) + 4); /* Higher density, higher angles */
+ st->dir = (random() & 1) ? 1 : -1;
+ st->d_angle_offset = random() % 360;
+ st->offset = ((random() % ((360 / 4) - 1)) + 1) / 4;
+ st->density = 1 << ((random() % 4) + 4); /* Higher density, higher angles */
if (mono_p)
- XSetForeground (dpy, draw_gc, default_fg_pixel);
+ XSetForeground (dpy, st->draw_gc, st->default_fg_pixel);
else
{
hsv_to_rgb (random () % 360, frand (1.0), frand (0.5) + 0.5,
&color->red, &color->green, &color->blue);
- if ((*got_color = XAllocColor (dpy, cmap, color)))
- XSetForeground (dpy, draw_gc, color->pixel);
+ if ((*got_color = XAllocColor (dpy, st->cmap, color)))
+ XSetForeground (dpy, st->draw_gc, color->pixel);
else
- XSetForeground (dpy, draw_gc, default_fg_pixel);
+ XSetForeground (dpy, st->draw_gc, st->default_fg_pixel);
}
- trig (dpy, window, d_angle, factor1, factor2,
- offset, d_angle_offset, dir, density);
+
+ XClearWindow (dpy, window);
}
-static void
-random_helix_or_trig (Display *dpy, Window window)
+
+/* random_helix_or_trig */
+static unsigned long
+helix_draw (Display *dpy, Window window, void *closure)
{
+ struct state *st = (struct state *) closure;
Bool free_color = False;
XColor color;
- int width, height;
- XWindowAttributes xgwa;
- Colormap cmap;
- XGetWindowAttributes (dpy, window, &xgwa);
- width = xgwa.width;
- height = xgwa.height;
- cmap = xgwa.colormap;
+ int delay = st->subdelay;
+ int erase_delay = 10000;
+ int ii;
+
+ if (st->eraser) {
+ st->eraser = erase_window (dpy, window, st->eraser);
+ if (st->eraser)
+ delay = erase_delay;
+ goto END;
+ }
+
+ switch (st->dstate)
+ {
+ case LINGER:
+ delay = st->sleep_time * 1000000;
+ st->dstate = ERASE;
+ break;
+
+ case ERASE:
+ st->eraser = erase_window (dpy, window, st->eraser);
+ delay = erase_delay;
+ if (free_color) XFreeColors (dpy, st->cmap, &color.pixel, 1, 0);
+ st->dstate = (random() & 1) ? HELIX : TRIG;
+ break;
+
+ case DRAW_HELIX:
+ for (ii = 0; ii < 10; ii++) {
+ helix (dpy, window, st);
+ if (st->dstate != DRAW_HELIX)
+ break;
+ }
+ break;
+
+ case DRAW_TRIG:
+ for (ii = 0; ii < 5; ii++) {
+ trig (dpy, window, st);
+ if (st->dstate != DRAW_TRIG)
+ break;
+ }
+ break;
+
+ case HELIX:
+ random_helix (dpy, window, st, &color, &free_color);
+ st->dstate = DRAW_HELIX;
+ break;
+
+ case TRIG:
+ random_trig(dpy, window, st, &color, &free_color);
+ st->dstate = DRAW_TRIG;
+ break;
+
+ default:
+ abort();
+ }
- if (random() & 1)
- random_helix(dpy, window, &color, &free_color);
- else
- random_trig(dpy, window, &color, &free_color);
+ END:
+ return delay;
+}
- XSync (dpy, True);
- sleep ( sleep_time );
+static void
+helix_reshape (Display *dpy, Window window, void *closure,
+ unsigned int w, unsigned int h)
+{
+ struct state *st = (struct state *) closure;
+ st->width = w;
+ st->height = h;
+}
- erase_full_window(dpy, window);
+static Bool
+helix_event (Display *dpy, Window window, void *closure, XEvent *event)
+{
+ return False;
+}
- if (free_color) XFreeColors (dpy, cmap, &color.pixel, 1, 0);
- XSync (dpy, True);
- sleep (1);
+static void
+helix_free (Display *dpy, Window window, void *closure)
+{
+ struct state *st = (struct state *) closure;
+ free (st);
}
-\f
-char *progclass = "Helix";
-char *defaults [] = {
+\f
+static const char *helix_defaults [] = {
".background: black",
+ ".foreground: white",
+ "*fpsSolid: true",
"*delay: 5",
+ "*subdelay: 20000",
+#ifdef USE_IPHONE
+ "*ignoreRotation: True",
+#endif
0
};
-XrmOptionDescRec options [] = {
+static XrmOptionDescRec helix_options [] = {
{ "-delay", ".delay", XrmoptionSepArg, 0 },
- { 0 },
+ { "-subdelay", ".subdelay", XrmoptionSepArg, 0 },
+ { 0, 0, 0, 0 },
};
-int options_size = (sizeof (options) / sizeof (options[0]));
-void
-screenhack (Display *dpy, Window window)
-{
- sleep_time = get_integer_resource("delay", "Integer");
- init_helix (dpy, window);
- while (1)
- random_helix_or_trig (dpy, window);
-}
+XSCREENSAVER_MODULE ("Helix", helix)