From http://www.jwz.org/xscreensaver/xscreensaver-5.35.tar.gz
[xscreensaver] / hacks / greynetic.c
1 /* xscreensaver, Copyright (c) 1992-2008 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 #include "screenhack.h"
13
14 #ifndef HAVE_JWXYZ
15 # define DO_STIPPLE
16 #endif
17
18 #define NBITS 12
19
20 /* On some systems (notably MacOS X) these files are messed up.
21  * They're tiny, so we might as well just inline them here.
22  *
23  * # include <X11/bitmaps/stipple>
24  * # include <X11/bitmaps/cross_weave>
25  * # include <X11/bitmaps/dimple1>
26  * # include <X11/bitmaps/dimple3>
27  * # include <X11/bitmaps/flipped_gray>
28  * # include <X11/bitmaps/gray1>
29  * # include <X11/bitmaps/gray3>
30  * # include <X11/bitmaps/hlines2>
31  * # include <X11/bitmaps/light_gray>
32  * # include <X11/bitmaps/root_weave>
33  * # include <X11/bitmaps/vlines2>
34  * # include <X11/bitmaps/vlines3>
35 */
36
37 #ifdef DO_STIPPLE
38 #define stipple_width  16
39 #define stipple_height 4
40 static unsigned char stipple_bits[] = {
41   0x55, 0x55, 0xee, 0xee, 0x55, 0x55, 0xba, 0xbb};
42
43 #define cross_weave_width  16
44 #define cross_weave_height 16
45 static unsigned char cross_weave_bits[] = {
46    0x55, 0x55, 0x88, 0x88, 0x55, 0x55, 0x22, 0x22, 0x55, 0x55, 0x88, 0x88,
47    0x55, 0x55, 0x22, 0x22, 0x55, 0x55, 0x88, 0x88, 0x55, 0x55, 0x22, 0x22,
48    0x55, 0x55, 0x88, 0x88, 0x55, 0x55, 0x22, 0x22};
49
50 #define dimple1_width 16
51 #define dimple1_height 16
52 static unsigned char dimple1_bits[] = {
53    0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00,
54    0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00,
55    0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00};
56
57 #define dimple3_width 16
58 #define dimple3_height 16
59 static unsigned char dimple3_bits[] = {
60    0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00,
61    0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62    0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
63
64 #define flipped_gray_width  4
65 #define flipped_gray_height 2
66 static char flipped_gray_bits[] = { 0x07, 0x0d};
67 #define gray1_width  2
68 #define gray1_height 2
69 static char gray1_bits[] = { 0x01, 0x02};
70 #define gray3_width  4
71 #define gray3_height 4
72 static char gray3_bits[] = { 0x01, 0x00, 0x04, 0x00};
73 #define hlines2_width  1
74 #define hlines2_height 2
75 static char hlines2_bits[] = { 0x01, 0x00};
76 #define light_gray_width  4
77 #define light_gray_height 2
78 static char light_gray_bits[] = { 0x08, 0x02};
79 #define root_weave_width  4
80 #define root_weave_height 4
81 static char root_weave_bits[] = { 0x07, 0x0d, 0x0b, 0x0e};
82 #define vlines2_width  2
83 #define vlines2_height 1
84 static char vlines2_bits[] = { 0x01};
85 #define vlines3_width  3
86 #define vlines3_height 1
87 static char vlines3_bits[] = { 0x02};
88
89 #endif /* DO_STIPPLE */
90
91 struct state {
92   Display *dpy;
93   Window window;
94
95   Pixmap pixmaps [NBITS];
96
97   GC gc;
98   int delay;
99   unsigned long fg, bg, pixels [512];
100   int npixels;
101   int xlim, ylim;
102   Bool grey_p;
103   Colormap cmap;
104 };
105
106
107 static void *
108 greynetic_init (Display *dpy, Window window)
109 {
110   struct state *st = (struct state *) calloc (1, sizeof(*st));
111 # ifdef DO_STIPPLE
112   int i;
113 # endif /* DO_STIPPLE */
114   XGCValues gcv;
115   XWindowAttributes xgwa;
116   st->dpy = dpy;
117   st->window = window;
118
119   XGetWindowAttributes (st->dpy, st->window, &xgwa);
120   st->xlim = xgwa.width;
121   st->ylim = xgwa.height;
122   st->cmap = xgwa.colormap;
123   st->npixels = 0;
124   st->grey_p = get_boolean_resource(st->dpy, "grey", "Boolean");
125   gcv.foreground= st->fg= get_pixel_resource(st->dpy, st->cmap, "foreground","Foreground");
126   gcv.background= st->bg= get_pixel_resource(st->dpy, st->cmap, "background","Background");
127
128   st->delay = get_integer_resource (st->dpy, "delay", "Integer");
129   if (st->delay < 0) st->delay = 0;
130
131 # ifndef DO_STIPPLE
132   st->gc = XCreateGC (st->dpy, st->window, GCForeground, &gcv);
133 #  ifdef HAVE_JWXYZ /* allow non-opaque alpha components in pixel values */
134   jwxyz_XSetAlphaAllowed (st->dpy, st->gc, True);
135 #  endif /* HAVE_JWXYZ */
136 # else /* DO_STIPPLE */
137   gcv.fill_style= FillOpaqueStippled;
138   st->gc = XCreateGC (st->dpy, st->window, GCForeground|GCBackground|GCFillStyle, &gcv);
139   
140   i = 0;
141 # define BITS(n,w,h) \
142   st->pixmaps [i++] = \
143     XCreatePixmapFromBitmapData (st->dpy, st->window, (char *) n, w, h, 1, 0, 1)
144
145   BITS (stipple_bits, stipple_width, stipple_height);
146   BITS (cross_weave_bits, cross_weave_width, cross_weave_height);
147   BITS (dimple1_bits, dimple1_width, dimple1_height);
148   BITS (dimple3_bits, dimple3_width, dimple3_height);
149   BITS (flipped_gray_bits, flipped_gray_width, flipped_gray_height);
150   BITS (gray1_bits, gray1_width, gray1_height);
151   BITS (gray3_bits, gray3_width, gray3_height);
152   BITS (hlines2_bits, hlines2_width, hlines2_height);
153   BITS (light_gray_bits, light_gray_width, light_gray_height);
154   BITS (root_weave_bits, root_weave_width, root_weave_height);
155   BITS (vlines2_bits, vlines2_width, vlines2_height);
156   BITS (vlines3_bits, vlines3_width, vlines3_height);
157 # endif /* DO_STIPPLE */
158   return st;
159 }
160
161 static unsigned long
162 greynetic_draw (Display *dpy, Window window, void *closure)
163 {
164   struct state *st = (struct state *) closure;
165   int x, y, w=0, h=0, i;
166   XGCValues gcv;
167
168   for (i = 0; i < 10; i++) /* minimize area, but don't try too hard */
169     {
170       w = 50 + random () % (st->xlim - 50);
171       h = 50 + random () % (st->ylim - 50);
172       if (w + h < st->xlim && w + h < st->ylim)
173         break;
174     }
175   x = random () % (st->xlim - w);
176   y = random () % (st->ylim - h);
177 # ifdef DO_STIPPLE
178   gcv.stipple = st->pixmaps [random () % NBITS];
179 # endif /* !DO_STIPPLE */
180   if (mono_p)
181     {
182     MONO:
183       if (random () & 1)
184         gcv.foreground = st->fg, gcv.background = st->bg;
185       else
186         gcv.foreground = st->bg, gcv.background = st->fg;
187     }
188   else
189     {
190       XColor fgc, bgc;
191       if (st->npixels == sizeof (st->pixels) / sizeof (unsigned long))
192         goto REUSE;
193       fgc.flags = bgc.flags = DoRed|DoGreen|DoBlue;
194       fgc.red = random ();
195       fgc.green = random ();
196       fgc.blue = random ();
197 # ifdef DO_STIPPLE
198       bgc.red = random ();
199       bgc.green = random ();
200       bgc.blue = random ();
201 # endif /* DO_STIPPLE */
202
203       if (st->grey_p)
204         {
205           fgc.green = fgc.blue = fgc.red;
206           bgc.green = bgc.blue = bgc.red;
207         }
208
209       if (! XAllocColor (st->dpy, st->cmap, &fgc))
210         goto REUSE;
211       st->pixels [st->npixels++] = fgc.pixel;
212       gcv.foreground = fgc.pixel;
213 # ifdef DO_STIPPLE
214       if (! XAllocColor (st->dpy, st->cmap, &bgc))
215         goto REUSE;
216       st->pixels [st->npixels++] = bgc.pixel;
217       gcv.background = bgc.pixel;
218 # endif /* DO_STIPPLE */
219       goto DONE;
220     REUSE:
221       if (st->npixels <= 0)
222         {
223           mono_p = 1;
224           goto MONO;
225         }
226       gcv.foreground = st->pixels [random () % st->npixels];
227 # ifdef DO_STIPPLE
228       gcv.background = st->pixels [random () % st->npixels];
229 # endif /* DO_STIPPLE */
230     DONE:
231       ;
232
233 # ifdef HAVE_JWXYZ
234       {
235         /* give a non-opaque alpha to the color */
236         unsigned long pixel = gcv.foreground;
237         unsigned long amask = BlackPixel (dpy,0);
238         unsigned long a = (random() & amask);
239         pixel = (pixel & (~amask)) | a;
240         gcv.foreground = pixel;
241       }
242 # endif /* !HAVE_JWXYZ */
243     }
244 # ifndef DO_STIPPLE
245   XChangeGC (st->dpy, st->gc, GCForeground, &gcv);
246 # else  /* DO_STIPPLE */
247   XChangeGC (st->dpy, st->gc, GCStipple|GCForeground|GCBackground, &gcv);
248 # endif /* DO_STIPPLE */
249   XFillRectangle (st->dpy, st->window, st->gc, x, y, w, h);
250   return st->delay;
251 }
252
253 \f
254 static const char *greynetic_defaults [] = {
255   ".background: black",
256   ".foreground: white",
257   "*fpsSolid:   true",
258   "*delay:      10000",
259   "*grey:       false",
260 #ifdef HAVE_MOBILE
261   "*ignoreRotation: True",
262 #endif
263   0
264 };
265
266 static XrmOptionDescRec greynetic_options [] = {
267   { "-delay",           ".delay",       XrmoptionSepArg, 0 },
268   { "-grey",            ".grey",        XrmoptionNoArg, "True" },
269   { 0, 0, 0, 0 }
270 };
271
272 static void
273 greynetic_reshape (Display *dpy, Window window, void *closure, 
274                  unsigned int w, unsigned int h)
275 {
276   struct state *st = (struct state *) closure;
277   st->xlim = w;
278   st->ylim = h;
279 }
280
281 static Bool
282 greynetic_event (Display *dpy, Window window, void *closure, XEvent *event)
283 {
284   return False;
285 }
286
287 static void
288 greynetic_free (Display *dpy, Window window, void *closure)
289 {
290   struct state *st = (struct state *) closure;
291   XFreeGC (st->dpy, st->gc);
292   free (st);
293 }
294
295 XSCREENSAVER_MODULE ("Greynetic", greynetic)
296