X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fhelix.c;h=9e28c9fd07f7ecad9351e34a5cbce9e23abd4224;hp=7ca03da7760377aed93d87006bac39bb71ae977d;hb=49f5b54f312fe4ac2e9bc47581a72451bd0e8439;hpb=ccb7f4903325f92555a9722bba74b58346654ba0 diff --git a/hacks/helix.c b/hacks/helix.c index 7ca03da7..9e28c9fd 100644 --- a/hacks/helix.c +++ b/hacks/helix.c @@ -1,5 +1,4 @@ -/* xscreensaver, Copyright (c) 1992, 1995, 1996, 1997 - * Jamie Zawinski +/* xscreensaver, Copyright (c) 1992-2006 Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -26,33 +25,58 @@ #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; -static int subdelay; +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 @@ -69,254 +93,260 @@ gcd (int a, int b) } 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; - - /* if we sleep every time, it's too slow */ - if(subdelay && i%16 == 0) usleep(subdelay); - - 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; - - /* this draws faster, so we sleep somewhat more often */ - if(subdelay && d_angle%4 == 0) usleep(subdelay); - - /* without this, the subdelay effect is lost */ - XFlush (dpy); + 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, False); - screenhack_handle_events (dpy); - 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; +} - screenhack_handle_events (dpy); - 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, False); - screenhack_handle_events (dpy); - sleep (1); +static void +helix_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); } - -char *progclass = "Helix"; -char *defaults [] = { + +static const char *helix_defaults [] = { ".background: black", + ".foreground: white", "*delay: 5", - "*subdelay: 0", + "*subdelay: 20000", 0 }; -XrmOptionDescRec options [] = { +static XrmOptionDescRec helix_options [] = { { "-delay", ".delay", XrmoptionSepArg, 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"); - subdelay = get_integer_resource("subdelay", "Integer"); - init_helix (dpy, window); - while (1) - random_helix_or_trig (dpy, window); -} +XSCREENSAVER_MODULE ("Helix", helix)