ftp://ftp.ntnu.no/old/pub/X11/R5contrib/xscreensaver-1.17.tar.gz
[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    but I don't think that would be as interesting looking.
21
22    It's too bad almost nothing uses blitter hardware these days,
23    or this might actually win.
24  */
25
26 #include "screenhack.h"
27 #include <X11/Xmu/Drawing.h>
28 #include <stdio.h>
29
30 static Display *dpy;
31 static Window window;
32 static unsigned int size;
33 static Pixmap self, temp, mask;
34 static GC SET, CLR, CPY, IOR, AND, XOR;
35 static GC gc;
36 static int delay, delay2;
37 static Pixmap bitmap;
38
39 static void rotate(), init (), display ();
40
41 #define copy_all_to(from, xoff, yoff, to, gc)           \
42   XCopyArea (dpy, (from), (to), (gc), 0, 0,             \
43              size-(xoff), size-(yoff), (xoff), (yoff))
44
45 #define copy_all_from(to, xoff, yoff, from, gc)         \
46   XCopyArea (dpy, (from), (to), (gc), (xoff), (yoff),   \
47              size-(xoff), size-(yoff), 0, 0)
48
49 static void
50 rotate ()
51 {
52   int qwad; /* fuckin' C, man... who needs namespaces? */
53   XFillRectangle (dpy, mask, CLR, 0, 0, size, size);
54   XFillRectangle (dpy, mask, SET, 0, 0, size>>1, size>>1);
55   for (qwad = size>>1; qwad > 0; qwad>>=1)
56     {
57       if (delay) usleep (delay);
58       copy_all_to   (mask,       0,       0, temp, CPY);  /* 1 */
59       copy_all_to   (mask,       0,    qwad, temp, IOR);  /* 2 */
60       copy_all_to   (self,       0,       0, temp, AND);  /* 3 */
61       copy_all_to   (temp,       0,       0, self, XOR);  /* 4 */
62       copy_all_from (temp,    qwad,       0, self, XOR);  /* 5 */
63       copy_all_from (self,    qwad,       0, self, IOR);  /* 6 */
64       copy_all_to   (temp,    qwad,       0, self, XOR);  /* 7 */
65       copy_all_to   (self,       0,       0, temp, CPY);  /* 8 */
66       copy_all_from (temp,    qwad,    qwad, self, XOR);  /* 9 */
67       copy_all_to   (mask,       0,       0, temp, AND);  /* A */
68       copy_all_to   (temp,       0,       0, self, XOR);  /* B */
69       copy_all_to   (temp,    qwad,    qwad, self, XOR);  /* C */
70       copy_all_from (mask, qwad>>1, qwad>>1, mask, AND);  /* D */
71       copy_all_to   (mask,    qwad,       0, mask, IOR);  /* E */
72       copy_all_to   (mask,       0,    qwad, mask, IOR);  /* F */
73       display (self);
74     }
75 }
76
77 static void
78 init ()
79 {
80   XWindowAttributes xgwa;
81   Colormap cmap;
82   XGCValues gcv;
83   int width, height, xh, yh;
84   unsigned int real_size;
85   char *bitmap_name;
86   int i;
87   XGetWindowAttributes (dpy, window, &xgwa);
88   cmap = xgwa.colormap;
89
90   delay = get_integer_resource ("delay", "Integer");
91   delay2 = get_integer_resource ("delay2", "Integer");
92   if (delay < 0) delay = 0;
93   if (delay2 < 0) delay2 = 0;
94   bitmap_name = get_string_resource ("bitmap", "Bitmap");
95   if (! bitmap_name)
96     {
97       fprintf (stderr, "%s: no bitmap specified\n", progname);
98       exit (1);
99     }
100   bitmap = XmuLocateBitmapFile (DefaultScreenOfDisplay (dpy), bitmap_name,
101                                 0, 0, &width, &height, &xh, &yh);
102   if (! bitmap)
103     {
104       fprintf (stderr, "%s: couldn't find bitmap %s\n", progname, bitmap_name);
105       exit (1);
106     }
107
108   real_size = (width > height) ? width : height;
109
110   size = real_size;
111   /* semi-sleazy way of doing (setq size (expt 2 (ceiling (log size 2)))). */
112   for (i = 31; i > 0; i--)
113     if (size & (1<<i)) break;
114   if (size & (~(1<<i)))
115     size = (size>>i)<<(i+1);
116   self = XCreatePixmap (dpy, window, size, size, 1);
117   temp = XCreatePixmap (dpy, window, size, size, 1);
118   mask = XCreatePixmap (dpy, window, size, size, 1);
119   gcv.foreground = 1;
120   gcv.function=GXset;  SET = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
121   gcv.function=GXclear;CLR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
122   gcv.function=GXcopy; CPY = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
123   gcv.function=GXor;   IOR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
124   gcv.function=GXand;  AND = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
125   gcv.function=GXxor;  XOR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
126
127   XFillRectangle (dpy, self, CLR, 0, 0, size, size);
128   XCopyArea (dpy, bitmap, self, CPY, 0, 0, width, height,
129              (size - width)>>1, (size - height)>>1);
130
131   gcv.foreground = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
132   gcv.background = get_pixel_resource ("background", "Background", dpy, cmap);
133   gc = XCreateGC (dpy, window, GCForeground|GCBackground, &gcv);
134 }
135
136 static void
137 display (pixmap)
138      Pixmap pixmap;
139 {
140   XWindowAttributes xgwa;
141   static int last_w = 0, last_h = 0;
142   XGetWindowAttributes (dpy, window, &xgwa);
143   if (xgwa.width != last_w || xgwa.height != last_h)
144     {
145       XClearWindow (dpy, window);
146       last_w = xgwa.width;
147       last_h = xgwa.height;
148     }
149   XCopyPlane (dpy, pixmap, window, gc, 0, 0, size, size,
150               (xgwa.width-size)>>1, (xgwa.height-size)>>1, 1);
151 /*
152   XDrawRectangle (dpy, window, gc,
153                   ((xgwa.width-size)>>1)-1, ((xgwa.height-size)>>1)-1,
154                   size+2, size+2);
155 */
156   XSync (dpy, True);
157 }
158
159 \f
160 char *progclass = "BlitSpin";
161
162 char *defaults [] = {
163   "*background: black",
164   "*foreground: white",
165   "*delay:      500000",
166   "*delay2:     500000",
167   "*bitmap:     xlogo64",       /* hey, pick something better! */
168   0
169 };
170
171 XrmOptionDescRec options [] = {
172   { "-delay",           ".delay",       XrmoptionSepArg, 0 },
173   { "-delay2",          ".delay2",      XrmoptionSepArg, 0 },
174   { "-bitmap",          ".bitmap",      XrmoptionSepArg, 0 }
175 };
176 int options_size = (sizeof (options) / sizeof (options[0]));
177
178 void
179 screenhack (d, w)
180      Display *d;
181      Window w;
182 {
183   dpy = d;
184   window = w;
185   init ();
186   while (1)
187     {
188       rotate ();
189       if (delay2) usleep (delay2);
190     }
191 }