ftp://ftp.zenez.com/pub/SCO/Skunk96/UnixWare/FreeBird/x11/utils/xscreensaver-1.18...
[xscreensaver] / hacks / blitspin.c
1 /* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@lucid.com>
2  *
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 
9  * implied warranty.
10  */
11
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.
16
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
21    interesting looking.
22
23    It's too bad almost nothing uses blitter hardware these days,
24    or this might actually win.
25  */
26
27 #include "screenhack.h"
28 #include <stdio.h>
29
30 #ifdef HAVE_XPM
31 # include <X11/xpm.h>
32 # ifndef PIXEL_ALREADY_TYPEDEFED
33 #  define PIXEL_ALREADY_TYPEDEFED /* Sigh, Xmu/Drawing.h needs this... */
34 # endif
35 #endif
36
37 #include <X11/Xmu/Drawing.h>
38
39
40 static Display *dpy;
41 static Window window;
42 static unsigned int size;
43 static Pixmap self, temp, mask;
44 static GC SET, CLR, CPY, IOR, AND, XOR;
45 static GC gc;
46 static int delay, delay2;
47 static Pixmap bitmap;
48 static int depth;
49
50 static void rotate(), init (), display ();
51
52 #define copy_all_to(from, xoff, yoff, to, gc)           \
53   XCopyArea (dpy, (from), (to), (gc), 0, 0,             \
54              size-(xoff), size-(yoff), (xoff), (yoff))
55
56 #define copy_all_from(to, xoff, yoff, from, gc)         \
57   XCopyArea (dpy, (from), (to), (gc), (xoff), (yoff),   \
58              size-(xoff), size-(yoff), 0, 0)
59
60 static void
61 rotate ()
62 {
63   int qwad; /* fuckin' C, man... who needs namespaces? */
64   XFillRectangle (dpy, mask, CLR, 0, 0, size, size);
65   XFillRectangle (dpy, mask, SET, 0, 0, size>>1, size>>1);
66   for (qwad = size>>1; qwad > 0; qwad>>=1)
67     {
68       if (delay) usleep (delay);
69       copy_all_to   (mask,       0,       0, temp, CPY);  /* 1 */
70       copy_all_to   (mask,       0,    qwad, temp, IOR);  /* 2 */
71       copy_all_to   (self,       0,       0, temp, AND);  /* 3 */
72       copy_all_to   (temp,       0,       0, self, XOR);  /* 4 */
73       copy_all_from (temp,    qwad,       0, self, XOR);  /* 5 */
74       copy_all_from (self,    qwad,       0, self, IOR);  /* 6 */
75       copy_all_to   (temp,    qwad,       0, self, XOR);  /* 7 */
76       copy_all_to   (self,       0,       0, temp, CPY);  /* 8 */
77       copy_all_from (temp,    qwad,    qwad, self, XOR);  /* 9 */
78       copy_all_to   (mask,       0,       0, temp, AND);  /* A */
79       copy_all_to   (temp,       0,       0, self, XOR);  /* B */
80       copy_all_to   (temp,    qwad,    qwad, self, XOR);  /* C */
81       copy_all_from (mask, qwad>>1, qwad>>1, mask, AND);  /* D */
82       copy_all_to   (mask,    qwad,       0, mask, IOR);  /* E */
83       copy_all_to   (mask,       0,    qwad, mask, IOR);  /* F */
84       display (self);
85     }
86 }
87
88 static void
89 init ()
90 {
91   XWindowAttributes xgwa;
92   Colormap cmap;
93   XGCValues gcv;
94   int width, height, xh, yh;
95   unsigned int real_size;
96   char *bitmap_name;
97   int i;
98 #ifdef HAVE_XPM
99   XpmAttributes xpmattrs;
100   int result;
101 #endif
102
103   XGetWindowAttributes (dpy, window, &xgwa);
104   cmap = xgwa.colormap;
105   depth = xgwa.depth;
106
107   delay = get_integer_resource ("delay", "Integer");
108   delay2 = get_integer_resource ("delay2", "Integer");
109   if (delay < 0) delay = 0;
110   if (delay2 < 0) delay2 = 0;
111   bitmap_name = get_string_resource ("bitmap", "Bitmap");
112   if (! bitmap_name)
113     {
114       fprintf (stderr, "%s: no bitmap specified\n", progname);
115       exit (1);
116     }
117 #ifdef HAVE_XPM
118   xpmattrs.valuemask = 0;
119   bitmap = 0;
120   result = XpmReadFileToPixmap (dpy,window, bitmap_name, &bitmap, 0, &xpmattrs);
121   switch (result)
122     {
123     case XpmColorError:
124       fprintf (stderr, "%s: warning: xpm color substitution performed\n",
125                progname);
126       /* fall through */
127     case XpmSuccess:
128       width = xpmattrs.width;
129       height = xpmattrs.height;
130       break;
131     case XpmFileInvalid:
132     case XpmOpenFailed:
133       bitmap = 0;
134       break;
135     case XpmColorFailed:
136       fprintf (stderr, "%s: xpm: color allocation failed\n", progname);
137       exit (-1);
138     case XpmNoMemory:
139       fprintf (stderr, "%s: xpm: out of memory\n", progname);
140       exit (-1);
141     default:
142       fprintf (stderr, "%s: xpm: unknown error code %d\n", progname, result);
143       exit (-1);
144     }
145   if (! bitmap)
146 #endif
147     bitmap = XmuLocateBitmapFile (DefaultScreenOfDisplay (dpy), bitmap_name,
148                                 0, 0, &width, &height, &xh, &yh);
149   if (! bitmap)
150     {
151       fprintf (stderr, "%s: couldn't find bitmap %s\n", progname, bitmap_name);
152       exit (1);
153     }
154
155   real_size = (width > height) ? width : height;
156
157   size = real_size;
158   /* semi-sleazy way of doing (setq size (expt 2 (ceiling (log size 2)))). */
159   for (i = 31; i > 0; i--)
160     if (size & (1<<i)) break;
161   if (size & (~(1<<i)))
162     size = (size>>i)<<(i+1);
163   self = XCreatePixmap (dpy, window, size, size, depth);
164   temp = XCreatePixmap (dpy, window, size, size, depth);
165   mask = XCreatePixmap (dpy, window, size, size, depth);
166   gcv.foreground = (depth == 1 ? 1 : (~0));
167   gcv.function=GXset;  SET = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
168   gcv.function=GXclear;CLR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
169   gcv.function=GXcopy; CPY = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
170   gcv.function=GXor;   IOR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
171   gcv.function=GXand;  AND = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
172   gcv.function=GXxor;  XOR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
173
174   XFillRectangle (dpy, self, CLR, 0, 0, size, size);
175   XCopyArea (dpy, bitmap, self, CPY, 0, 0, width, height,
176              (size - width)>>1, (size - height)>>1);
177
178   gcv.foreground = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
179   gcv.background = get_pixel_resource ("background", "Background", dpy, cmap);
180   gc = XCreateGC (dpy, window, GCForeground|GCBackground, &gcv);
181 }
182
183 static void
184 display (pixmap)
185      Pixmap pixmap;
186 {
187   XWindowAttributes xgwa;
188   static int last_w = 0, last_h = 0;
189   XGetWindowAttributes (dpy, window, &xgwa);
190   if (xgwa.width != last_w || xgwa.height != last_h)
191     {
192       XClearWindow (dpy, window);
193       last_w = xgwa.width;
194       last_h = xgwa.height;
195     }
196 #ifdef HAVE_XPM
197   if (depth != 1)
198     XCopyArea (dpy, pixmap, window, gc, 0, 0, size, size,
199                (xgwa.width-size)>>1, (xgwa.height-size)>>1);
200   else
201 #endif
202     XCopyPlane (dpy, pixmap, window, gc, 0, 0, size, size,
203                 (xgwa.width-size)>>1, (xgwa.height-size)>>1, 1);
204 /*
205   XDrawRectangle (dpy, window, gc,
206                   ((xgwa.width-size)>>1)-1, ((xgwa.height-size)>>1)-1,
207                   size+2, size+2);
208 */
209   XSync (dpy, True);
210 }
211
212 \f
213 char *progclass = "BlitSpin";
214
215 char *defaults [] = {
216   "*background: black",
217   "*foreground: white",
218   "*delay:      500000",
219   "*delay2:     500000",
220   "*bitmap:     xlogo64",       /* hey, pick something better! */
221   0
222 };
223
224 XrmOptionDescRec options [] = {
225   { "-delay",           ".delay",       XrmoptionSepArg, 0 },
226   { "-delay2",          ".delay2",      XrmoptionSepArg, 0 },
227   { "-bitmap",          ".bitmap",      XrmoptionSepArg, 0 }
228 };
229 int options_size = (sizeof (options) / sizeof (options[0]));
230
231 void
232 screenhack (d, w)
233      Display *d;
234      Window w;
235 {
236   dpy = d;
237   window = w;
238   init ();
239   while (1)
240     {
241       rotate ();
242       if (delay2) usleep (delay2);
243     }
244 }