-/* xflame, Copyright (c) 1996-1999 Carsten Haitzler <raster@redhat.com>
+/* xflame, Copyright (c) 1996-2002 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
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.
+
+ */
/* portions by Daniel Zahn <stumpy@religions.com> */
#include "screenhack.h"
-#include <X11/Xutil.h>
+#include "xpm-pixmap.h"
#include <limits.h>
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
#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;
+#include "images/bob.xbm"
+
+#define MAX_VAL 255
+
+struct state {
+ Display *dpy;
+ Window window;
+ int depth;
+ int width;
+ int height;
+ Colormap colormap;
+ Visual *visual;
+ Screen *screen;
+ Bool shared;
+ Bool bloom;
+ XImage *xim;
#ifdef HAVE_XSHM_EXTENSION
-static XShmSegmentInfo shminfo;
+ 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;
+ 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(Display *disp, Window win)
+GetXInfo(struct state *st)
{
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++;
+ 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(void)
+MakeImage(struct state *st)
{
XGCValues gcv;
- shared = True;
- xim = create_xshm_image (display, visual, depth, ZPixmap, NULL,
- &shminfo, width, height);
- if (!xim)
+#ifdef HAVE_XSHM_EXTENSION
+ st->shared = True;
+ st->xim = create_xshm_image (st->dpy, st->visual, st->depth, ZPixmap, NULL,
+ &st->shminfo, st->width, st->height);
+#else /* !HAVE_XSHM_EXTENSION */
+ st->xim = 0;
+#endif /* !HAVE_XSHM_EXTENSION */
+
+ if (!st->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)
+ st->shared = False;
+ st->xim = XCreateImage (st->dpy, st->visual, st->depth, ZPixmap, 0, NULL,
+ st->width, st->height, 32, 0);
+ if (st->xim)
+ st->xim->data = (char *) calloc(st->xim->height, st->xim->bytes_per_line);
+ if (!st->xim || !st->xim->data)
{
fprintf(stderr,"%s: out of memory.\n", progname);
exit(1);
}
}
- gc = XCreateGC(display,window,0,&gcv);
- if (!gc) exit (1);
+ st->gc = XCreateGC(st->dpy,st->window,0,&gcv);
+ if (!st->gc) exit (1);
}
static void
-InitColors(void)
+InitColors(struct state *st)
{
- int i = 0, j = 0;
+ 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 - 0) * 3;
- int g = (i - 80) * 3;
- int b = (i - 160) * 3;
+ 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;
xcl.blue = (unsigned short)((b << 8) | b);
xcl.flags = DoRed | DoGreen | DoBlue;
- XAllocColor(display,colormap,&xcl);
+ XAllocColor(st->dpy,st->colormap,&xcl);
- ctab[j++] = (int)xcl.pixel;
+ st->ctab[j++] = (int)xcl.pixel;
}
}
static void
-DisplayImage(void)
+DisplayImage(struct state *st)
{
- if (shared)
- XShmPutImage(display, window, gc, xim, 0,(top - 1) << 1, 0,
- (top - 1) << 1, width, height - ((top - 1) << 1), False);
+#ifdef HAVE_XSHM_EXTENSION
+ if (st->shared)
+ XShmPutImage(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), False);
else
- XPutImage(display, window, gc, xim, 0, (top - 1) << 1, 0,
- (top - 1) << 1, width, height - ((top - 1) << 1));
+#endif /* HAVE_XSHM_EXTENSION */
+ XPutImage(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));
}
static void
-InitFlame(void)
+InitFlame(struct state *st)
{
- fwidth = width / 2;
- fheight = height / 2;
- flame = (unsigned char *) malloc((fwidth + 2) * (fheight + 2)
+ st->fwidth = st->width / 2;
+ st->fheight = st->height / 2;
+ st->flame = (unsigned char *) malloc((st->fwidth + 2) * (st->fheight + 2)
* sizeof(unsigned char));
- if (!flame)
+ if (!st->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");
+ 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 (ihspread, "hspread");
- THROTTLE (ivspread, "vspread");
- THROTTLE (iresidual,"residual");
- THROTTLE (variance, "variance");
- THROTTLE (vartrend, "vartrend");
+ THROTTLE (st->ihspread, "hspread");
+ THROTTLE (st->ivspread, "vspread");
+ THROTTLE (st->iresidual,"residual");
+ THROTTLE (st->variance, "variance");
+ THROTTLE (st->vartrend, "vartrend");
# undef THROTTLE
- hspread = ihspread;
- vspread = ivspread;
- residual = iresidual;
+ st->hspread = st->ihspread;
+ st->vspread = st->ivspread;
+ st->residual = st->iresidual;
}
static void
-Flame2Image16(void)
+Flame2Image16(struct state *st)
{
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));
+ ptr = (unsigned short *)st->xim->data;
+ ptr += (st->top << 1) * st->width;
+ ptr1 = st->flame + 1 + (st->top * (st->fwidth + 2));
- for(y = top; y < fheight; y++)
+ for(y = st->top; y < st->fheight; y++)
{
- for( x = 0; x < fwidth; x++)
+ for( x = 0; x < st->fwidth; x++)
{
v1 = (int)*ptr1;
v2 = (int)*(ptr1 + 1);
- v3 = (int)*(ptr1 + fwidth + 2);
- v4 = (int)*(ptr1 + fwidth + 2 + 1);
+ v3 = (int)*(ptr1 + st->fwidth + 2);
+ v4 = (int)*(ptr1 + st->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++ = (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 += width;
+ ptr += st->width;
ptr1 += 2;
}
}
static void
-Flame2Image32(void)
+Flame2Image32(struct state *st)
{
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));
+ ptr = (unsigned int *)st->xim->data;
+ ptr += (st->top << 1) * st->width;
+ ptr1 = st->flame + 1 + (st->top * (st->fwidth + 2));
- for( y = top; y < fheight; y++)
+ for( y = st->top; y < st->fheight; y++)
{
- for( x = 0; x < fwidth; x++)
+ for( x = 0; x < st->fwidth; x++)
{
v1 = (int)*ptr1;
v2 = (int)*(ptr1 + 1);
- v3 = (int)*(ptr1 + fwidth + 2);
- v4 = (int)*(ptr1 + fwidth + 2 + 1);
+ v3 = (int)*(ptr1 + st->fwidth + 2);
+ v4 = (int)*(ptr1 + st->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++ = (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 += width;
+ ptr += st->width;
ptr1 += 2;
}
}
static void
-Flame2Image8(void)
+Flame2Image24(struct state *st)
{
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));
+ 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=top;y<fheight;y++)
+ for( y = st->top; y < st->fheight; y++)
{
- for(x=0;x<fwidth;x++)
+ unsigned char *last_ptr = ptr;
+ for( x = 0; x < st->fwidth; x++)
{
v1 = (int)*ptr1;
v2 = (int)*(ptr1 + 1);
- v3 = (int)*(ptr1 + fwidth + 2);
- v4 = (int)*(ptr1 + fwidth + 2 + 1);
+ v3 = (int)*(ptr1 + st->fwidth + 2);
+ v4 = (int)*(ptr1 + st->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[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 += width;
+
+ ptr = last_ptr + (st->xim->bytes_per_line << 1);
ptr1 += 2;
}
}
static void
-Flame2Image1234567(void)
+Flame2Image8(struct state *st)
{
int x,y;
+ unsigned char *ptr;
unsigned char *ptr1;
int v1,v2,v3,v4;
- ptr1 = flame + 1 + (top * (fwidth + 2));
+ ptr = (unsigned char *)st->xim->data;
+ ptr += (st->top << 1) * st->width;
+ ptr1 = st->flame + 1 + (st->top * (st->fwidth + 2));
- for( y = top; y < fheight; y++)
+ for(y=st->top;y<st->fheight;y++)
{
- for( x = 0; x < fwidth; x++)
+ for(x=0;x<st->fwidth;x++)
{
v1 = (int)*ptr1;
v2 = (int)*(ptr1 + 1);
- v3 = (int)*(ptr1 + fwidth + 2);
- v4 = (int)*(ptr1 + fwidth + 2 + 1);
+ v3 = (int)*(ptr1 + st->fwidth + 2);
+ v4 = (int)*(ptr1 + st->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]);
+ *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
-Flame2Image(void)
+Flame2Image1234567(struct state *st)
{
- 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();
+ 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(void)
+FlameActive(struct state *st)
{
int x,v1;
unsigned char *ptr1;
- ptr1 = flame + ((fheight + 1) * (fwidth + 2));
+ ptr1 = st->flame + ((st->fheight + 1) * (st->fwidth + 2));
- for (x = 0; x < fwidth + 2; x++)
+ for (x = 0; x < st->fwidth + 2; x++)
{
v1 = *ptr1;
- v1 += ((random() % variance) - vartrend);
+ v1 += ((random() % st->variance) - st->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;
+ 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(void)
+FlameAdvance(struct state *st)
{
int x,y;
unsigned char *ptr2;
- int newtop = top;
+ int newtop = st->top;
- for (y = fheight + 1; y >= top; y--)
+ for (y = st->fheight + 1; y >= st->top; y--)
{
int used = 0;
- unsigned char *ptr1 = flame + 1 + (y * (fwidth + 2));
- for (x = 0; x < fwidth; x++)
+ 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 - fwidth - 2;
- v3 = (v1 * vspread) >> 8;
+ ptr2 = ptr1 - st->fwidth - 2;
+ v3 = (v1 * st->vspread) >> 8;
v2 = (int)*(ptr2);
v2 += v3;
- if (v2 > MAX)
- v2 = MAX;
+ if (v2 > MAX_VAL)
+ v2 = MAX_VAL;
*(ptr2) = (unsigned char)v2;
- v3 = (v1 * hspread) >> 8;
+ v3 = (v1 * st->hspread) >> 8;
v2 = (int)*(ptr2 + 1);
v2 += v3;
- if (v2 > MAX)
- v2 = MAX;
+ if (v2 > MAX_VAL)
+ v2 = MAX_VAL;
*(ptr2 + 1) = (unsigned char)v2;
v2 = (int)*(ptr2 - 1);
v2 += v3;
- if (v2 > MAX)
- v2 = MAX;
+ if (v2 > MAX_VAL)
+ v2 = MAX_VAL;
*(ptr2 - 1) = (unsigned char)v2;
- if (y < fheight + 1)
+ if (y < st->fheight + 1)
{
- v1 = (v1 * residual) >> 8;
+ v1 = (v1 * st->residual) >> 8;
*ptr1 = (unsigned char)v1;
}
}
if (used)
newtop = y - 1;
}
+
+ /* clean up the right gutter */
+ {
+ int v1 = (int)*ptr1;
+ v1 = (v1 * st->residual) >> 8;
+ *ptr1 = (unsigned char)v1;
+ }
}
- top = newtop - 1;
+ st->top = newtop - 1;
- if (top < 1)
- top = 1;
+ if (st->top < 1)
+ st->top = 1;
}
static void
-FlameFill(int val)
+FlameFill(struct state *st, int val)
{
int x, y;
- for (y = 0; y < fheight + 1; y++)
+ for (y = 0; y < st->fheight + 1; y++)
{
- unsigned char *ptr1 = flame + 1 + (y * (fwidth + 2));
- for (x = 0; x < fwidth; x++)
+ unsigned char *ptr1 = st->flame + 1 + (y * (st->fwidth + 2));
+ for (x = 0; x < st->fwidth; x++)
{
*ptr1 = val;
ptr1++;
static void
-FlamePasteData(unsigned char *d, int xx, int yy, int w, int h)
+FlamePasteData(struct state *st,
+ unsigned char *d, int xx, int yy, int w, int h)
{
unsigned char *ptr1,*ptr2;
ptr2 = d;
if ((xx >= 0) &&
(yy >= 0) &&
- (xx + w <= fwidth) &&
- (yy + h <= fheight))
+ (xx + w <= st->fwidth) &&
+ (yy + h <= st->fheight))
{
int x, y;
for (y = 0; y < h; y++)
{
- ptr1 = flame + 1 + xx + ((yy + y) * (fwidth + 2));
+ ptr1 = st->flame + 1 + xx + ((yy + y) * (st->fwidth + 2));
for (x = 0; x < w; x++)
{
if (*ptr2 / 24)
static Bool warned = False;
if (!warned)
{
- fprintf (stderr, "%s: window is %dx%d; image must be "
+ fprintf (stderr, "%s: st->window is %dx%d; image must be "
"smaller than %dx%d (not %dx%d).\n",
- progname, width, height, fwidth, fheight, w, h);
+ progname, st->width, st->height, st->fwidth, st->fheight, w, h);
warned = True;
}
}
static unsigned char *
-loadBitmap(int *w, int *h)
+loadBitmap(struct state *st, int *w, int *h)
{
- char *bitmap_name = get_string_resource ("bitmap", "Bitmap");
-
- if (bitmap_name &&
- *bitmap_name &&
- !!strcmp(bitmap_name, "none"))
+ char *bitmap_name = get_string_resource (st->dpy, "bitmap", "Bitmap");
+
+#ifdef HAVE_COCOA
+ bitmap_name = "(default)"; /* #### always use builtin */
+#endif /* HAVE_COCOA */
+
+ if (!bitmap_name ||
+ !*bitmap_name ||
+ !strcmp(bitmap_name, "none"))
+ ;
+ else if (!strcmp(bitmap_name, "(default)")) /* use the builtin */
{
- XpmInfo xpm_info = { 0, };
- XpmImage xpm_image = { 0, };
+ XImage *ximage;
+ unsigned char *result, *o;
+ char *bits = (char *) malloc (sizeof(bob_bits));
+ int x, y;
+ int scale = ((st->width > bob_width * 11) ? 2 : 1);
+
+ memcpy (bits, bob_bits, sizeof(bob_bits));
+ ximage = XCreateImage (st->dpy, st->visual, 1, XYBitmap, 0, bits,
+ bob_width, bob_height, 8, 0);
+ ximage->byte_order = LSBFirst;
+ ximage->bitmap_bit_order = LSBFirst;
+ *w = ximage->width * scale;
+ *h = ximage->height * scale;
+ o = result = (unsigned char *) malloc ((*w * scale) * (*h * scale));
+ for (y = 0; y < *h; y++)
+ for (x = 0; x < *w; x++)
+ *o++ = (XGetPixel(ximage, x/scale, y/scale) ? 255 : 0);
+
+ return result;
+ }
+ else /* load a bitmap file */
+#ifdef HAVE_COCOA
+ abort(); /* #### fix me */
+#else
+ {
+ Pixmap pixmap =
+ xpm_file_to_pixmap (st->dpy, st->window, bitmap_name, &st->width, &st->height, 0);
+ XImage *image;
+ int x, y;
+ unsigned char *result, *o;
+ XColor colors[256];
+ Bool cmap_p = has_writable_cells (st->screen, st->visual);
- int result = XpmReadFileToXpmImage (bitmap_name, &xpm_image, &xpm_info);
- if (result == XpmSuccess)
+ if (cmap_p)
{
- 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);
- }
+ int i;
+ for (i = 0; i < countof (colors); i++)
+ colors[i].pixel = i;
+ XQueryColors (st->dpy, st->colormap, colors, countof (colors));
+ }
- XGetWindowAttributes (display, window, &xgwa);
+ image = XGetImage (st->dpy, pixmap, 0, 0, st->width, st->height, ~0L, ZPixmap);
+ XFreePixmap(st->dpy, pixmap);
+
+ result = (unsigned char *) malloc (st->width * st->height);
+ o = result;
+ for (y = 0; y < st->height; y++)
+ for (x = 0; x < st->width; x++)
+ {
+ int rgba = XGetPixel (image, x, y);
+ int gray;
+ if (cmap_p)
+ gray = ((200 - ((((colors[rgba].red >> 8) & 0xFF) +
+ ((colors[rgba].green >> 8) & 0xFF) +
+ ((colors[rgba].blue >> 8) & 0xFF))
+ >> 1))
+ & 0xFF);
+ else
+ /* This is *so* not handling all the cases... */
+ gray = (image->depth > 16
+ ? ((((rgba >> 24) & 0xFF) +
+ ((rgba >> 16) & 0xFF) +
+ ((rgba >> 8) & 0xFF) +
+ ((rgba ) & 0xFF)) >> 2)
+ : ((((rgba >> 12) & 0x0F) +
+ ((rgba >> 8) & 0x0F) +
+ ((rgba >> 4) & 0x0F) +
+ ((rgba ) & 0x0F)) >> 1));
+
+ *o++ = 255 - gray;
+ }
+
+ XFree (image->data);
+ image->data = 0;
+ XDestroyImage (image);
+
+ *w = st->width;
+ *h = st->height;
+ return result;
+ }
+#endif /* !HAVE_COCOA */
- 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);
- }
+ *w = 0;
+ *h = 0;
+ return 0;
- 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 */
- {
-#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();
+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, &st->theimx, &st->theimy);
- *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);
- }
+ /* 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(st);
- o = result;
- for (y = 0; y < *h; y++)
- for (x = 0; x < *w; x++)
- *o++ = (XGetPixel(ximage, x, y) ? 255 : 0);
+ MakeImage(st);
+ InitFlame(st);
+ FlameFill(st,0);
- return result;
+ return st;
+}
-#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 */
- }
- }
+static unsigned long
+xflame_draw (Display *dpy, Window win, void *closure)
+{
+ struct state *st = (struct state *) closure;
+ FlameActive(st);
- *w = 0;
- *h = 0;
- return 0;
+ 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)
+{
+}
+
+static Bool
+xflame_event (Display *dpy, Window window, void *closure, XEvent *event)
+{
+ return False;
+}
+static void
+xflame_free (Display *dpy, Window window, void *closure)
+{
}
\f
-char *progclass = "XFlame";
-char *defaults [] = {
+static const char *xflame_defaults [] = {
".background: black",
- ".foreground: red",
- "*bitmap: none",
+ ".foreground: #FFAF5F",
+ "*fpsTop: true",
+ "*fpsSolid: true",
+ "*bitmap: (default)",
"*bitmapBaseline: 20",
"*delay: 10000",
"*hspread: 30",
"*residual: 99",
"*variance: 50",
"*vartrend: 20",
+ "*bloom: True",
#ifdef HAVE_XSHM_EXTENSION
"*useSHM: False", /* xshm turns out not to help. */
0
};
-XrmOptionDescRec options [] = {
+static XrmOptionDescRec xflame_options [] = {
+ { "-foreground",".foreground", XrmoptionSepArg, 0 },
+ { "-fg", ".foreground", XrmoptionSepArg, 0 },
{ "-delay", ".delay", XrmoptionSepArg, 0 },
{ "-bitmap", ".bitmap", XrmoptionSepArg, 0 },
{ "-baseline", ".bitmapBaseline", 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" },
{ 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);
- }
-}
+XSCREENSAVER_MODULE ("XFlame", xflame)