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;
129 xim = create_xshm_image (display, visual, depth, ZPixmap, NULL,
130 &shminfo, width, height);
134 xim = XCreateImage (display, visual, depth, ZPixmap, 0, NULL,
135 width, height, 32, 0);
137 xim->data = (char *) calloc(xim->height, xim->bytes_per_line);
138 if (!xim || !xim->data)
140 fprintf(stderr,"%s: out of memory.\n", progname);
145 gc = XCreateGC(display,window,0,&gcv);
154 for (i = 0; i < 256 * 2; i += 2)
158 int g = (i - 80) * 3;
159 int b = (i - 160) * 3;
162 if (r > 255) r = 255;
164 if (g > 255) g = 255;
166 if (b > 255) b = 255;
168 xcl.red = (unsigned short)((r << 8) | r);
169 xcl.green = (unsigned short)((g << 8) | g);
170 xcl.blue = (unsigned short)((b << 8) | b);
171 xcl.flags = DoRed | DoGreen | DoBlue;
173 XAllocColor(display,colormap,&xcl);
175 ctab[j++] = (int)xcl.pixel;
184 XShmPutImage(display, window, gc, xim, 0,(top - 1) << 1, 0,
185 (top - 1) << 1, width, height - ((top - 1) << 1), False);
187 XPutImage(display, window, gc, xim, 0, (top - 1) << 1, 0,
188 (top - 1) << 1, width, height - ((top - 1) << 1));
196 fheight = height / 2;
197 flame = (unsigned char *) malloc((fwidth + 2) * (fheight + 2)
198 * sizeof(unsigned char));
202 fprintf(stderr,"%s: out of memory\n", progname);
207 ihspread = get_integer_resource("hspread", "Integer");
208 ivspread = get_integer_resource("vspread", "Integer");
209 iresidual = get_integer_resource("residual", "Integer");
210 variance = get_integer_resource("variance", "Integer");
211 vartrend = get_integer_resource("vartrend", "Integer");
213 # define THROTTLE(VAR,NAME) \
214 if (VAR < 0 || VAR > 255) { \
215 fprintf(stderr, "%s: %s must be in the range 0-255 (not %d).\n", \
216 progname, NAME, VAR); \
218 THROTTLE (ihspread, "hspread");
219 THROTTLE (ivspread, "vspread");
220 THROTTLE (iresidual,"residual");
221 THROTTLE (variance, "variance");
222 THROTTLE (vartrend, "vartrend");
229 residual = iresidual;
241 ptr = (unsigned short *)xim->data;
242 ptr += (top << 1) * width;
243 ptr1 = flame + 1 + (top * (fwidth + 2));
245 for(y = top; y < fheight; y++)
247 for( x = 0; x < fwidth; x++)
250 v2 = (int)*(ptr1 + 1);
251 v3 = (int)*(ptr1 + fwidth + 2);
252 v4 = (int)*(ptr1 + fwidth + 2 + 1);
254 *ptr++ = (unsigned short)ctab[v1];
255 *ptr = (unsigned short)ctab[(v1 + v2) >> 1];
257 *ptr++ = (unsigned short)ctab[(v1 + v3) >> 1];
258 *ptr = (unsigned short)ctab[(v1 + v4) >> 1];
274 ptr = (unsigned int *)xim->data;
275 ptr += (top << 1) * width;
276 ptr1 = flame + 1 + (top * (fwidth + 2));
278 for( y = top; y < fheight; y++)
280 for( x = 0; x < fwidth; x++)
283 v2 = (int)*(ptr1 + 1);
284 v3 = (int)*(ptr1 + fwidth + 2);
285 v4 = (int)*(ptr1 + fwidth + 2 + 1);
287 *ptr++ = (unsigned int)ctab[v1];
288 *ptr = (unsigned int)ctab[(v1 + v2) >> 1];
290 *ptr++ = (unsigned int)ctab[(v1 + v3) >> 1];
291 *ptr = (unsigned int)ctab[(v1 + v4) >> 1];
307 ptr = (unsigned char *)xim->data;
308 ptr += (top << 1) * width;
309 ptr1 = flame + 1 + (top * (fwidth + 2));
311 for(y=top;y<fheight;y++)
313 for(x=0;x<fwidth;x++)
316 v2 = (int)*(ptr1 + 1);
317 v3 = (int)*(ptr1 + fwidth + 2);
318 v4 = (int)*(ptr1 + fwidth + 2 + 1);
320 *ptr++ = (unsigned char)ctab[v1];
321 *ptr = (unsigned char)ctab[(v1 + v2) >> 1];
323 *ptr++ = (unsigned char)ctab[(v1 + v3) >> 1];
324 *ptr = (unsigned char)ctab[(v1 + v4) >> 1];
333 Flame2Image1234567(void)
339 ptr1 = flame + 1 + (top * (fwidth + 2));
341 for( y = top; y < fheight; y++)
343 for( x = 0; x < fwidth; x++)
346 v2 = (int)*(ptr1 + 1);
347 v3 = (int)*(ptr1 + fwidth + 2);
348 v4 = (int)*(ptr1 + fwidth + 2 + 1);
350 XPutPixel(xim,(x << 1), (y << 1), ctab[v1]);
351 XPutPixel(xim,(x << 1) + 1,(y << 1), ctab[(v1 + v2) >> 1]);
352 XPutPixel(xim,(x << 1), (y << 1) + 1,ctab[(v1 + v3) >> 1]);
353 XPutPixel(xim,(x << 1) + 1,(y << 1) + 1,ctab[(v1 + v4) >> 1]);
361 if (depth >= 24) Flame2Image32();
362 else if (depth == 16) Flame2Image16();
363 else if (depth == 8) Flame2Image8();
364 else if (depth == 15) Flame2Image16();
365 else if (depth < 8) Flame2Image1234567();
366 else if (depth == 12) Flame2Image16();
375 ptr1 = flame + ((fheight + 1) * (fwidth + 2));
377 for (x = 0; x < fwidth + 2; x++)
380 v1 += ((random() % variance) - vartrend);
384 v1= (random() % 100);
386 residual += (random()%10);
388 hspread += (random()%15);
390 vspread += (random()%20);
392 residual = ((iresidual* 10) + (residual *90)) / 100;
393 hspread = ((ihspread * 10) + (hspread *90)) / 100;
394 vspread = ((ivspread * 10) + (vspread *90)) / 100;
405 for (y = fheight + 1; y >= top; y--)
408 unsigned char *ptr1 = flame + 1 + (y * (fwidth + 2));
409 for (x = 0; x < fwidth; x++)
416 ptr2 = ptr1 - fwidth - 2;
417 v3 = (v1 * vspread) >> 8;
423 *(ptr2) = (unsigned char)v2;
424 v3 = (v1 * hspread) >> 8;
425 v2 = (int)*(ptr2 + 1);
430 *(ptr2 + 1) = (unsigned char)v2;
431 v2 = (int)*(ptr2 - 1);
436 *(ptr2 - 1) = (unsigned char)v2;
440 v1 = (v1 * residual) >> 8;
441 *ptr1 = (unsigned char)v1;
461 for (y = 0; y < fheight + 1; y++)
463 unsigned char *ptr1 = flame + 1 + (y * (fwidth + 2));
464 for (x = 0; x < fwidth; x++)
474 FlamePasteData(unsigned char *d, int xx, int yy, int w, int h)
476 unsigned char *ptr1,*ptr2;
484 (xx + w <= fwidth) &&
488 for (y = 0; y < h; y++)
490 ptr1 = flame + 1 + xx + ((yy + y) * (fwidth + 2));
491 for (x = 0; x < w; x++)
494 *ptr1 += random() % (*ptr2 / 24);
503 static Bool warned = False;
506 fprintf (stderr, "%s: window is %dx%d; image must be "
507 "smaller than %dx%d (not %dx%d).\n",
508 progname, width, height, fwidth, fheight, w, h);
515 static unsigned char *
516 loadBitmap(int *w, int *h)
518 char *bitmap_name = get_string_resource ("bitmap", "Bitmap");
522 !!strcmp(bitmap_name, "none"))
524 XpmInfo xpm_info = { 0, };
525 XpmImage xpm_image = { 0, };
527 int result = XpmReadFileToXpmImage (bitmap_name, &xpm_image, &xpm_info);
528 if (result == XpmSuccess)
531 unsigned char *result, *o;
532 unsigned char *grays;
533 XWindowAttributes xgwa;
535 *w = xpm_image.width;
536 *h = xpm_image.height;
537 result = (unsigned char *) malloc ((*w) * (*h));
540 fprintf(stderr, "%s: out of memory loading %s\n",
541 progname, bitmap_name);
545 XGetWindowAttributes (display, window, &xgwa);
547 grays = (unsigned char *) calloc (xpm_image.ncolors+1, 1);
548 for (x = 0; x < xpm_image.ncolors; x++)
551 XpmColor *xpmc = &xpm_image.colorTable[x];
553 if (xpmc->g_color && *xpmc->g_color)
554 cstring = xpmc->g_color;
555 else if (xpmc->g4_color && *xpmc->g4_color)
556 cstring = xpmc->g4_color;
557 else if (xpmc->c_color && *xpmc->c_color)
558 cstring = xpmc->c_color;
560 cstring = xpmc->m_color;
562 memset (&xc, 0, sizeof(xc));
565 !XParseColor (display, xgwa.colormap, cstring, &xc))
568 grays[x] = (int) (((xc.red * 0.299) +
575 for (y = 0; y < *h; y++)
576 for (x = 0; x < *w; x++)
578 int color = xpm_image.data[(y * (*w)) + x];
579 if (color < 0 || color > xpm_image.ncolors) abort();
584 else /* failed to read XPM -- fall through and try XBM */
588 int width, height, xh, yh;
590 unsigned char *result, *o;
592 XmuLocateBitmapFile (DefaultScreenOfDisplay (display),
593 bitmap_name, 0, 0, &width, &height, &xh, &yh);
596 fprintf(stderr, "%s: unable to load bitmap file %s\n",
597 progname, bitmap_name);
600 ximage = XGetImage (display, bitmap, 0, 0, width, height,
602 XFreePixmap (display, bitmap);
604 if (ximage->depth != 1) abort();
608 result = (unsigned char *) malloc ((*w) * (*h));
611 fprintf(stderr, "%s: out of memory loading %s\n",
612 progname, bitmap_name);
617 for (y = 0; y < *h; y++)
618 for (x = 0; x < *w; x++)
619 *o++ = (XGetPixel(ximage, x, y) ? 255 : 0);
625 "%s: your vendor doesn't ship the standard Xmu library.\n",
627 fprintf (stderr, "\tWe can't load XBM files without it.\n");
641 char *progclass = "XFlame";
643 char *defaults [] = {
644 ".background: black",
647 "*bitmapBaseline: 20",
655 #ifdef HAVE_XSHM_EXTENSION
656 "*useSHM: False", /* xshm turns out not to help. */
657 #endif /* HAVE_XSHM_EXTENSION */
661 XrmOptionDescRec options [] = {
662 { "-delay", ".delay", XrmoptionSepArg, 0 },
663 { "-bitmap", ".bitmap", XrmoptionSepArg, 0 },
664 { "-baseline", ".bitmapBaseline", XrmoptionSepArg, 0 },
665 { "-hspread", ".hspread", XrmoptionSepArg, 0 },
666 { "-vspread", ".vspread", XrmoptionSepArg, 0 },
667 { "-residual", ".residual", XrmoptionSepArg, 0 },
668 { "-variance", ".variance", XrmoptionSepArg, 0 },
669 { "-vartrend", ".vartrend", XrmoptionSepArg, 0 },
670 #ifdef HAVE_XSHM_EXTENSION
671 { "-shm", ".useSHM", XrmoptionNoArg, "True" },
672 { "-no-shm", ".useSHM", XrmoptionNoArg, "False" },
673 #endif /* HAVE_XSHM_EXTENSION */
678 screenhack (Display *disp, Window win)
680 int theimx = 0, theimy = 0;
681 int baseline = get_integer_resource ("bitmapBaseline", "Integer");
682 int delay = get_integer_resource ("delay", "Integer");
689 theim = loadBitmap(&theimx, &theimy);
691 /* utils/xshm.c doesn't provide a way to free the shared-memory image, which
692 makes it hard for us to react to window resizing. So, punt for now. The
693 size of the window at startup is the size it will stay.
706 FlamePasteData(theim, (fwidth - theimx) / 2,
707 fheight - theimy - baseline, theimx, theimy);
713 XSync(display,False);
714 screenhack_handle_events(display);