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/xflame.c | |
download | xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.gz xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.xz xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.zip |
Original 5.40
Diffstat (limited to 'hacks/xflame.c')
-rw-r--r-- | hacks/xflame.c | 819 |
1 files changed, 819 insertions, 0 deletions
diff --git a/hacks/xflame.c b/hacks/xflame.c new file mode 100644 index 0000000..1037460 --- /dev/null +++ b/hacks/xflame.c @@ -0,0 +1,819 @@ +/* xflame, Copyright (c) 1996-2018 Carsten Haitzler <raster@redhat.com> + * + * 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. + */ + +/* Version history as near as I (jwz) can piece together: + + * Carsten Haitzler <raster@redhat.com> wrote the first version in 1996. + + * Rahul Jain <rahul@rice.edu> added support for TrueColor displays. + + * Someone did a rough port of it to use the xscreensaver utility routines + instead of creating its own window by hand. + + * Someone (probably Raster) came up with a subsequent version that had + a Red Hat logo hardcoded into it. + + * Daniel Zahn <stumpy@religions.com> found that version in 1998, and + hacked it to be able to load a different logo from a PGM (P5) file, + with a single hardcoded pathname. + + * Jamie Zawinski <jwz@jwz.org> found several versions of xflame in + March 1999, and pieced them together. Changes: + + - Correct and fault-tolerant use of the Shared Memory extension; + previous versions of xflame did not work when $DISPLAY was remote. + + - Replaced PGM-reading code with code that can read arbitrary XBM + and XPM files (color ones will be converted to grayscale.) + + - Command-line options all around -- no hardcoded pathnames or + behavioral constants. + + - General cleanup and portability tweaks. + + * 4-Oct-99, jwz: added support for packed-24bpp (versus 32bpp.) + * 16-Jan-2002, jwz: added gdk_pixbuf support. + * 9-Oct-2016, Dave Odell <dmo2118@gmail.com>: Updated for new xshm.c. + + */ + +/* portions by Daniel Zahn <stumpy@religions.com> */ + + +#include "screenhack.h" +#include "ximage-loader.h" +#include <limits.h> + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +# undef MAX +# undef MIN +# define MAX(A,B) ((A)>(B)?(A):(B)) +# define MIN(A,B) ((A)<(B)?(A):(B)) + +#include "xshm.h" + +#include "images/gen/bob_png.h" + +#define MAX_VAL 255 + +struct state { + Display *dpy; + Window window; + int depth; + int width; + int height; + Colormap colormap; + Visual *visual; + Screen *screen; + Bool bloom; + XImage *xim; + XShmSegmentInfo shminfo; + GC gc; + int ctab[256]; + + unsigned char *flame; + unsigned char *theim; + int fwidth; + int fheight; + int top; + int hspread; + int vspread; + int residual; + + int ihspread; + int ivspread; + int iresidual; + int variance; + int vartrend; + + int delay; + int baseline; + int theimx, theimy; +}; + +static void +GetXInfo(struct state *st) +{ + XWindowAttributes xwa; + + XGetWindowAttributes(st->dpy,st->window,&xwa); + + st->colormap = xwa.colormap; + st->depth = xwa.depth; + st->visual = xwa.visual; + st->screen = xwa.screen; + st->width = xwa.width; + st->height = xwa.height; + + if (st->width%2) + st->width++; + if (st->height%2) + st->height++; +} + +static void +MakeImage(struct state *st) +{ + XGCValues gcv; + + if (st->xim) + destroy_xshm_image (st->dpy, st->xim, &st->shminfo); + + st->xim = create_xshm_image (st->dpy, st->visual, st->depth, ZPixmap, + &st->shminfo, st->width, st->height); + if (!st->xim) + { + fprintf(stderr,"%s: out of memory.\n", progname); + exit(1); + } + + if (! st->gc) + st->gc = XCreateGC(st->dpy,st->window,0,&gcv); +} + + +static void +InitColors(struct state *st) +{ + int i = 0, j = 0, red = 0, green = 0, blue = 0; + XColor fg; + + /* Make it possible to set the color of the flames, + by Raymond Medeiros <ray@stommel.marine.usf.edu> and jwz. + */ + fg.pixel = get_pixel_resource (st->dpy, st->colormap, + "foreground", "Foreground"); + XQueryColor (st->dpy, st->colormap, &fg); + + red = 255 - (fg.red >> 8); + green = 255 - (fg.green >> 8); + blue = 255 - (fg.blue >> 8); + + + for (i = 0; i < 256 * 2; i += 2) + { + XColor xcl; + int r = (i - red) * 3; + int g = (i - green) * 3; + int b = (i - blue) * 3; + + if (r < 0) r = 0; + if (r > 255) r = 255; + if (g < 0) g = 0; + if (g > 255) g = 255; + if (b < 0) b = 0; + if (b > 255) b = 255; + + xcl.red = (unsigned short)((r << 8) | r); + xcl.green = (unsigned short)((g << 8) | g); + xcl.blue = (unsigned short)((b << 8) | b); + xcl.flags = DoRed | DoGreen | DoBlue; + + XAllocColor(st->dpy,st->colormap,&xcl); + + st->ctab[j++] = (int)xcl.pixel; + } +} + + +static void +DisplayImage(struct state *st) +{ + put_xshm_image(st->dpy, st->window, st->gc, st->xim, 0,(st->top - 1) << 1, 0, + (st->top - 1) << 1, st->width, st->height - ((st->top - 1) << 1), + &st->shminfo); +} + + +static void +InitFlame(struct state *st) +{ + st->fwidth = st->width / 2; + st->fheight = st->height / 2; + + if (st->flame) free (st->flame); + st->flame = (unsigned char *) malloc((st->fwidth + 2) * (st->fheight + 2) + * sizeof(unsigned char)); + + if (!st->flame) + { + fprintf(stderr,"%s: out of memory\n", progname); + exit(1); + } + + st->top = 1; + st->ihspread = get_integer_resource(st->dpy, "hspread", "Integer"); + st->ivspread = get_integer_resource(st->dpy, "vspread", "Integer"); + st->iresidual = get_integer_resource(st->dpy, "residual", "Integer"); + st->variance = get_integer_resource(st->dpy, "variance", "Integer"); + st->vartrend = get_integer_resource(st->dpy, "vartrend", "Integer"); + st->bloom = get_boolean_resource(st->dpy, "bloom", "Boolean"); + +# define THROTTLE(VAR,NAME) \ + if (VAR < 0 || VAR > 255) { \ + fprintf(stderr, "%s: %s must be in the range 0-255 (not %d).\n", \ + progname, NAME, VAR); \ + exit(1); } + THROTTLE (st->ihspread, "hspread"); + THROTTLE (st->ivspread, "vspread"); + THROTTLE (st->iresidual,"residual"); + THROTTLE (st->variance, "variance"); + THROTTLE (st->vartrend, "vartrend"); +# undef THROTTLE + +#if 0 + if (st->width > 2560) /* Retina displays */ + { + /* #### One of these knobs must mean "make the fire be twice as tall" + but I can't figure out how. Changing any of the default values + of any of these seems to just make it all go crappy. */ + st->ivspread = MAX (0, MIN (255, st->ivspread + 1)); + } +#endif + + st->hspread = st->ihspread; + st->vspread = st->ivspread; + st->residual = st->iresidual; +} + + +static void +Flame2Image16(struct state *st) +{ + int x,y; + unsigned short *ptr; + unsigned char *ptr1; + int v1,v2,v3,v4; + + ptr = (unsigned short *)st->xim->data; + ptr += (st->top << 1) * st->width; + ptr1 = st->flame + 1 + (st->top * (st->fwidth + 2)); + + for(y = st->top; y < st->fheight; y++) + { + for( x = 0; x < st->fwidth; x++) + { + v1 = (int)*ptr1; + v2 = (int)*(ptr1 + 1); + v3 = (int)*(ptr1 + st->fwidth + 2); + v4 = (int)*(ptr1 + st->fwidth + 2 + 1); + ptr1++; + *ptr++ = (unsigned short)st->ctab[v1]; + *ptr = (unsigned short)st->ctab[(v1 + v2) >> 1]; + ptr += st->width - 1; + *ptr++ = (unsigned short)st->ctab[(v1 + v3) >> 1]; + *ptr = (unsigned short)st->ctab[(v1 + v4) >> 1]; + ptr -= st->width - 1; + } + ptr += st->width; + ptr1 += 2; + } +} + +static void +Flame2Image32(struct state *st) +{ + int x,y; + unsigned int *ptr; + unsigned char *ptr1; + int v1,v2,v3,v4; + + ptr = (unsigned int *)st->xim->data; + ptr += (st->top << 1) * st->width; + ptr1 = st->flame + 1 + (st->top * (st->fwidth + 2)); + + for( y = st->top; y < st->fheight; y++) + { + for( x = 0; x < st->fwidth; x++) + { + v1 = (int)*ptr1; + v2 = (int)*(ptr1 + 1); + v3 = (int)*(ptr1 + st->fwidth + 2); + v4 = (int)*(ptr1 + st->fwidth + 2 + 1); + ptr1++; + *ptr++ = (unsigned int)st->ctab[v1]; + *ptr = (unsigned int)st->ctab[(v1 + v2) >> 1]; + ptr += st->width - 1; + *ptr++ = (unsigned int)st->ctab[(v1 + v3) >> 1]; + *ptr = (unsigned int)st->ctab[(v1 + v4) >> 1]; + ptr -= st->width - 1; + } + ptr += st->width; + ptr1 += 2; + } +} + +static void +Flame2Image24(struct state *st) +{ + int x,y; + unsigned char *ptr; + unsigned char *ptr1; + int v1,v2,v3,v4; + + ptr = (unsigned char *)st->xim->data; + ptr += (st->top << 1) * st->xim->bytes_per_line; + ptr1 = st->flame + 1 + (st->top * (st->fwidth + 2)); + + for( y = st->top; y < st->fheight; y++) + { + unsigned char *last_ptr = ptr; + for( x = 0; x < st->fwidth; x++) + { + v1 = (int)*ptr1; + v2 = (int)*(ptr1 + 1); + v3 = (int)*(ptr1 + st->fwidth + 2); + v4 = (int)*(ptr1 + st->fwidth + 2 + 1); + ptr1++; + + ptr[2] = ((unsigned int)st->ctab[v1] & 0x00FF0000) >> 16; + ptr[1] = ((unsigned int)st->ctab[v1] & 0x0000FF00) >> 8; + ptr[0] = ((unsigned int)st->ctab[v1] & 0x000000FF); + ptr += 3; + + ptr[2] = ((unsigned int)st->ctab[(v1 + v2) >> 1] & 0x00FF0000) >> 16; + ptr[1] = ((unsigned int)st->ctab[(v1 + v2) >> 1] & 0x0000FF00) >> 8; + ptr[0] = ((unsigned int)st->ctab[(v1 + v2) >> 1] & 0x000000FF); + ptr += ((st->width - 1) * 3); + + ptr[2] = ((unsigned int)st->ctab[(v1 + v3) >> 1] & 0x00FF0000) >> 16; + ptr[1] = ((unsigned int)st->ctab[(v1 + v3) >> 1] & 0x0000FF00) >> 8; + ptr[0] = ((unsigned int)st->ctab[(v1 + v3) >> 1] & 0x000000FF); + ptr += 3; + + ptr[2] = ((unsigned int)st->ctab[(v1 + v4) >> 1] & 0x00FF0000) >> 16; + ptr[1] = ((unsigned int)st->ctab[(v1 + v4) >> 1] & 0x0000FF00) >> 8; + ptr[0] = ((unsigned int)st->ctab[(v1 + v4) >> 1] & 0x000000FF); + ptr -= ((st->width - 1) * 3); + } + + ptr = last_ptr + (st->xim->bytes_per_line << 1); + ptr1 += 2; + } +} + +static void +Flame2Image8(struct state *st) +{ + int x,y; + unsigned char *ptr; + unsigned char *ptr1; + int v1,v2,v3,v4; + + ptr = (unsigned char *)st->xim->data; + ptr += (st->top << 1) * st->width; + ptr1 = st->flame + 1 + (st->top * (st->fwidth + 2)); + + for(y=st->top;y<st->fheight;y++) + { + for(x=0;x<st->fwidth;x++) + { + v1 = (int)*ptr1; + v2 = (int)*(ptr1 + 1); + v3 = (int)*(ptr1 + st->fwidth + 2); + v4 = (int)*(ptr1 + st->fwidth + 2 + 1); + ptr1++; + *ptr++ = (unsigned char)st->ctab[v1]; + *ptr = (unsigned char)st->ctab[(v1 + v2) >> 1]; + ptr += st->width - 1; + *ptr++ = (unsigned char)st->ctab[(v1 + v3) >> 1]; + *ptr = (unsigned char)st->ctab[(v1 + v4) >> 1]; + ptr -= st->width - 1; + } + ptr += st->width; + ptr1 += 2; + } +} + +static void +Flame2Image1234567(struct state *st) +{ + int x,y; + unsigned char *ptr1; + int v1,v2,v3,v4; + + ptr1 = st->flame + 1 + (st->top * (st->fwidth + 2)); + + for( y = st->top; y < st->fheight; y++) + { + for( x = 0; x < st->fwidth; x++) + { + v1 = (int)*ptr1; + v2 = (int)*(ptr1 + 1); + v3 = (int)*(ptr1 + st->fwidth + 2); + v4 = (int)*(ptr1 + st->fwidth + 2 + 1); + ptr1++; + XPutPixel(st->xim,(x << 1), (y << 1), st->ctab[v1]); + XPutPixel(st->xim,(x << 1) + 1,(y << 1), st->ctab[(v1 + v2) >> 1]); + XPutPixel(st->xim,(x << 1), (y << 1) + 1,st->ctab[(v1 + v3) >> 1]); + XPutPixel(st->xim,(x << 1) + 1,(y << 1) + 1,st->ctab[(v1 + v4) >> 1]); + } + } +} + +static void +Flame2Image(struct state *st) +{ + switch (st->xim->bits_per_pixel) + { + case 32: Flame2Image32(st); break; + case 24: Flame2Image24(st); break; + case 16: Flame2Image16(st); break; + case 8: Flame2Image8(st); break; + default: + if (st->xim->bits_per_pixel <= 7) + Flame2Image1234567(st); + else + abort(); + break; + } +} + + +static void +FlameActive(struct state *st) +{ + int x,v1; + unsigned char *ptr1; + + ptr1 = st->flame + ((st->fheight + 1) * (st->fwidth + 2)); + + for (x = 0; x < st->fwidth + 2; x++) + { + v1 = *ptr1; + v1 += ((random() % st->variance) - st->vartrend); + *ptr1++ = v1 % 255; + } + + if (st->bloom) + { + v1= (random() % 100); + if (v1 == 10) + st->residual += (random()%10); + else if (v1 == 20) + st->hspread += (random()%15); + else if (v1 == 30) + st->vspread += (random()%20); + } + + st->residual = ((st->iresidual* 10) + (st->residual *90)) / 100; + st->hspread = ((st->ihspread * 10) + (st->hspread *90)) / 100; + st->vspread = ((st->ivspread * 10) + (st->vspread *90)) / 100; +} + + +static void +FlameAdvance(struct state *st) +{ + int x,y; + unsigned char *ptr2; + int newtop = st->top; + + for (y = st->fheight + 1; y >= st->top; y--) + { + int used = 0; + unsigned char *ptr1 = st->flame + 1 + (y * (st->fwidth + 2)); + for (x = 0; x < st->fwidth; x++) + { + int v1 = (int)*ptr1; + int v2, v3; + if (v1 > 0) + { + used = 1; + ptr2 = ptr1 - st->fwidth - 2; + v3 = (v1 * st->vspread) >> 8; + v2 = (int)*(ptr2); + v2 += v3; + if (v2 > MAX_VAL) + v2 = MAX_VAL; + + *(ptr2) = (unsigned char)v2; + v3 = (v1 * st->hspread) >> 8; + v2 = (int)*(ptr2 + 1); + v2 += v3; + if (v2 > MAX_VAL) + v2 = MAX_VAL; + + *(ptr2 + 1) = (unsigned char)v2; + v2 = (int)*(ptr2 - 1); + v2 += v3; + if (v2 > MAX_VAL) + v2 = MAX_VAL; + + *(ptr2 - 1) = (unsigned char)v2; + + if (y < st->fheight + 1) + { + v1 = (v1 * st->residual) >> 8; + *ptr1 = (unsigned char)v1; + } + } + ptr1++; + if (used) + newtop = y - 1; + } + + /* clean up the right gutter */ + { + int v1 = (int)*ptr1; + v1 = (v1 * st->residual) >> 8; + *ptr1 = (unsigned char)v1; + } + } + + st->top = newtop - 1; + + if (st->top < 1) + st->top = 1; +} + + +static void +FlameFill(struct state *st, int val) +{ + int x, y; + for (y = 0; y < st->fheight + 1; y++) + { + unsigned char *ptr1 = st->flame + 1 + (y * (st->fwidth + 2)); + for (x = 0; x < st->fwidth; x++) + { + *ptr1 = val; + ptr1++; + } + } +} + + +static void +FlamePasteData(struct state *st, + unsigned char *d, int xx, int yy, int w, int h) +{ + unsigned char *ptr1,*ptr2; + ptr2 = d; + + if (xx < 0) xx = 0; + if (yy < 0) yy = 0; + + if ((xx >= 0) && + (yy >= 0) && + (xx + w <= st->fwidth) && + (yy + h <= st->fheight)) + { + int x, y; + for (y = 0; y < h; y++) + { + ptr1 = st->flame + 1 + xx + ((yy + y) * (st->fwidth + 2)); + for (x = 0; x < w; x++) + { + if (*ptr2 / 24) + *ptr1 += random() % (*ptr2 / 24); + + ptr1++; + ptr2++; + } + } + } + else + { + static Bool warned = False; + if (!warned) + { + fprintf (stderr, "%s: st->window is %dx%d; image must be " + "smaller than %dx%d (not %dx%d).\n", + progname, st->width, st->height, st->fwidth, st->fheight, w, h); + warned = True; + } + } +} + + +static XImage * +double_ximage (Display *dpy, Visual *visual, XImage *image) +{ + int x, y; + XImage *out = XCreateImage (dpy, visual, image->depth, ZPixmap, 0, 0, + image->width * 2, image->height * 2, 8, 0); + out->data = (char *) malloc (out->height * out->bytes_per_line); + for (y = 0; y < image->width; y++) + for (x = 0; x < image->height; x++) + { + unsigned long p = XGetPixel (image, x, y); + XPutPixel (out, x*2, y*2, p); + XPutPixel (out, x*2+1, y*2, p); + XPutPixel (out, x*2, y*2+1, p); + XPutPixel (out, x*2+1, y*2+1, p); + } + XDestroyImage (image); + return out; +} + + +static unsigned char * +gaussian_blur (unsigned char *in, int w, int h, double r) +{ + unsigned char *out = malloc(w * h); + int rs = (int) ((r * 2.57) + 0.5); + int i, j; + + for (i = 0; i < h; i ++) + for (j = 0; j < w; j++) + { + double val = 0, wsum = 0; + int ix, iy; + for (iy = i-rs; iy<i+rs+1; iy++) + for (ix = j-rs; ix<j+rs+1; ix++) + { + int x = MIN(w-1, MAX(0, ix)); + int y = MIN(h-1, MAX(0, iy)); + int dsq = (ix-j)*(ix-j)+(iy-i)*(iy-i); + double wght = exp (-dsq / (2*r*r)) / (M_PI*2*r*r); + val += in[y*w+x] * wght; + wsum += wght; + } + out[i*w+j] = val/wsum; + } + + free (in); + return out; +} + + +static unsigned char * +loadBitmap (struct state *st) +{ + int x, y; + unsigned char *result, *o; + int blur = 0; + +# ifdef HAVE_JWXYZ + const char *bitmap_name = "(default)"; /* #### always use builtin */ +# else + char *bitmap_name = get_string_resource (st->dpy, "bitmap", "Bitmap"); +# endif + XImage *image = 0; + if (!bitmap_name || + !*bitmap_name || + !strcmp(bitmap_name, "none")) + ; + else if (!strcmp(bitmap_name, "(default)")) /* use the builtin */ + image = image_data_to_ximage (st->dpy, st->visual, + bob_png, sizeof(bob_png)); + else + image = file_to_ximage (st->dpy, st->visual, bitmap_name); + + if (! image) return 0; + + while (image->width < st->width / 10 && + image->height < st->height / 10) + { + image = double_ximage (st->dpy, st->visual, image); + blur++; + } + + result = (unsigned char *) malloc (image->width * image->height); + o = result; + for (y = 0; y < image->height; y++) + for (x = 0; x < image->width; x++) + { + unsigned long agbr = XGetPixel (image, x, image->height - y - 1); + unsigned long a = (agbr >> 24) & 0xFF; + unsigned long gray = (a == 0 + ? 0xFF + : ((((agbr >> 16) & 0xFF) + + ((agbr >> 8) & 0xFF) + + ((agbr >> 0) & 0xFF)) + / 3)); + if (gray < 96) gray /= 2; /* a little more contrast */ + *o++ = 255 - gray; + } + + /* If we enlarged the image, file off the sharp edges. */ + if (blur > 0) + result = gaussian_blur (result, image->width, image->height, blur * 1.7); + + st->theimx = image->width; + st->theimy = image->height; + XDestroyImage (image); + return result; +} + + +static void * +xflame_init (Display *dpy, Window win) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + st->dpy = dpy; + st->window = win; + st->baseline = get_integer_resource (dpy, "bitmapBaseline", "Integer"); + st->delay = get_integer_resource (dpy, "delay", "Integer"); + st->xim = NULL; + st->top = 1; + st->flame = NULL; + + GetXInfo(st); + InitColors(st); + st->theim = loadBitmap(st); + + MakeImage(st); + InitFlame(st); + FlameFill(st,0); + + return st; +} + +static unsigned long +xflame_draw (Display *dpy, Window win, void *closure) +{ + struct state *st = (struct state *) closure; + FlameActive(st); + + if (st->theim) + FlamePasteData(st, st->theim, (st->fwidth - st->theimx) / 2, + st->fheight - st->theimy - st->baseline, st->theimx, st->theimy); + + FlameAdvance(st); + Flame2Image(st); + DisplayImage(st); + + return st->delay; +} + +static void +xflame_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + GetXInfo(st); + MakeImage(st); + InitFlame(st); + FlameFill(st,0); + XClearWindow (dpy, window); +} + +static Bool +xflame_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +xflame_free (Display *dpy, Window window, void *closure) +{ +} + + + + +static const char *xflame_defaults [] = { + ".background: black", + ".foreground: #FFAF5F", + "*fpsTop: true", + "*fpsSolid: true", + "*bitmap: (default)", + "*bitmapBaseline: 20", + "*delay: 10000", + "*hspread: 30", + "*vspread: 97", + "*residual: 99", + "*variance: 50", + "*vartrend: 20", + "*bloom: True", + +#ifdef HAVE_XSHM_EXTENSION + "*useSHM: False", /* xshm turns out not to help. */ +#endif /* HAVE_XSHM_EXTENSION */ + 0 +}; + +static XrmOptionDescRec xflame_options [] = { + { "-foreground",".foreground", XrmoptionSepArg, 0 }, + { "-fg", ".foreground", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-bitmap", ".bitmap", XrmoptionSepArg, 0 }, + { "-baseline", ".bitmapBaseline", XrmoptionSepArg, 0 }, + { "-hspread", ".hspread", XrmoptionSepArg, 0 }, + { "-vspread", ".vspread", XrmoptionSepArg, 0 }, + { "-residual", ".residual", XrmoptionSepArg, 0 }, + { "-variance", ".variance", XrmoptionSepArg, 0 }, + { "-vartrend", ".vartrend", XrmoptionSepArg, 0 }, + { "-bloom", ".bloom", XrmoptionNoArg, "True" }, + { "-no-bloom", ".bloom", XrmoptionNoArg, "False" }, +#ifdef HAVE_XSHM_EXTENSION + { "-shm", ".useSHM", XrmoptionNoArg, "True" }, + { "-no-shm", ".useSHM", XrmoptionNoArg, "False" }, +#endif /* HAVE_XSHM_EXTENSION */ + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("XFlame", xflame) |