1 /* xflame, Copyright (c) 1996-1999 Carsten Haitzler <raster@redhat.com>
3 * Permission to use, copy, modify, distribute, and sell this software and its
4 * documentation for any purpose is hereby granted without fee, provided that
5 * the above copyright notice appear in all copies and that both that
6 * copyright notice and this permission notice appear in supporting
7 * documentation. No representations are made about the suitability of this
8 * software for any purpose. It is provided "as is" without express or
12 /* Version history as near as I (jwz) can piece together:
14 * Carsten Haitzler <raster@redhat.com> wrote the first version in 1996.
16 * Rahul Jain <rahul@rice.edu> added support for TrueColor displays.
18 * Someone did a rough port of it to use the xscreensaver utility routines
19 instead of creating its own window by hand.
21 * Someone (probably Raster) came up with a subsequent version that had
22 a Red Hat logo hardcoded into it.
24 * Daniel Zahn <stumpy@religions.com> found that version in 1998, and
25 hacked it to be able to load a different logo from a PGM (P5) file,
26 with a single hardcoded pathname.
28 * Jamie Zawinski <jwz@jwz.org> found several versions of xflame in
29 March 1999, and pieced them together. Changes:
31 - Correct and fault-tolerant use of the Shared Memory extension;
32 previous versions of xflame did not work when $DISPLAY was remote.
34 - Replaced PGM-reading code with code that can read arbitrary XBM
35 and XPM files (color ones will be converted to grayscale.)
37 - Command-line options all around -- no hardcoded pathnames or
40 - General cleanup and portability tweaks.
44 /* portions by Daniel Zahn <stumpy@religions.com> */
47 #include "screenhack.h"
48 #include <X11/Xutil.h>
51 #ifdef HAVE_XSHM_EXTENSION
53 #endif /* HAVE_XSHM_EXTENSION */
57 # ifndef PIXEL_ALREADY_TYPEDEFED
58 # define PIXEL_ALREADY_TYPEDEFED /* Sigh, Xmu/Drawing.h needs this... */
64 # include <X11/Xmu/Drawing.h>
66 # include <Xmu/Drawing.h>
72 static Display *display;
77 static Colormap colormap;
78 static Visual *visual;
81 #ifdef HAVE_XSHM_EXTENSION
82 static XShmSegmentInfo shminfo;
83 #endif /* HAVE_XSHM_EXTENSION */
87 static unsigned char *flame;
88 static unsigned char *theim;
103 GetXInfo(Display *disp, Window win)
105 XWindowAttributes xwa;
107 XGetWindowAttributes(disp,win,&xwa);
111 colormap = xwa.colormap;
128 #ifdef HAVE_XSHM_EXTENSION
130 xim = create_xshm_image (display, visual, depth, ZPixmap, NULL,
131 &shminfo, width, height);
132 #else /* !HAVE_XSHM_EXTENSION */
134 #endif /* !HAVE_XSHM_EXTENSION */
139 xim = XCreateImage (display, visual, depth, ZPixmap, 0, NULL,
140 width, height, 32, 0);
142 xim->data = (char *) calloc(xim->height, xim->bytes_per_line);
143 if (!xim || !xim->data)
145 fprintf(stderr,"%s: out of memory.\n", progname);
150 gc = XCreateGC(display,window,0,&gcv);
159 for (i = 0; i < 256 * 2; i += 2)
163 int g = (i - 80) * 3;
164 int b = (i - 160) * 3;
167 if (r > 255) r = 255;
169 if (g > 255) g = 255;
171 if (b > 255) b = 255;
173 xcl.red = (unsigned short)((r << 8) | r);
174 xcl.green = (unsigned short)((g << 8) | g);
175 xcl.blue = (unsigned short)((b << 8) | b);
176 xcl.flags = DoRed | DoGreen | DoBlue;
178 XAllocColor(display,colormap,&xcl);
180 ctab[j++] = (int)xcl.pixel;
188 #ifdef HAVE_XSHM_EXTENSION
190 XShmPutImage(display, window, gc, xim, 0,(top - 1) << 1, 0,
191 (top - 1) << 1, width, height - ((top - 1) << 1), False);
193 #endif /* HAVE_XSHM_EXTENSION */
194 XPutImage(display, window, gc, xim, 0, (top - 1) << 1, 0,
195 (top - 1) << 1, width, height - ((top - 1) << 1));
203 fheight = height / 2;
204 flame = (unsigned char *) malloc((fwidth + 2) * (fheight + 2)
205 * sizeof(unsigned char));
209 fprintf(stderr,"%s: out of memory\n", progname);
214 ihspread = get_integer_resource("hspread", "Integer");
215 ivspread = get_integer_resource("vspread", "Integer");
216 iresidual = get_integer_resource("residual", "Integer");
217 variance = get_integer_resource("variance", "Integer");
218 vartrend = get_integer_resource("vartrend", "Integer");
220 # define THROTTLE(VAR,NAME) \
221 if (VAR < 0 || VAR > 255) { \
222 fprintf(stderr, "%s: %s must be in the range 0-255 (not %d).\n", \
223 progname, NAME, VAR); \
225 THROTTLE (ihspread, "hspread");
226 THROTTLE (ivspread, "vspread");
227 THROTTLE (iresidual,"residual");
228 THROTTLE (variance, "variance");
229 THROTTLE (vartrend, "vartrend");
236 residual = iresidual;
248 ptr = (unsigned short *)xim->data;
249 ptr += (top << 1) * width;
250 ptr1 = flame + 1 + (top * (fwidth + 2));
252 for(y = top; y < fheight; y++)
254 for( x = 0; x < fwidth; x++)
257 v2 = (int)*(ptr1 + 1);
258 v3 = (int)*(ptr1 + fwidth + 2);
259 v4 = (int)*(ptr1 + fwidth + 2 + 1);
261 *ptr++ = (unsigned short)ctab[v1];
262 *ptr = (unsigned short)ctab[(v1 + v2) >> 1];
264 *ptr++ = (unsigned short)ctab[(v1 + v3) >> 1];
265 *ptr = (unsigned short)ctab[(v1 + v4) >> 1];
281 ptr = (unsigned int *)xim->data;
282 ptr += (top << 1) * width;
283 ptr1 = flame + 1 + (top * (fwidth + 2));
285 for( y = top; y < fheight; y++)
287 for( x = 0; x < fwidth; x++)
290 v2 = (int)*(ptr1 + 1);
291 v3 = (int)*(ptr1 + fwidth + 2);
292 v4 = (int)*(ptr1 + fwidth + 2 + 1);
294 *ptr++ = (unsigned int)ctab[v1];
295 *ptr = (unsigned int)ctab[(v1 + v2) >> 1];
297 *ptr++ = (unsigned int)ctab[(v1 + v3) >> 1];
298 *ptr = (unsigned int)ctab[(v1 + v4) >> 1];
314 ptr = (unsigned char *)xim->data;
315 ptr += (top << 1) * width;
316 ptr1 = flame + 1 + (top * (fwidth + 2));
318 for(y=top;y<fheight;y++)
320 for(x=0;x<fwidth;x++)
323 v2 = (int)*(ptr1 + 1);
324 v3 = (int)*(ptr1 + fwidth + 2);
325 v4 = (int)*(ptr1 + fwidth + 2 + 1);
327 *ptr++ = (unsigned char)ctab[v1];
328 *ptr = (unsigned char)ctab[(v1 + v2) >> 1];
330 *ptr++ = (unsigned char)ctab[(v1 + v3) >> 1];
331 *ptr = (unsigned char)ctab[(v1 + v4) >> 1];
340 Flame2Image1234567(void)
346 ptr1 = flame + 1 + (top * (fwidth + 2));
348 for( y = top; y < fheight; y++)
350 for( x = 0; x < fwidth; x++)
353 v2 = (int)*(ptr1 + 1);
354 v3 = (int)*(ptr1 + fwidth + 2);
355 v4 = (int)*(ptr1 + fwidth + 2 + 1);
357 XPutPixel(xim,(x << 1), (y << 1), ctab[v1]);
358 XPutPixel(xim,(x << 1) + 1,(y << 1), ctab[(v1 + v2) >> 1]);
359 XPutPixel(xim,(x << 1), (y << 1) + 1,ctab[(v1 + v3) >> 1]);
360 XPutPixel(xim,(x << 1) + 1,(y << 1) + 1,ctab[(v1 + v4) >> 1]);
368 if (depth >= 24) Flame2Image32();
369 else if (depth == 16) Flame2Image16();
370 else if (depth == 8) Flame2Image8();
371 else if (depth == 15) Flame2Image16();
372 else if (depth < 8) Flame2Image1234567();
373 else if (depth == 12) Flame2Image16();
382 ptr1 = flame + ((fheight + 1) * (fwidth + 2));
384 for (x = 0; x < fwidth + 2; x++)
387 v1 += ((random() % variance) - vartrend);
391 v1= (random() % 100);
393 residual += (random()%10);
395 hspread += (random()%15);
397 vspread += (random()%20);
399 residual = ((iresidual* 10) + (residual *90)) / 100;
400 hspread = ((ihspread * 10) + (hspread *90)) / 100;
401 vspread = ((ivspread * 10) + (vspread *90)) / 100;
412 for (y = fheight + 1; y >= top; y--)
415 unsigned char *ptr1 = flame + 1 + (y * (fwidth + 2));
416 for (x = 0; x < fwidth; x++)
423 ptr2 = ptr1 - fwidth - 2;
424 v3 = (v1 * vspread) >> 8;
430 *(ptr2) = (unsigned char)v2;
431 v3 = (v1 * hspread) >> 8;
432 v2 = (int)*(ptr2 + 1);
437 *(ptr2 + 1) = (unsigned char)v2;
438 v2 = (int)*(ptr2 - 1);
443 *(ptr2 - 1) = (unsigned char)v2;
447 v1 = (v1 * residual) >> 8;
448 *ptr1 = (unsigned char)v1;
468 for (y = 0; y < fheight + 1; y++)
470 unsigned char *ptr1 = flame + 1 + (y * (fwidth + 2));
471 for (x = 0; x < fwidth; x++)
481 FlamePasteData(unsigned char *d, int xx, int yy, int w, int h)
483 unsigned char *ptr1,*ptr2;
491 (xx + w <= fwidth) &&
495 for (y = 0; y < h; y++)
497 ptr1 = flame + 1 + xx + ((yy + y) * (fwidth + 2));
498 for (x = 0; x < w; x++)
501 *ptr1 += random() % (*ptr2 / 24);
510 static Bool warned = False;
513 fprintf (stderr, "%s: window is %dx%d; image must be "
514 "smaller than %dx%d (not %dx%d).\n",
515 progname, width, height, fwidth, fheight, w, h);
522 static unsigned char *
523 loadBitmap(int *w, int *h)
525 char *bitmap_name = get_string_resource ("bitmap", "Bitmap");
529 !!strcmp(bitmap_name, "none"))
532 XpmInfo xpm_info = { 0, };
533 XpmImage xpm_image = { 0, };
535 int result = XpmReadFileToXpmImage (bitmap_name, &xpm_image, &xpm_info);
536 if (result == XpmSuccess)
539 unsigned char *result, *o;
540 unsigned char *grays;
541 XWindowAttributes xgwa;
543 *w = xpm_image.width;
544 *h = xpm_image.height;
545 result = (unsigned char *) malloc ((*w) * (*h));
548 fprintf(stderr, "%s: out of memory loading %s\n",
549 progname, bitmap_name);
553 XGetWindowAttributes (display, window, &xgwa);
555 grays = (unsigned char *) calloc (xpm_image.ncolors+1, 1);
556 for (x = 0; x < xpm_image.ncolors; x++)
559 XpmColor *xpmc = &xpm_image.colorTable[x];
561 if (xpmc->g_color && *xpmc->g_color)
562 cstring = xpmc->g_color;
563 else if (xpmc->g4_color && *xpmc->g4_color)
564 cstring = xpmc->g4_color;
565 else if (xpmc->c_color && *xpmc->c_color)
566 cstring = xpmc->c_color;
568 cstring = xpmc->m_color;
570 memset (&xc, 0, sizeof(xc));
573 !XParseColor (display, xgwa.colormap, cstring, &xc))
576 grays[x] = (int) (((xc.red * 0.299) +
583 for (y = 0; y < *h; y++)
584 for (x = 0; x < *w; x++)
586 int color = xpm_image.data[(y * (*w)) + x];
587 if (color < 0 || color > xpm_image.ncolors) abort();
592 else /* failed to read XPM -- fall through and try XBM */
593 #endif /* HAVE_XPM */
597 int width, height, xh, yh;
599 unsigned char *result, *o;
601 XmuLocateBitmapFile (DefaultScreenOfDisplay (display),
602 bitmap_name, 0, 0, &width, &height, &xh, &yh);
605 fprintf(stderr, "%s: unable to load bitmap file %s\n",
606 progname, bitmap_name);
609 ximage = XGetImage (display, bitmap, 0, 0, width, height,
611 XFreePixmap (display, bitmap);
613 if (ximage->depth != 1) abort();
617 result = (unsigned char *) malloc ((*w) * (*h));
620 fprintf(stderr, "%s: out of memory loading %s\n",
621 progname, bitmap_name);
626 for (y = 0; y < *h; y++)
627 for (x = 0; x < *w; x++)
628 *o++ = (XGetPixel(ximage, x, y) ? 255 : 0);
634 "%s: your vendor doesn't ship the standard Xmu library.\n",
636 fprintf (stderr, "\tWe can't load XBM files without it.\n");
650 char *progclass = "XFlame";
652 char *defaults [] = {
653 ".background: black",
656 "*bitmapBaseline: 20",
664 #ifdef HAVE_XSHM_EXTENSION
665 "*useSHM: False", /* xshm turns out not to help. */
666 #endif /* HAVE_XSHM_EXTENSION */
670 XrmOptionDescRec options [] = {
671 { "-delay", ".delay", XrmoptionSepArg, 0 },
672 { "-bitmap", ".bitmap", XrmoptionSepArg, 0 },
673 { "-baseline", ".bitmapBaseline", XrmoptionSepArg, 0 },
674 { "-hspread", ".hspread", XrmoptionSepArg, 0 },
675 { "-vspread", ".vspread", XrmoptionSepArg, 0 },
676 { "-residual", ".residual", XrmoptionSepArg, 0 },
677 { "-variance", ".variance", XrmoptionSepArg, 0 },
678 { "-vartrend", ".vartrend", XrmoptionSepArg, 0 },
679 #ifdef HAVE_XSHM_EXTENSION
680 { "-shm", ".useSHM", XrmoptionNoArg, "True" },
681 { "-no-shm", ".useSHM", XrmoptionNoArg, "False" },
682 #endif /* HAVE_XSHM_EXTENSION */
687 screenhack (Display *disp, Window win)
689 int theimx = 0, theimy = 0;
690 int baseline = get_integer_resource ("bitmapBaseline", "Integer");
691 int delay = get_integer_resource ("delay", "Integer");
698 theim = loadBitmap(&theimx, &theimy);
700 /* utils/xshm.c doesn't provide a way to free the shared-memory image, which
701 makes it hard for us to react to window resizing. So, punt for now. The
702 size of the window at startup is the size it will stay.
715 FlamePasteData(theim, (fwidth - theimx) / 2,
716 fheight - theimy - baseline, theimx, theimy);
722 XSync(display,False);
723 screenhack_handle_events(display);