1 /* xscreensaver, Copyright (c) 1997, 1998, 2006 Jamie Zawinski <jwz@jwz.org>
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
12 #include "screenhack.h"
14 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
16 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
24 int fg_pixel, bg_pixel;
25 Pixmap p0, p1, p2, p3;
26 GC copy_gc, erase_gc, window_gc;
27 int width, height, size;
28 int x1, x2, y1, y2, x3, y3;
29 int dx1, dx2, dx3, dy1, dy2, dy3;
30 int othickness, thickness;
32 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
33 XdbeBackBuffer back_buf;
34 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
38 int delay, color_shift;
41 int iterations, iteration;
45 moire2_init_1 (struct state *st)
47 XWindowAttributes xgwa;
48 XGetWindowAttributes (st->dpy, st->window, &xgwa);
50 st->othickness = get_integer_resource(st->dpy, "thickness", "Thickness");
55 st->ncolors = get_integer_resource (st->dpy, "colors", "Colors");
56 if (st->ncolors < 2) st->ncolors = 2;
57 if (st->ncolors <= 2) mono_p = True;
62 st->colors = (XColor *) malloc(sizeof(*st->colors) * (st->ncolors+1));
67 make_smooth_colormap (st->dpy, xgwa.visual, xgwa.colormap, st->colors, &st->ncolors,
70 st->bg_pixel = get_pixel_resource(st->dpy,
71 xgwa.colormap, "background", "Background");
72 st->fg_pixel = get_pixel_resource(st->dpy,
73 xgwa.colormap, "foreground", "Foreground");
75 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
76 st->back_buf = xdbe_get_backbuffer (st->dpy, st->window, XdbeUndefined);
77 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
82 reset_moire2 (struct state *st)
85 XWindowAttributes xgwa;
88 XGetWindowAttributes (st->dpy, st->window, &xgwa);
90 st->do_three = (0 == (random() % 3));
92 st->width = xgwa.width;
93 st->height = xgwa.height;
94 st->size = st->width > st->height ? st->width : st->height;
96 if (st->p0) XFreePixmap(st->dpy, st->p0);
97 if (st->p1) XFreePixmap(st->dpy, st->p1);
98 if (st->p2) XFreePixmap(st->dpy, st->p2);
99 if (st->p3) XFreePixmap(st->dpy, st->p3);
101 st->p0 = XCreatePixmap(st->dpy, st->window, st->width, st->height, 1);
102 st->p1 = XCreatePixmap(st->dpy, st->window, st->width*2, st->height*2, 1);
103 st->p2 = XCreatePixmap(st->dpy, st->window, st->width*2, st->height*2, 1);
105 st->p3 = XCreatePixmap(st->dpy, st->window, st->width*2, st->height*2, 1);
109 st->thickness = (st->othickness > 0 ? st->othickness : (1 + (random() % 4)));
112 gcv.line_width = (st->thickness == 1 ? 0 : st->thickness);
113 gc = XCreateGC (st->dpy, st->p1, GCForeground|GCLineWidth, &gcv);
115 XFillRectangle(st->dpy, st->p1, gc, 0, 0, st->width*2, st->height*2);
116 XFillRectangle(st->dpy, st->p2, gc, 0, 0, st->width*2, st->height*2);
118 XFillRectangle(st->dpy, st->p3, gc, 0, 0, st->width*2, st->height*2);
120 XSetForeground(st->dpy, gc, 1);
122 xor = (st->do_three || (st->thickness == 1) || (random() & 1));
125 int i, ii, maxx, maxy;
127 #define FROB(P) do { \
128 maxx = (st->size*4); \
129 maxy = (st->size*4); \
130 if (0 == (random() % 5)) { \
131 float f = 1.0 + frand(0.05); \
132 if (random() & 1) maxx *= f; \
135 ii = (st->thickness + 1 + (xor ? 0 : 1) + (random() % (4 * st->thickness))); \
136 for (i = 0; i < (st->size*2); i += ii) \
137 XDrawArc(st->dpy, (P), gc, i-st->size, i-st->size, maxx-i-i, maxy-i-i, 0, 360*64); \
138 if (0 == (random() % 5)) \
140 XSetFunction(st->dpy, gc, GXxor); \
141 XFillRectangle(st->dpy, (P), gc, 0, 0, st->width*2, st->height*2); \
142 XSetFunction(st->dpy, gc, GXcopy); \
153 XFreeGC(st->dpy, gc);
155 if (st->copy_gc) XFreeGC(st->dpy, st->copy_gc);
156 gcv.function = (xor ? GXxor : GXor);
160 st->copy_gc = XCreateGC (st->dpy, st->p0, GCFunction|GCForeground|GCBackground, &gcv);
163 if (st->erase_gc) XFreeGC(st->dpy, st->erase_gc);
164 st->erase_gc = XCreateGC (st->dpy, st->p0, GCForeground, &gcv);
166 gcv.foreground = st->fg_pixel;
167 gcv.background = st->bg_pixel;
168 if (st->window_gc) XFreeGC(st->dpy, st->window_gc);
169 st->window_gc = XCreateGC (st->dpy, st->window, GCForeground|GCBackground, &gcv);
171 #define FROB(N,DN,MAX) \
172 N = (MAX/2) + (random() % MAX); \
173 DN = ((1 + (random() % (7*st->thickness))) * ((random() & 1) ? 1 : -1))
175 FROB(st->x1,st->dx1,st->width);
176 FROB(st->x2,st->dx2,st->width);
177 FROB(st->x3,st->dx3,st->width);
178 FROB(st->y1,st->dy1,st->height);
179 FROB(st->y2,st->dy2,st->height);
180 FROB(st->y3,st->dy3,st->height);
187 moire2 (struct state *st)
189 #define FROB(N,DN,MAX) \
191 if (N <= 0) N = 0, DN = -DN; \
192 else if (N >= MAX) N = MAX, DN = -DN; \
193 else if (0 == (random() % 100)) DN = -DN; \
194 else if (0 == (random() % 50)) \
195 DN += (DN <= -20 ? 1 : (DN >= 20 ? -1 : ((random() & 1) ? 1 : -1)))
197 FROB(st->x1,st->dx1,st->width);
198 FROB(st->x2,st->dx2,st->width);
199 FROB(st->x3,st->dx3,st->width);
200 FROB(st->y1,st->dy1,st->height);
201 FROB(st->y2,st->dy2,st->height);
202 FROB(st->y3,st->dy3,st->height);
205 XFillRectangle(st->dpy, st->p0, st->erase_gc, 0, 0, st->width, st->height);
206 XCopyArea(st->dpy, st->p1, st->p0, st->copy_gc, st->x1, st->y1, st->width, st->height, 0, 0);
207 XCopyArea(st->dpy, st->p2, st->p0, st->copy_gc, st->x2, st->y2, st->width, st->height, 0, 0);
209 XCopyArea(st->dpy, st->p3, st->p0, st->copy_gc, st->x3, st->y3, st->width, st->height, 0, 0);
211 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
214 XdbeSwapInfo info[1];
215 info[0].swap_window = st->window;
216 info[0].swap_action = XdbeUndefined;
217 XCopyPlane (st->dpy, st->p0, st->back_buf, st->window_gc, 0, 0, st->width, st->height, 0, 0, 1L);
218 XdbeSwapBuffers (st->dpy, info, 1);
221 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
222 XCopyPlane (st->dpy, st->p0, st->window, st->window_gc, 0, 0, st->width, st->height, 0, 0, 1L);
225 XCopyPlane(st->dpy, st->p1, st->window, st->window_gc, (st->width*2)/3, (st->height*2)/3,
226 st->width/2, st->height/2,
227 0, st->height/2, 1L);
228 XCopyPlane(st->dpy, st->p2, st->window, st->window_gc, (st->width*2)/3, (st->height*2)/3,
229 st->width/2, st->height/2,
230 st->width/2, st->height/2, 1L);
237 moire2_init (Display *dpy, Window window)
239 struct state *st = (struct state *) calloc (1, sizeof(*st));
244 st->delay = get_integer_resource (st->dpy, "delay", "Integer");
245 st->color_shift = get_integer_resource (st->dpy, "colorShift", "Integer");
247 if (st->color_shift <= 0) st->color_shift = 1;
253 moire2_draw (Display *dpy, Window window, void *closure)
255 struct state *st = (struct state *) closure;
262 st->iterations = 30 + (random() % 70) + (random() % 70);
265 st->flip_a = mono_p ? False : (random() & 1);
266 st->flip_b = mono_p ? False : (random() & 1);
270 XSetForeground(st->dpy, st->window_gc, st->bg_pixel);
271 XSetBackground(st->dpy, st->window_gc, st->fg_pixel);
275 XSetForeground(st->dpy, st->window_gc, st->fg_pixel);
276 XSetBackground(st->dpy, st->window_gc, st->bg_pixel);
283 st->pix = st->pix % st->ncolors;
286 XSetBackground(st->dpy, st->window_gc, st->colors[st->pix].pixel);
288 XSetForeground(st->dpy, st->window_gc, st->colors[st->pix].pixel);
294 if (st->iteration >= st->color_shift)
298 if (st->iterations <= 0)
306 moire2_reshape (Display *dpy, Window window, void *closure,
307 unsigned int w, unsigned int h)
309 struct state *st = (struct state *) closure;
314 moire2_event (Display *dpy, Window window, void *closure, XEvent *event)
320 moire2_free (Display *dpy, Window window, void *closure)
324 static const char *moire2_defaults [] = {
325 ".background: black",
326 ".foreground: white",
332 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
333 /* Off by default, since it slows it down a lot, and the flicker isn't really
334 all that bad without it... Or rather, it flickers just as badly with it.
335 The XFree86 implementation of the XDBE extension totally blows! There is
336 just *no* excuse for the "swap buffers" operation to flicker like it does.
339 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
344 static XrmOptionDescRec moire2_options [] = {
345 { "-delay", ".delay", XrmoptionSepArg, 0 },
346 { "-ncolors", ".colors", XrmoptionSepArg, 0 },
347 { "-thickness", ".thickness", XrmoptionSepArg, 0 },
351 XSCREENSAVER_MODULE ("Moire2", moire2)