+++ /dev/null
-/* xflame, Copyright (c) 1996-1999 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.
- */
-
-
-/* portions by Daniel Zahn <stumpy@religions.com> */
-
-
-#include "screenhack.h"
-#include <X11/Xutil.h>
-#include <limits.h>
-
-#ifdef HAVE_XSHM_EXTENSION
-# include "xshm.h"
-#endif /* HAVE_XSHM_EXTENSION */
-
-#ifdef HAVE_XPM
-# include <X11/xpm.h>
-# ifndef PIXEL_ALREADY_TYPEDEFED
-# define PIXEL_ALREADY_TYPEDEFED /* Sigh, Xmu/Drawing.h needs this... */
-# endif
-#endif
-
-#ifdef HAVE_XMU
-# ifndef VMS
-# include <X11/Xmu/Drawing.h>
-# else /* VMS */
-# include <Xmu/Drawing.h>
-# endif /* VMS */
-#endif /* HAVE_XMU */
-
-#define MAX 255
-
-static Display *display;
-static Window window;
-static int depth;
-static int width;
-static int height;
-static Colormap colormap;
-static Visual *visual;
-static Bool shared;
-static XImage *xim;
-#ifdef HAVE_XSHM_EXTENSION
-static XShmSegmentInfo shminfo;
-#endif /* HAVE_XSHM_EXTENSION */
-static GC gc;
-static int ctab[256];
-
-static unsigned char *flame;
-static unsigned char *theim;
-static int fwidth;
-static int fheight;
-static int top;
-static int hspread;
-static int vspread;
-static int residual;
-
-static int ihspread;
-static int ivspread;
-static int iresidual;
-static int variance;
-static int vartrend;
-
-static void
-GetXInfo(Display *disp, Window win)
-{
- XWindowAttributes xwa;
-
- XGetWindowAttributes(disp,win,&xwa);
-
- window = win;
- display = disp;
- colormap = xwa.colormap;
- depth = xwa.depth;
- visual = xwa.visual;
- width = xwa.width;
- height = xwa.height;
-
- if (width%2)
- width++;
- if (height%2)
- height++;
-}
-
-static void
-MakeImage(void)
-{
- XGCValues gcv;
-
-#ifdef HAVE_XSHM_EXTENSION
- shared = True;
- xim = create_xshm_image (display, visual, depth, ZPixmap, NULL,
- &shminfo, width, height);
-#else /* !HAVE_XSHM_EXTENSION */
- xim = 0;
-#endif /* !HAVE_XSHM_EXTENSION */
-
- if (!xim)
- {
- shared = False;
- xim = XCreateImage (display, visual, depth, ZPixmap, 0, NULL,
- width, height, 32, 0);
- if (xim)
- xim->data = (char *) calloc(xim->height, xim->bytes_per_line);
- if (!xim || !xim->data)
- {
- fprintf(stderr,"%s: out of memory.\n", progname);
- exit(1);
- }
- }
-
- gc = XCreateGC(display,window,0,&gcv);
- if (!gc) exit (1);
-}
-
-
-static void
-InitColors(void)
-{
- int i = 0, j = 0;
- for (i = 0; i < 256 * 2; i += 2)
- {
- XColor xcl;
- int r = (i - 0) * 3;
- int g = (i - 80) * 3;
- int b = (i - 160) * 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(display,colormap,&xcl);
-
- ctab[j++] = (int)xcl.pixel;
- }
-}
-
-
-static void
-DisplayImage(void)
-{
-#ifdef HAVE_XSHM_EXTENSION
- if (shared)
- XShmPutImage(display, window, gc, xim, 0,(top - 1) << 1, 0,
- (top - 1) << 1, width, height - ((top - 1) << 1), False);
- else
-#endif /* HAVE_XSHM_EXTENSION */
- XPutImage(display, window, gc, xim, 0, (top - 1) << 1, 0,
- (top - 1) << 1, width, height - ((top - 1) << 1));
-}
-
-
-static void
-InitFlame(void)
-{
- fwidth = width / 2;
- fheight = height / 2;
- flame = (unsigned char *) malloc((fwidth + 2) * (fheight + 2)
- * sizeof(unsigned char));
-
- if (!flame)
- {
- fprintf(stderr,"%s: out of memory\n", progname);
- exit(1);
- }
-
- top = 1;
- ihspread = get_integer_resource("hspread", "Integer");
- ivspread = get_integer_resource("vspread", "Integer");
- iresidual = get_integer_resource("residual", "Integer");
- variance = get_integer_resource("variance", "Integer");
- vartrend = get_integer_resource("vartrend", "Integer");
-
-# 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 (ihspread, "hspread");
- THROTTLE (ivspread, "vspread");
- THROTTLE (iresidual,"residual");
- THROTTLE (variance, "variance");
- THROTTLE (vartrend, "vartrend");
-# undef THROTTLE
-
-
-
- hspread = ihspread;
- vspread = ivspread;
- residual = iresidual;
-}
-
-
-static void
-Flame2Image16(void)
-{
- int x,y;
- unsigned short *ptr;
- unsigned char *ptr1;
- int v1,v2,v3,v4;
-
- ptr = (unsigned short *)xim->data;
- ptr += (top << 1) * width;
- ptr1 = flame + 1 + (top * (fwidth + 2));
-
- for(y = top; y < fheight; y++)
- {
- for( x = 0; x < fwidth; x++)
- {
- v1 = (int)*ptr1;
- v2 = (int)*(ptr1 + 1);
- v3 = (int)*(ptr1 + fwidth + 2);
- v4 = (int)*(ptr1 + fwidth + 2 + 1);
- ptr1++;
- *ptr++ = (unsigned short)ctab[v1];
- *ptr = (unsigned short)ctab[(v1 + v2) >> 1];
- ptr += width - 1;
- *ptr++ = (unsigned short)ctab[(v1 + v3) >> 1];
- *ptr = (unsigned short)ctab[(v1 + v4) >> 1];
- ptr -= width - 1;
- }
- ptr += width;
- ptr1 += 2;
- }
-}
-
-static void
-Flame2Image32(void)
-{
- int x,y;
- unsigned int *ptr;
- unsigned char *ptr1;
- int v1,v2,v3,v4;
-
- ptr = (unsigned int *)xim->data;
- ptr += (top << 1) * width;
- ptr1 = flame + 1 + (top * (fwidth + 2));
-
- for( y = top; y < fheight; y++)
- {
- for( x = 0; x < fwidth; x++)
- {
- v1 = (int)*ptr1;
- v2 = (int)*(ptr1 + 1);
- v3 = (int)*(ptr1 + fwidth + 2);
- v4 = (int)*(ptr1 + fwidth + 2 + 1);
- ptr1++;
- *ptr++ = (unsigned int)ctab[v1];
- *ptr = (unsigned int)ctab[(v1 + v2) >> 1];
- ptr += width - 1;
- *ptr++ = (unsigned int)ctab[(v1 + v3) >> 1];
- *ptr = (unsigned int)ctab[(v1 + v4) >> 1];
- ptr -= width - 1;
- }
- ptr += width;
- ptr1 += 2;
- }
-}
-
-static void
-Flame2Image8(void)
-{
- int x,y;
- unsigned char *ptr;
- unsigned char *ptr1;
- int v1,v2,v3,v4;
-
- ptr = (unsigned char *)xim->data;
- ptr += (top << 1) * width;
- ptr1 = flame + 1 + (top * (fwidth + 2));
-
- for(y=top;y<fheight;y++)
- {
- for(x=0;x<fwidth;x++)
- {
- v1 = (int)*ptr1;
- v2 = (int)*(ptr1 + 1);
- v3 = (int)*(ptr1 + fwidth + 2);
- v4 = (int)*(ptr1 + fwidth + 2 + 1);
- ptr1++;
- *ptr++ = (unsigned char)ctab[v1];
- *ptr = (unsigned char)ctab[(v1 + v2) >> 1];
- ptr += width - 1;
- *ptr++ = (unsigned char)ctab[(v1 + v3) >> 1];
- *ptr = (unsigned char)ctab[(v1 + v4) >> 1];
- ptr -= width - 1;
- }
- ptr += width;
- ptr1 += 2;
- }
-}
-
-static void
-Flame2Image1234567(void)
-{
- int x,y;
- unsigned char *ptr1;
- int v1,v2,v3,v4;
-
- ptr1 = flame + 1 + (top * (fwidth + 2));
-
- for( y = top; y < fheight; y++)
- {
- for( x = 0; x < fwidth; x++)
- {
- v1 = (int)*ptr1;
- v2 = (int)*(ptr1 + 1);
- v3 = (int)*(ptr1 + fwidth + 2);
- v4 = (int)*(ptr1 + fwidth + 2 + 1);
- ptr1++;
- XPutPixel(xim,(x << 1), (y << 1), ctab[v1]);
- XPutPixel(xim,(x << 1) + 1,(y << 1), ctab[(v1 + v2) >> 1]);
- XPutPixel(xim,(x << 1), (y << 1) + 1,ctab[(v1 + v3) >> 1]);
- XPutPixel(xim,(x << 1) + 1,(y << 1) + 1,ctab[(v1 + v4) >> 1]);
- }
- }
-}
-
-static void
-Flame2Image(void)
-{
- if (depth >= 24) Flame2Image32();
- else if (depth == 16) Flame2Image16();
- else if (depth == 8) Flame2Image8();
- else if (depth == 15) Flame2Image16();
- else if (depth < 8) Flame2Image1234567();
- else if (depth == 12) Flame2Image16();
-}
-
-static void
-FlameActive(void)
-{
- int x,v1;
- unsigned char *ptr1;
-
- ptr1 = flame + ((fheight + 1) * (fwidth + 2));
-
- for (x = 0; x < fwidth + 2; x++)
- {
- v1 = *ptr1;
- v1 += ((random() % variance) - vartrend);
- *ptr1++ = v1 % 255;
- }
-
- v1= (random() % 100);
- if (v1 == 10)
- residual += (random()%10);
- else if (v1 == 20)
- hspread += (random()%15);
- else if (v1 == 30)
- vspread += (random()%20);
-
- residual = ((iresidual* 10) + (residual *90)) / 100;
- hspread = ((ihspread * 10) + (hspread *90)) / 100;
- vspread = ((ivspread * 10) + (vspread *90)) / 100;
-}
-
-
-static void
-FlameAdvance(void)
-{
- int x,y;
- unsigned char *ptr2;
- int newtop = top;
-
- for (y = fheight + 1; y >= top; y--)
- {
- int used = 0;
- unsigned char *ptr1 = flame + 1 + (y * (fwidth + 2));
- for (x = 0; x < fwidth; x++)
- {
- int v1 = (int)*ptr1;
- int v2, v3;
- if (v1 > 0)
- {
- used = 1;
- ptr2 = ptr1 - fwidth - 2;
- v3 = (v1 * vspread) >> 8;
- v2 = (int)*(ptr2);
- v2 += v3;
- if (v2 > MAX)
- v2 = MAX;
-
- *(ptr2) = (unsigned char)v2;
- v3 = (v1 * hspread) >> 8;
- v2 = (int)*(ptr2 + 1);
- v2 += v3;
- if (v2 > MAX)
- v2 = MAX;
-
- *(ptr2 + 1) = (unsigned char)v2;
- v2 = (int)*(ptr2 - 1);
- v2 += v3;
- if (v2 > MAX)
- v2 = MAX;
-
- *(ptr2 - 1) = (unsigned char)v2;
-
- if (y < fheight + 1)
- {
- v1 = (v1 * residual) >> 8;
- *ptr1 = (unsigned char)v1;
- }
- }
- ptr1++;
- if (used)
- newtop = y - 1;
- }
- }
-
- top = newtop - 1;
-
- if (top < 1)
- top = 1;
-}
-
-
-static void
-FlameFill(int val)
-{
- int x, y;
- for (y = 0; y < fheight + 1; y++)
- {
- unsigned char *ptr1 = flame + 1 + (y * (fwidth + 2));
- for (x = 0; x < fwidth; x++)
- {
- *ptr1 = val;
- ptr1++;
- }
- }
-}
-
-
-static void
-FlamePasteData(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 <= fwidth) &&
- (yy + h <= fheight))
- {
- int x, y;
- for (y = 0; y < h; y++)
- {
- ptr1 = flame + 1 + xx + ((yy + y) * (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: window is %dx%d; image must be "
- "smaller than %dx%d (not %dx%d).\n",
- progname, width, height, fwidth, fheight, w, h);
- warned = True;
- }
- }
-}
-
-
-static unsigned char *
-loadBitmap(int *w, int *h)
-{
- char *bitmap_name = get_string_resource ("bitmap", "Bitmap");
-
- if (bitmap_name &&
- *bitmap_name &&
- !!strcmp(bitmap_name, "none"))
- {
-#ifdef HAVE_XPM
- XpmInfo xpm_info = { 0, };
- XpmImage xpm_image = { 0, };
-
- int result = XpmReadFileToXpmImage (bitmap_name, &xpm_image, &xpm_info);
- if (result == XpmSuccess)
- {
- int x, y;
- unsigned char *result, *o;
- unsigned char *grays;
- XWindowAttributes xgwa;
-
- *w = xpm_image.width;
- *h = xpm_image.height;
- result = (unsigned char *) malloc ((*w) * (*h));
- if (!result)
- {
- fprintf(stderr, "%s: out of memory loading %s\n",
- progname, bitmap_name);
- exit (1);
- }
-
- XGetWindowAttributes (display, window, &xgwa);
-
- grays = (unsigned char *) calloc (xpm_image.ncolors+1, 1);
- for (x = 0; x < xpm_image.ncolors; x++)
- {
- XColor xc;
- XpmColor *xpmc = &xpm_image.colorTable[x];
- char *cstring = 0;
- if (xpmc->g_color && *xpmc->g_color)
- cstring = xpmc->g_color;
- else if (xpmc->g4_color && *xpmc->g4_color)
- cstring = xpmc->g4_color;
- else if (xpmc->c_color && *xpmc->c_color)
- cstring = xpmc->c_color;
- else
- cstring = xpmc->m_color;
-
- memset (&xc, 0, sizeof(xc));
- if (!cstring ||
- !*cstring ||
- !XParseColor (display, xgwa.colormap, cstring, &xc))
- grays[x] = 0;
- else
- grays[x] = (int) (((xc.red * 0.299) +
- (xc.green * 0.587) +
- (xc.blue * 0.114))
- / 255);
- }
-
- o = result;
- for (y = 0; y < *h; y++)
- for (x = 0; x < *w; x++)
- {
- int color = xpm_image.data[(y * (*w)) + x];
- if (color < 0 || color > xpm_image.ncolors) abort();
- *o++ = grays[color];
- }
- return result;
- }
- else /* failed to read XPM -- fall through and try XBM */
-#endif /* HAVE_XPM */
- {
-#ifdef HAVE_XMU
- XImage *ximage = 0;
- int width, height, xh, yh;
- int x, y;
- unsigned char *result, *o;
- Pixmap bitmap =
- XmuLocateBitmapFile (DefaultScreenOfDisplay (display),
- bitmap_name, 0, 0, &width, &height, &xh, &yh);
- if (!bitmap)
- {
- fprintf(stderr, "%s: unable to load bitmap file %s\n",
- progname, bitmap_name);
- exit (1);
- }
- ximage = XGetImage (display, bitmap, 0, 0, width, height,
- 1L, XYPixmap);
- XFreePixmap (display, bitmap);
-
- if (ximage->depth != 1) abort();
-
- *w = ximage->width;
- *h = ximage->height;
- result = (unsigned char *) malloc ((*w) * (*h));
- if (!result)
- {
- fprintf(stderr, "%s: out of memory loading %s\n",
- progname, bitmap_name);
- exit (1);
- }
-
- o = result;
- for (y = 0; y < *h; y++)
- for (x = 0; x < *w; x++)
- *o++ = (XGetPixel(ximage, x, y) ? 255 : 0);
-
- return result;
-
-#else /* !XMU */
- fprintf (stderr,
- "%s: your vendor doesn't ship the standard Xmu library.\n",
- progname);
- fprintf (stderr, "\tWe can't load XBM files without it.\n");
- exit (1);
-#endif /* !XMU */
- }
- }
-
- *w = 0;
- *h = 0;
- return 0;
-
-}
-
-
-\f
-char *progclass = "XFlame";
-
-char *defaults [] = {
- ".background: black",
- ".foreground: red",
- "*bitmap: none",
- "*bitmapBaseline: 20",
- "*delay: 10000",
- "*hspread: 30",
- "*vspread: 97",
- "*residual: 99",
- "*variance: 50",
- "*vartrend: 20",
-
-#ifdef HAVE_XSHM_EXTENSION
- "*useSHM: False", /* xshm turns out not to help. */
-#endif /* HAVE_XSHM_EXTENSION */
- 0
-};
-
-XrmOptionDescRec options [] = {
- { "-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 },
-#ifdef HAVE_XSHM_EXTENSION
- { "-shm", ".useSHM", XrmoptionNoArg, "True" },
- { "-no-shm", ".useSHM", XrmoptionNoArg, "False" },
-#endif /* HAVE_XSHM_EXTENSION */
- { 0, 0, 0, 0 }
-};
-
-void
-screenhack (Display *disp, Window win)
-{
- int theimx = 0, theimy = 0;
- int baseline = get_integer_resource ("bitmapBaseline", "Integer");
- int delay = get_integer_resource ("delay", "Integer");
- xim = NULL;
- top = 1;
- flame = NULL;
-
- GetXInfo(disp,win);
- InitColors();
- theim = loadBitmap(&theimx, &theimy);
-
- /* utils/xshm.c doesn't provide a way to free the shared-memory image, which
- makes it hard for us to react to window resizing. So, punt for now. The
- size of the window at startup is the size it will stay.
- */
- GetXInfo(disp,win);
-
- MakeImage();
- InitFlame();
- FlameFill(0);
-
- while (1)
- {
- FlameActive();
-
- if (theim)
- FlamePasteData(theim, (fwidth - theimx) / 2,
- fheight - theimy - baseline, theimx, theimy);
-
- FlameAdvance();
- Flame2Image();
- DisplayImage();
-
- XSync(display,False);
- screenhack_handle_events(display);
- if (delay)
- usleep (delay);
- }
-}