diff options
author | Simon Rettberg | 2018-10-16 10:08:48 +0200 |
---|---|---|
committer | Simon Rettberg | 2018-10-16 10:08:48 +0200 |
commit | d3a98cf6cbc3bd0b9efc570f58e8812c03931c18 (patch) | |
tree | cbddf8e50f35a9c6e878a5bfe3c6d625d99e12ba /hacks/helix.c | |
download | xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.gz xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.xz xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.zip |
Original 5.40
Diffstat (limited to 'hacks/helix.c')
-rw-r--r-- | hacks/helix.c | 356 |
1 files changed, 356 insertions, 0 deletions
diff --git a/hacks/helix.c b/hacks/helix.c new file mode 100644 index 0000000..0fdaa90 --- /dev/null +++ b/hacks/helix.c @@ -0,0 +1,356 @@ +/* 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 + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. No representations are made about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + */ + +/* Algorithm from a Mac program by Chris Tate, written in 1988 or so. */ + +/* 18-Sep-97: Johannes Keukelaar (johannes@nada.kth.se): Improved screen + * eraser. + * 10-May-97: merged ellipse code by Dan Stromberg <strombrg@nis.acs.uci.edu> + * as found in xlockmore 4.03a10. + * 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" + +enum draw_state { HELIX, DRAW_HELIX, TRIG, DRAW_TRIG, LINGER, ERASE }; + +struct state { + enum draw_state dstate; + double sins [360]; + double coss [360]; + + 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; + + st->sleep_time = get_integer_resource(dpy, "delay", "Integer"); + st->subdelay = get_integer_resource(dpy, "subdelay", "Integer"); + + XGetWindowAttributes (dpy, window, &xgwa); + 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++) + { + 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 +gcd (int a, int b) +{ + while (b > 0) + { + int tmp; + tmp = a % b; + a = b; + b = tmp; + } + return (a < 0 ? -a : a); +} + +static void +helix (Display *dpy, Window window, struct state *st) +{ + int xmid = st->width / 2; + int ymid = st->height / 2; + int limit = 1 + (360 / gcd (360, st->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 (st->i = 0; st->i < limit; st->i++)*/ + { + int tmp; +#define pmod(x,y) (tmp=((x) % (y)), (tmp >= 0 ? tmp : (tmp + (y)))) + + 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, struct state *st) +{ + int xmid = st->width / 2; + int ymid = st->height / 2; + +/* while (st->d_angle >= -360 && st->d_angle <= 360)*/ + { + 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 */ + 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, struct state *st, + XColor *color, Bool *got_color) +{ + int radius; + double divisor; + + radius = min (st->width, st->height) / 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) + { + st->radius1 = radius; + st->radius2 = radius / divisor; + } + else + { + st->radius2 = radius; + st->radius1 = radius / divisor; + } + + 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 (st->factor1, st->factor2), st->factor3), st->factor4) != 1) + { + st->factor1 = random_factor (); + st->factor2 = random_factor (); + st->factor3 = random_factor (); + st->factor4 = random_factor (); + } + + if (mono_p) + 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, st->cmap, color))) + XSetForeground (dpy, st->draw_gc, color->pixel); + else + XSetForeground (dpy, st->draw_gc, st->default_fg_pixel); + } + + XClearWindow (dpy, window); +} + +static void +random_trig (Display *dpy, Window window, struct state *st, + XColor *color, Bool *got_color) +{ + st->d_angle = 0; + st->factor1 = (random() % 8) + 1; + do { + st->factor2 = (random() % 8) + 1; + } while (st->factor1 == st->factor2); + + 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, 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, st->cmap, color))) + XSetForeground (dpy, st->draw_gc, color->pixel); + else + XSetForeground (dpy, st->draw_gc, st->default_fg_pixel); + } + + XClearWindow (dpy, 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 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(); + } + + END: + return delay; +} + +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; +} + +static Bool +helix_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +helix_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + + +static const char *helix_defaults [] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*delay: 5", + "*subdelay: 20000", +#ifdef HAVE_MOBILE + "*ignoreRotation: True", +#endif + 0 +}; + +static XrmOptionDescRec helix_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-subdelay", ".subdelay", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 }, +}; + +XSCREENSAVER_MODULE ("Helix", helix) |