X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fflame.c;h=851b26151a84dfd79b34fe5545d683383848f64b;hb=0bd2eabab3e404c6769fe8f59b639275e960c415;hp=3f98e3e3036efbf670f287091a1776a9bbb611ef;hpb=ccbc9f87eb59497b23bd0424ee1ed20ad7c7db54;p=xscreensaver diff --git a/hacks/flame.c b/hacks/flame.c index 3f98e3e3..851b2615 100644 --- a/hacks/flame.c +++ b/hacks/flame.c @@ -1,4 +1,5 @@ -/* xscreensaver, Copyright (c) 1993, 1995 Jamie Zawinski +/* xscreensaver, Copyright (c) 1993, 1995, 1996 + * 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 @@ -10,7 +11,7 @@ */ /* This file was ported from xlock for use in xscreensaver (and standalone) - * by jwz on 18-Oct-93. Original copyright reads: + * 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"; * @@ -41,28 +42,33 @@ * 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 Graves, spot@cs.cmu.edu). + * 06-Jun-91: Written. (received from Scott Draves, spot@cs.cmu.edu). */ +#include #include "screenhack.h" #define POINT_BUFFER_SIZE 10 #define MAXLEV 4 +#define MAXKINDS 10 static double f[2][3][MAXLEV]; /* three non-homogeneous transforms */ static int max_total; static int max_levels; static int max_points; static int cur_level; +static int variation; static int snum; static int anum; static int num_points; static int total_points; static int pixcol; -static int npixels; -static unsigned long *pixels; +static int ncolors; +static XColor *colors; static XPoint points [POINT_BUFFER_SIZE]; static GC gc; @@ -70,8 +76,7 @@ static int delay, delay2; static int width, height; static short -halfrandom (mv) - int mv; +halfrandom (int mv) { static short lasthalf = 0; unsigned long r; @@ -89,11 +94,8 @@ halfrandom (mv) return (r % mv); } - static void -init_flame (dpy, window) - Display *dpy; - Window window; +init_flame (Display *dpy, Window window) { XGCValues gcv; XWindowAttributes xgwa; @@ -116,25 +118,19 @@ init_flame (dpy, window) delay2 = get_integer_resource ("delay2", "Integer"); if (delay2 < 0) delay2 = 0; + variation = random() % MAXKINDS; + if (mono_p) - npixels = 0; + ncolors = 0; else { - int i = get_integer_resource ("ncolors", "Integer"); - double saturation = 1.0; - double value = 1.0; - XColor color; - if (i <= 0) i = 128; - - pixels = (unsigned long *) malloc ((i+1) * sizeof (*pixels)); - for (npixels = 0; npixels < i; npixels++) - { - hsv_to_rgb ((360*npixels)/i, saturation, value, - &color.red, &color.green, &color.blue); - if (! XAllocColor (dpy, cmap, &color)) - break; - pixels [npixels] = color.pixel; - } + ncolors = get_integer_resource ("colors", "Integer"); + if (ncolors <= 0) ncolors = 128; + colors = (XColor *) malloc ((ncolors+1) * sizeof (*colors)); + make_smooth_colormap (dpy, xgwa.visual, xgwa.colormap, colors, &ncolors, + True, 0, True); + if (ncolors <= 2) + mono_p = True, ncolors = 0; } gcv.foreground = get_pixel_resource ("foreground", "Foreground", dpy, cmap); @@ -142,19 +138,15 @@ init_flame (dpy, window) if (! mono_p) { - pixcol = halfrandom (npixels); - gcv.foreground = (pixels [pixcol]); + pixcol = halfrandom (ncolors); + gcv.foreground = (colors [pixcol].pixel); } gc = XCreateGC (dpy, window, GCForeground | GCBackground, &gcv); } static int -recurse (x, y, l, dpy, win) - register double x, y; - register int l; - Display *dpy; - Window win; +recurse (double x, double y, int l, Display *dpy, Window win) { int xp, yp, i; double nx, ny; @@ -183,12 +175,134 @@ recurse (x, y, l, dpy, win) { for (i = 0; i < 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 ((abs(x) > 1.0E5) || (abs(y) > 1.0E5)) + x = x / y; + nx = f[0][0][i] * x + f[0][1][i] * y + f[0][2][i]; ny = f[1][0][i] * x + f[1][1][i] * y + f[1][2][i]; if (i < anum) { - nx = sin(nx); - ny = sin(ny); + switch (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 (nx, ny, l + 1, dpy, win)) return 0; @@ -199,9 +313,7 @@ recurse (x, y, l, dpy, win) static void -flame (dpy, window) - Display *dpy; - Window window; +flame (Display *dpy, Window window) { int i, j, k; static int alt = 0; @@ -211,14 +323,16 @@ flame (dpy, window) if (delay2) usleep (delay2); XClearWindow (dpy, window); alt = !alt; + + variation = random() % MAXKINDS; } else { - if (npixels > 2) + if (ncolors > 2) { - XSetForeground (dpy, gc, pixels [pixcol]); + XSetForeground (dpy, gc, colors [pixcol].pixel); if (--pixcol < 0) - pixcol = npixels - 1; + pixcol = ncolors - 1; } } @@ -267,9 +381,9 @@ int matherr(x) char *progclass = "Flame"; char *defaults [] = { - "Flame.background: black", /* to placate SGI */ - "Flame.foreground: white", - "*colors: 128", + ".background: black", + ".foreground: white", + "*colors: 64", "*iterations: 25", "*delay: 50000", "*delay2: 2000000", @@ -278,18 +392,16 @@ char *defaults [] = { }; XrmOptionDescRec options [] = { - { "-ncolors", ".colors", XrmoptionSepArg, 0 }, + { "-colors", ".colors", XrmoptionSepArg, 0 }, { "-iterations", ".iterations", XrmoptionSepArg, 0 }, { "-delay", ".delay", XrmoptionSepArg, 0 }, { "-delay2", ".delay2", XrmoptionSepArg, 0 }, - { "-points", ".points", XrmoptionSepArg, 0 } + { "-points", ".points", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } }; -int options_size = (sizeof (options) / sizeof (options[0])); void -screenhack (dpy, window) - Display *dpy; - Window window; +screenhack (Display *dpy, Window window) { init_flame (dpy, window); while (1)