1 /* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@mcom.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 /* Rotate a bitmap using using bitblts.
13 The bitmap must be square, and must be a power of 2 in size.
14 This was translated from SmallTalk code which appeared in the
15 August 1981 issue of Byte magazine.
17 The input bitmap may be non-square, it is padded and centered
18 with the background color. Another way would be to subdivide
19 the bitmap into square components and rotate them independently
20 (and preferably in parallel), but I don't think that would be as
23 It's too bad almost nothing uses blitter hardware these days,
24 or this might actually win.
27 #include "screenhack.h"
32 # ifndef PIXEL_ALREADY_TYPEDEFED
33 # define PIXEL_ALREADY_TYPEDEFED /* Sigh, Xmu/Drawing.h needs this... */
38 #include <X11/Xmu/Drawing.h>
40 #include "sys$common:[decw$include.xmu]Drawing.h"
43 #include "default.xbm"
47 static unsigned int size;
48 static Pixmap self, temp, mask;
49 static GC SET, CLR, CPY, IOR, AND, XOR;
51 static int delay, delay2;
54 static unsigned int fg, bg;
56 static void rotate(), init (), display ();
58 #define copy_all_to(from, xoff, yoff, to, gc) \
59 XCopyArea (dpy, (from), (to), (gc), 0, 0, \
60 size-(xoff), size-(yoff), (xoff), (yoff))
62 #define copy_all_from(to, xoff, yoff, from, gc) \
63 XCopyArea (dpy, (from), (to), (gc), (xoff), (yoff), \
64 size-(xoff), size-(yoff), 0, 0)
69 int qwad; /* fuckin' C, man... who needs namespaces? */
70 XFillRectangle (dpy, mask, CLR, 0, 0, size, size);
71 XFillRectangle (dpy, mask, SET, 0, 0, size>>1, size>>1);
72 for (qwad = size>>1; qwad > 0; qwad>>=1)
74 if (delay) usleep (delay);
75 copy_all_to (mask, 0, 0, temp, CPY); /* 1 */
76 copy_all_to (mask, 0, qwad, temp, IOR); /* 2 */
77 copy_all_to (self, 0, 0, temp, AND); /* 3 */
78 copy_all_to (temp, 0, 0, self, XOR); /* 4 */
79 copy_all_from (temp, qwad, 0, self, XOR); /* 5 */
80 copy_all_from (self, qwad, 0, self, IOR); /* 6 */
81 copy_all_to (temp, qwad, 0, self, XOR); /* 7 */
82 copy_all_to (self, 0, 0, temp, CPY); /* 8 */
83 copy_all_from (temp, qwad, qwad, self, XOR); /* 9 */
84 copy_all_to (mask, 0, 0, temp, AND); /* A */
85 copy_all_to (temp, 0, 0, self, XOR); /* B */
86 copy_all_to (temp, qwad, qwad, self, XOR); /* C */
87 copy_all_from (mask, qwad>>1, qwad>>1, mask, AND); /* D */
88 copy_all_to (mask, qwad, 0, mask, IOR); /* E */
89 copy_all_to (mask, 0, qwad, mask, IOR); /* F */
95 read_bitmap (bitmap_name, widthP, heightP)
97 int *widthP, *heightP;
100 XpmAttributes xpmattrs;
102 xpmattrs.valuemask = 0;
104 result = XpmReadFileToPixmap (dpy, window, bitmap_name, &bitmap, 0,
109 fprintf (stderr, "%s: warning: xpm color substitution performed\n",
113 *widthP = xpmattrs.width;
114 *heightP = xpmattrs.height;
121 fprintf (stderr, "%s: xpm: color allocation failed\n", progname);
124 fprintf (stderr, "%s: xpm: out of memory\n", progname);
127 fprintf (stderr, "%s: xpm: unknown error code %d\n", progname, result);
135 bitmap = XmuLocateBitmapFile (DefaultScreenOfDisplay (dpy), bitmap_name,
136 0, 0, widthP, heightP, &xh, &yh);
139 fprintf (stderr, "%s: couldn't find bitmap %s\n", progname,
143 b2 = XmuCreatePixmapFromBitmap (dpy, window, bitmap, *widthP, *heightP,
145 XFreePixmap (dpy, bitmap);
153 XWindowAttributes xgwa;
157 unsigned int real_size;
161 XGetWindowAttributes (dpy, window, &xgwa);
162 cmap = xgwa.colormap;
165 fg = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
166 bg = get_pixel_resource ("background", "Background", dpy, cmap);
167 delay = get_integer_resource ("delay", "Integer");
168 delay2 = get_integer_resource ("delay2", "Integer");
169 if (delay < 0) delay = 0;
170 if (delay2 < 0) delay2 = 0;
171 bitmap_name = get_string_resource ("bitmap", "Bitmap");
172 if (! bitmap_name || !*bitmap_name)
173 bitmap_name = "(default)";
175 if (!strcmp (bitmap_name, "(default)"))
178 height = logo_height;
179 bitmap = XCreatePixmapFromBitmapData (dpy, window, (char *) logo_bits,
180 width, height, fg, bg, depth);
184 read_bitmap (bitmap_name, &width, &height);
187 real_size = (width > height) ? width : height;
190 /* semi-sleazy way of doing (setq size (expt 2 (ceiling (log size 2)))). */
191 for (i = 31; i > 0; i--)
192 if (size & (1<<i)) break;
193 if (size & (~(1<<i)))
194 size = (size>>i)<<(i+1);
195 self = XCreatePixmap (dpy, window, size, size, depth);
196 temp = XCreatePixmap (dpy, window, size, size, depth);
197 mask = XCreatePixmap (dpy, window, size, size, depth);
198 gcv.foreground = (depth == 1 ? 1 : (~0));
199 gcv.function=GXset; SET = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
200 gcv.function=GXclear;CLR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
201 gcv.function=GXcopy; CPY = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
202 gcv.function=GXor; IOR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
203 gcv.function=GXand; AND = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
204 gcv.function=GXxor; XOR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
206 gcv.foreground = gcv.background = bg;
207 gc = XCreateGC (dpy, window, GCForeground|GCBackground, &gcv);
208 /* Clear self to the background color (not to 0, which CLR does.) */
209 XFillRectangle (dpy, self, gc, 0, 0, size, size);
210 XSetForeground (dpy, gc, fg);
212 XCopyArea (dpy, bitmap, self, CPY, 0, 0, width, height,
213 (size - width)>>1, (size - height)>>1);
220 XWindowAttributes xgwa;
221 static int last_w = 0, last_h = 0;
222 XGetWindowAttributes (dpy, window, &xgwa);
223 if (xgwa.width != last_w || xgwa.height != last_h)
225 XClearWindow (dpy, window);
227 last_h = xgwa.height;
231 XCopyArea (dpy, pixmap, window, gc, 0, 0, size, size,
232 (xgwa.width-size)>>1, (xgwa.height-size)>>1);
235 XCopyPlane (dpy, pixmap, window, gc, 0, 0, size, size,
236 (xgwa.width-size)>>1, (xgwa.height-size)>>1, 1);
238 XDrawRectangle (dpy, window, gc,
239 ((xgwa.width-size)>>1)-1, ((xgwa.height-size)>>1)-1,
246 char *progclass = "BlitSpin";
248 char *defaults [] = {
249 "BlitSpin.background: black", /* to placate SGI */
250 "BlitSpin.foreground: white",
253 "*bitmap: (default)",
257 XrmOptionDescRec options [] = {
258 { "-delay", ".delay", XrmoptionSepArg, 0 },
259 { "-delay2", ".delay2", XrmoptionSepArg, 0 },
260 { "-bitmap", ".bitmap", XrmoptionSepArg, 0 }
262 int options_size = (sizeof (options) / sizeof (options[0]));
275 if (delay2) usleep (delay2);