From d3a98cf6cbc3bd0b9efc570f58e8812c03931c18 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 16 Oct 2018 10:08:48 +0200 Subject: Original 5.40 --- hacks/flame.c | 466 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 466 insertions(+) create mode 100644 hacks/flame.c (limited to 'hacks/flame.c') diff --git a/hacks/flame.c b/hacks/flame.c new file mode 100644 index 0000000..7b59056 --- /dev/null +++ b/hacks/flame.c @@ -0,0 +1,466 @@ +/* xscreensaver, Copyright (c) 1993-2014 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 + * 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. + */ + +/* This file was ported from xlock for use in xscreensaver (and standalone) + * by jwz on 18-Oct-93. (And again, 11-May-97.) Original copyright reads: + * + * static char sccsid[] = "@(#)flame.c 1.4 91/09/27 XLOCK"; + * + * flame.c - recursive fractal cosmic flames. + * + * Copyright (c) 1991 by Patrick J. Naughton. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Comments and additions should be sent to the author: + * + * naughton@eng.sun.com + * + * Patrick J. Naughton + * MS 21-14 + * Sun Laboritories, Inc. + * 2550 Garcia Ave + * Mountain View, CA 94043 + * + * Revision History: + * 01-Jun-95: This should look more like the original with some updates by + * Scott Draves. + * 27-Jun-91: vary number of functions used. + * 24-Jun-91: fixed portability problem with integer mod (%). + * 06-Jun-91: Written. (received from Scott Draves, spot@cs.cmu.edu). + */ + +#include +#include "screenhack.h" + +#include /* so we can ignore SIGFPE */ + +#define POINT_BUFFER_SIZE 10 +#define MAXLEV 4 +#define MAXKINDS 10 + +struct state { + Display *dpy; + Window window; + + double f[2][3][MAXLEV]; /* three non-homogeneous transforms */ + int max_total; + int max_levels; + int max_points; + int cur_level; + int variation; + int snum; + int anum; + int num_points; + int total_points; + int pixcol; + int ncolors; + XColor *colors; + XPoint points [POINT_BUFFER_SIZE]; + GC gc; + + int delay, delay2; + int width, height; + + short lasthalf; + + int flame_alt; + int do_reset; +}; + + +static short +halfrandom (struct state *st, int mv) +{ + unsigned long r; + + if (st->lasthalf) + { + r = st->lasthalf; + st->lasthalf = 0; + } + else + { + r = random (); + st->lasthalf = r >> 16; + } + return (r % mv); +} + +static void * +flame_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XGCValues gcv; + XWindowAttributes xgwa; + Colormap cmap; + + st->dpy = dpy; + st->window = window; + +#if defined(SIGFPE) && defined(SIG_IGN) + /* No doubt a better fix would be to track down where the NaN is coming + from, and code around that; but this should do. Apparently most systems + (Linux, Solaris, Irix, ...) ignore FPE by default -- but FreeBSD dumps + core by default. */ + signal (SIGFPE, SIG_IGN); +#endif + + XGetWindowAttributes (st->dpy, st->window, &xgwa); + st->width = xgwa.width; + st->height = xgwa.height; + cmap = xgwa.colormap; + + st->max_points = get_integer_resource (st->dpy, "iterations", "Integer"); + if (st->max_points <= 0) st->max_points = 100; + + st->max_levels = st->max_points; + + st->max_total = get_integer_resource (st->dpy, "points", "Integer"); + if (st->max_total <= 0) st->max_total = 10000; + + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + if (st->delay < 0) st->delay = 0; + st->delay2 = get_integer_resource (st->dpy, "delay2", "Integer"); + if (st->delay2 < 0) st->delay2 = 0; + + st->variation = random() % MAXKINDS; + + if (mono_p) + st->ncolors = 0; + else + { + st->ncolors = get_integer_resource (st->dpy, "colors", "Integer"); + if (st->ncolors <= 0) st->ncolors = 128; + st->colors = (XColor *) malloc ((st->ncolors+1) * sizeof (*st->colors)); + make_smooth_colormap (xgwa.screen, xgwa.visual, xgwa.colormap, + st->colors, &st->ncolors, + True, 0, True); + if (st->ncolors <= 2) + mono_p = True, st->ncolors = 0; + } + + gcv.foreground = get_pixel_resource (st->dpy, cmap, "foreground", "Foreground"); + gcv.background = get_pixel_resource (st->dpy, cmap, "background", "Background"); + + if (! mono_p) + { + st->pixcol = halfrandom (st, st->ncolors); + gcv.foreground = (st->colors [st->pixcol].pixel); + } + + st->gc = XCreateGC (st->dpy, st->window, GCForeground | GCBackground, &gcv); + return st; +} + +static int +recurse (struct state *st, double x, double y, int l, Display *dpy, Window win) +{ + int i; + double nx, ny; + + if (l == st->max_levels) + { + st->total_points++; + if (st->total_points > st->max_total) /* how long each fractal runs */ + return 0; + + if (x > -1.0 && x < 1.0 && y > -1.0 && y < 1.0) + { + st->points[st->num_points].x = (int) ((st->width / 2) * (x + 1.0)); + st->points[st->num_points].y = (int) ((st->height / 2) * (y + 1.0)); + st->num_points++; + if (st->num_points >= POINT_BUFFER_SIZE) + { + XDrawPoints (st->dpy, win, st->gc, st->points, st->num_points, CoordModeOrigin); + st->num_points = 0; + } + } + } + else + { + for (i = 0; i < st->snum; i++) + { + + /* Scale back when values get very large. Spot sez: + "I think this happens on HPUX. I think it's non-IEEE + to generate an exception instead of a silent NaN." + */ + if ((fabs(x) > 1.0E5) || (fabs(y) > 1.0E5)) + x = x / y; + + nx = st->f[0][0][i] * x + st->f[0][1][i] * y + st->f[0][2][i]; + ny = st->f[1][0][i] * x + st->f[1][1][i] * y + st->f[1][2][i]; + if (i < st->anum) + { + switch (st->variation) + { + case 0: /* sinusoidal */ + nx = sin(nx); + ny = sin(ny); + break; + case 1: /* complex */ + { + double r2 = nx * nx + ny * ny + 1e-6; + nx = nx / r2; + ny = ny / r2; + } + break; + case 2: /* bent */ + if (nx < 0.0) + nx = nx * 2.0; + if (ny < 0.0) + ny = ny / 2.0; + break; + case 3: /* swirl */ + { + double r = (nx * nx + ny * ny); /* times k here is fun */ + double c1 = sin(r); + double c2 = cos(r); + double t = nx; + + if (nx > 1e4 || nx < -1e4 || ny > 1e4 || ny < -1e4) + ny = 1e4; + else + ny = c2 * t + c1 * ny; + nx = c1 * nx - c2 * ny; + } + break; + case 4: /* horseshoe */ + { + double r, c1, c2, t; + + /* Avoid atan2: DOMAIN error message */ + if (nx == 0.0 && ny == 0.0) + r = 0.0; + else + r = atan2(nx, ny); /* times k here is fun */ + c1 = sin(r); + c2 = cos(r); + t = nx; + + nx = c1 * nx - c2 * ny; + ny = c2 * t + c1 * ny; + } + break; + case 5: /* drape */ + { + double t; + + /* Avoid atan2: DOMAIN error message */ + if (nx == 0.0 && ny == 0.0) + t = 0.0; + else + t = atan2(nx, ny) / M_PI; + + if (nx > 1e4 || nx < -1e4 || ny > 1e4 || ny < -1e4) + ny = 1e4; + else + ny = sqrt(nx * nx + ny * ny) - 1.0; + nx = t; + } + break; + case 6: /* broken */ + if (nx > 1.0) + nx = nx - 1.0; + if (nx < -1.0) + nx = nx + 1.0; + if (ny > 1.0) + ny = ny - 1.0; + if (ny < -1.0) + ny = ny + 1.0; + break; + case 7: /* spherical */ + { + double r = 0.5 + sqrt(nx * nx + ny * ny + 1e-6); + + nx = nx / r; + ny = ny / r; + } + break; + case 8: /* */ + nx = atan(nx) / M_PI_2; + ny = atan(ny) / M_PI_2; + break; +/* #if 0 */ /* core dumps on some machines, why not all? */ + case 9: /* complex sine */ + { + double u = nx; + double v = ny; + double ev = exp(v); + double emv = exp(-v); + + nx = (ev + emv) * sin(u) / 2.0; + ny = (ev - emv) * cos(u) / 2.0; + } + break; + case 10: /* polynomial */ + if (nx < 0) + nx = -nx * nx; + else + nx = nx * nx; + if (ny < 0) + ny = -ny * ny; + else + ny = ny * ny; + break; +/* #endif */ + default: + nx = sin(nx); + ny = sin(ny); + } + } + if (!recurse (st, nx, ny, l + 1, st->dpy, win)) + return 0; + } + } + return 1; +} + +static unsigned long +flame_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int i, j, k; + unsigned long this_delay = st->delay; + + if (st->do_reset) + { + st->do_reset = 0; + XClearWindow (st->dpy, st->window); + } + + if (!(st->cur_level++ % st->max_levels)) + { + st->do_reset = 1; + this_delay = st->delay2; + st->flame_alt = !st->flame_alt; + st->variation = random() % MAXKINDS; + } + else + { + if (st->ncolors > 2) + { + XSetForeground (st->dpy, st->gc, st->colors [st->pixcol].pixel); + if (--st->pixcol < 0) + st->pixcol = st->ncolors - 1; + } + } + + /* number of functions */ + st->snum = 2 + (st->cur_level % (MAXLEV - 1)); + + /* how many of them are of alternate form */ + if (st->flame_alt) + st->anum = 0; + else + st->anum = halfrandom (st, st->snum) + 2; + + /* 6 coefs per function */ + for (k = 0; k < st->snum; k++) + { + for (i = 0; i < 2; i++) + for (j = 0; j < 3; j++) + st->f[i][j][k] = ((double) (random() & 1023) / 512.0 - 1.0); + } + st->num_points = 0; + st->total_points = 0; + recurse (st, 0.0, 0.0, 0, st->dpy, st->window); + XDrawPoints (st->dpy, st->window, st->gc, st->points, st->num_points, CoordModeOrigin); + + return this_delay; +} + + +#if defined(__hpux) && defined(PLOSS) +/* I don't understand why this is necessary, but I'm told that this program + does nothing at all on HP-sUX without it. + + I'm further told that HPUX 11.0 doesn't define PLOSS, and works ok without + this section. Go figure. + */ +#undef random +#undef srandom +#include +int matherr(x) + register struct exception *x; +{ + if (x->type == PLOSS) return 1; + else return 0; +} +#endif /* __hpux */ + + + +static const char *flame_defaults [] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*colors: 64", + "*iterations: 25", + "*delay: 50000", + "*delay2: 2000000", + "*points: 10000", +#ifdef HAVE_MOBILE + "*ignoreRotation: True", +#endif + 0 +}; + +static XrmOptionDescRec flame_options [] = { + { "-colors", ".colors", XrmoptionSepArg, 0 }, + { "-iterations", ".iterations", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-delay2", ".delay2", XrmoptionSepArg, 0 }, + { "-points", ".points", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + +static void +flame_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 +flame_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + struct state *st = (struct state *) closure; + if (screenhack_event_helper (dpy, window, event)) + { + st->do_reset = 1; + return True; + } + return False; +} + +static void +flame_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + +XSCREENSAVER_MODULE ("Flame", flame) + -- cgit v1.2.3-55-g7522