Commit | Line | Data |
---|---|---|
6881658b AT |
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 |