source: trunk/third/xscreensaver/hacks/blitspin.c @ 20148

Revision 20148, 8.2 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20147, which included commits to RCS files with non-trunk default branches.
Line 
1/* xscreensaver, Copyright (c) 1992-1997, 2003 Jamie Zawinski <jwz@jwz.org>
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 "xpm-pixmap.h"
29#include <stdio.h>
30
31#include "images/som.xbm"
32
33static Display *dpy;
34static Window window;
35static unsigned int size;
36static Pixmap self, temp, mask;
37static GC SET, CLR, CPY, IOR, AND, XOR;
38static GC gc;
39static int delay, delay2;
40static Pixmap bitmap;
41static int depth;
42static unsigned int fg, bg;
43
44static void display (Pixmap);
45
46#define copy_all_to(from, xoff, yoff, to, gc)           \
47  XCopyArea (dpy, (from), (to), (gc), 0, 0,             \
48             size-(xoff), size-(yoff), (xoff), (yoff))
49
50#define copy_all_from(to, xoff, yoff, from, gc)         \
51  XCopyArea (dpy, (from), (to), (gc), (xoff), (yoff),   \
52             size-(xoff), size-(yoff), 0, 0)
53
54static void
55rotate (void)
56{
57  int qwad; /* fuckin' C, man... who needs namespaces? */
58  XFillRectangle (dpy, mask, CLR, 0, 0, size, size);
59  XFillRectangle (dpy, mask, SET, 0, 0, size>>1, size>>1);
60  for (qwad = size>>1; qwad > 0; qwad>>=1)
61    {
62      if (delay) usleep (delay);
63      copy_all_to   (mask,       0,       0, temp, CPY);  /* 1 */
64      copy_all_to   (mask,       0,    qwad, temp, IOR);  /* 2 */
65      copy_all_to   (self,       0,       0, temp, AND);  /* 3 */
66      copy_all_to   (temp,       0,       0, self, XOR);  /* 4 */
67      copy_all_from (temp,    qwad,       0, self, XOR);  /* 5 */
68      copy_all_from (self,    qwad,       0, self, IOR);  /* 6 */
69      copy_all_to   (temp,    qwad,       0, self, XOR);  /* 7 */
70      copy_all_to   (self,       0,       0, temp, CPY);  /* 8 */
71      copy_all_from (temp,    qwad,    qwad, self, XOR);  /* 9 */
72      copy_all_to   (mask,       0,       0, temp, AND);  /* A */
73      copy_all_to   (temp,       0,       0, self, XOR);  /* B */
74      copy_all_to   (temp,    qwad,    qwad, self, XOR);  /* C */
75      copy_all_from (mask, qwad>>1, qwad>>1, mask, AND);  /* D */
76      copy_all_to   (mask,    qwad,       0, mask, IOR);  /* E */
77      copy_all_to   (mask,       0,    qwad, mask, IOR);  /* F */
78      display (self);
79    }
80}
81
82static Pixmap
83read_screen (Display *dpy, Window window, int *widthP, int *heightP)
84{
85  Pixmap p;
86  XWindowAttributes xgwa;
87  XGCValues gcv;
88  GC gc;
89  XGetWindowAttributes (dpy, window, &xgwa);
90  *widthP = xgwa.width;
91  *heightP = xgwa.height;
92
93  p = XCreatePixmap(dpy, window, *widthP, *heightP, xgwa.depth);
94  gcv.function = GXcopy;
95  gc = XCreateGC (dpy, window, GCFunction, &gcv);
96
97  load_random_image (xgwa.screen, window, p, NULL);
98
99  /* Reset the window's background color... */
100  XSetWindowBackground (dpy, window,
101                        get_pixel_resource ("background", "Background",
102                                            dpy, xgwa.colormap));
103  XCopyArea (dpy, p, window, gc, 0, 0, *widthP, *heightP, 0, 0);
104  XFreeGC (dpy, gc);
105
106  return p;
107}
108
109
110static int
111to_pow2(int n, Bool up)
112{
113  /* sizeof(Dimension) == 2. */
114  int powers_of_2[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,
115                        2048, 4096, 8192, 16384, 32768, 65536 };
116  int i = 0;
117  if (n > 65536) size = 65536;
118  while (n >= powers_of_2[i]) i++;
119  if (n == powers_of_2[i-1])
120    return n;
121  else
122    return powers_of_2[up ? i : i-1];
123}
124
125static void
126init (void)
127{
128  XWindowAttributes xgwa;
129  Colormap cmap;
130  XGCValues gcv;
131  int width, height;
132  char *bitmap_name;
133  Bool scale_up;
134
135  XGetWindowAttributes (dpy, window, &xgwa);
136  cmap = xgwa.colormap;
137  depth = xgwa.depth;
138
139  fg = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
140  bg = get_pixel_resource ("background", "Background", dpy, cmap);
141  delay = get_integer_resource ("delay", "Integer");
142  delay2 = get_integer_resource ("delay2", "Integer");
143  if (delay < 0) delay = 0;
144  if (delay2 < 0) delay2 = 0;
145  bitmap_name = get_string_resource ("bitmap", "Bitmap");
146  if (! bitmap_name || !*bitmap_name)
147    bitmap_name = "(default)";
148
149  if (!strcmp (bitmap_name, "(default)"))
150    {
151      width = som_width;
152      height = som_height;
153      bitmap = XCreatePixmapFromBitmapData (dpy, window, (char *) som_bits,
154                                            width, height, fg, bg, depth);
155      scale_up = True; /* definitely. */
156    }
157  else if (!strcmp (bitmap_name, "(screen)"))
158    {
159      bitmap = read_screen (dpy, window, &width, &height);
160      scale_up = True; /* maybe? */
161    }
162  else
163    {
164      bitmap = xpm_file_to_pixmap (dpy, window, bitmap_name,
165                                   &width, &height, 0);
166      scale_up = True; /* probably? */
167    }
168
169  size = (width < height) ? height : width;     /* make it square */
170  size = to_pow2(size, scale_up);               /* round up to power of 2 */
171  {                                             /* don't exceed screen size */
172    int s = XScreenNumberOfScreen(xgwa.screen);
173    int w = to_pow2(XDisplayWidth(dpy, s), False);
174    int h = to_pow2(XDisplayHeight(dpy, s), False);
175    if (size > w) size = w;
176    if (size > h) size = h;
177  }
178
179  self = XCreatePixmap (dpy, window, size, size, depth);
180  temp = XCreatePixmap (dpy, window, size, size, depth);
181  mask = XCreatePixmap (dpy, window, size, size, depth);
182  gcv.foreground = (depth == 1 ? 1 : (~0));
183  gcv.function=GXset;  SET = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
184  gcv.function=GXclear;CLR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
185  gcv.function=GXcopy; CPY = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
186  gcv.function=GXor;   IOR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
187  gcv.function=GXand;  AND = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
188  gcv.function=GXxor;  XOR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
189
190  gcv.foreground = gcv.background = bg;
191  gc = XCreateGC (dpy, window, GCForeground|GCBackground, &gcv);
192  /* Clear self to the background color (not to 0, which CLR does.) */
193  XFillRectangle (dpy, self, gc, 0, 0, size, size);
194  XSetForeground (dpy, gc, fg);
195
196  XCopyArea (dpy, bitmap, self, CPY, 0, 0, width, height,
197             (size - width)>>1, (size - height)>>1);
198  XFreePixmap(dpy, bitmap);
199
200  display (self);
201  XSync(dpy, False);
202  screenhack_handle_events (dpy);
203}
204
205static void
206display (Pixmap pixmap)
207{
208  XWindowAttributes xgwa;
209  static int last_w = 0, last_h = 0;
210  XGetWindowAttributes (dpy, window, &xgwa);
211  if (xgwa.width != last_w || xgwa.height != last_h)
212    {
213      XClearWindow (dpy, window);
214      last_w = xgwa.width;
215      last_h = xgwa.height;
216    }
217  if (depth != 1)
218    XCopyArea (dpy, pixmap, window, gc, 0, 0, size, size,
219               (xgwa.width-size)>>1, (xgwa.height-size)>>1);
220  else
221    XCopyPlane (dpy, pixmap, window, gc, 0, 0, size, size,
222                (xgwa.width-size)>>1, (xgwa.height-size)>>1, 1);
223/*
224  XDrawRectangle (dpy, window, gc,
225                  ((xgwa.width-size)>>1)-1, ((xgwa.height-size)>>1)-1,
226                  size+2, size+2);
227*/
228  XSync (dpy, False);
229  screenhack_handle_events (dpy);
230}
231
232
233char *progclass = "BlitSpin";
234
235char *defaults [] = {
236  ".background: black",
237  ".foreground: white",
238  "*delay:      500000",
239  "*delay2:     500000",
240  "*bitmap:     (default)",
241  "*geometry:   512x512",
242  0
243};
244
245XrmOptionDescRec options [] = {
246  { "-delay",           ".delay",       XrmoptionSepArg, 0 },
247  { "-delay2",          ".delay2",      XrmoptionSepArg, 0 },
248  { "-bitmap",          ".bitmap",      XrmoptionSepArg, 0 },
249  { "-grab-screen",     ".bitmap",      XrmoptionNoArg, "(screen)" },
250  { 0, 0, 0, 0 }
251};
252
253void
254screenhack (Display *d, Window w)
255{
256  dpy = d;
257  window = w;
258  init ();
259  if (delay2) usleep (delay2 * 2);
260  while (1)
261    {
262      rotate ();
263      screenhack_handle_events (d);
264      if (delay2) usleep (delay2);
265    }
266}
Note: See TracBrowser for help on using the repository browser.