1 | /* xscreensaver, Copyright (c) 1997, 1998, 2001 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 | * Concept snarfed from Michael D. Bayne in |
---|
12 | * http://www.go2net.com/internet/deep/1997/04/16/body.html |
---|
13 | */ |
---|
14 | |
---|
15 | #include "screenhack.h" |
---|
16 | #include <X11/Xutil.h> |
---|
17 | #include <stdio.h> |
---|
18 | |
---|
19 | #ifdef HAVE_XSHM_EXTENSION |
---|
20 | # include "xshm.h" |
---|
21 | static Bool use_shm; |
---|
22 | static XShmSegmentInfo shm_info; |
---|
23 | #endif /* HAVE_XSHM_EXTENSION */ |
---|
24 | |
---|
25 | static int offset = 0; |
---|
26 | static XColor *colors = 0; |
---|
27 | static int ncolors = 0; |
---|
28 | static GC gc = 0; |
---|
29 | static unsigned long fg_pixel = 0; |
---|
30 | static unsigned long bg_pixel = 0; |
---|
31 | |
---|
32 | static void |
---|
33 | init_moire (Display *dpy, Window window) |
---|
34 | { |
---|
35 | int oncolors; |
---|
36 | int i; |
---|
37 | int fgh, bgh; |
---|
38 | double fgs, fgv, bgs, bgv; |
---|
39 | XWindowAttributes xgwa; |
---|
40 | XColor fgc, bgc; |
---|
41 | XGCValues gcv; |
---|
42 | XGetWindowAttributes (dpy, window, &xgwa); |
---|
43 | |
---|
44 | offset = get_integer_resource ("offset", "Integer"); |
---|
45 | if (offset < 2) offset = 2; |
---|
46 | |
---|
47 | #ifdef HAVE_XSHM_EXTENSION |
---|
48 | use_shm = get_boolean_resource("useSHM", "Boolean"); |
---|
49 | #endif /* HAVE_XSHM_EXTENSION */ |
---|
50 | |
---|
51 | MONO: |
---|
52 | if (colors) |
---|
53 | { |
---|
54 | for (i = 0; i < ncolors; i++) |
---|
55 | XFreeColors (dpy, xgwa.colormap, &colors[i].pixel, 1, 0); |
---|
56 | free(colors); |
---|
57 | colors = 0; |
---|
58 | } |
---|
59 | |
---|
60 | if (mono_p) |
---|
61 | { |
---|
62 | fg_pixel = WhitePixelOfScreen (DefaultScreenOfDisplay(dpy)); |
---|
63 | bg_pixel = BlackPixelOfScreen (DefaultScreenOfDisplay(dpy)); |
---|
64 | } |
---|
65 | else |
---|
66 | { |
---|
67 | fg_pixel = get_pixel_resource ("foreground", "Foreground", dpy, |
---|
68 | xgwa.colormap); |
---|
69 | bg_pixel = get_pixel_resource ("background", "Background", dpy, |
---|
70 | xgwa.colormap); |
---|
71 | } |
---|
72 | |
---|
73 | if (mono_p) |
---|
74 | { |
---|
75 | offset *= 20; /* compensate for lack of shading */ |
---|
76 | gcv.foreground = fg_pixel; |
---|
77 | } |
---|
78 | else |
---|
79 | { |
---|
80 | ncolors = get_integer_resource ("ncolors", "Integer"); |
---|
81 | if (ncolors < 2) ncolors = 2; |
---|
82 | oncolors = ncolors; |
---|
83 | |
---|
84 | fgc.flags = bgc.flags = DoRed|DoGreen|DoBlue; |
---|
85 | if (get_boolean_resource("random","Boolean")) |
---|
86 | { |
---|
87 | fgc.red = random() & 0xFFFF; |
---|
88 | fgc.green = random() & 0xFFFF; |
---|
89 | fgc.blue = random() & 0xFFFF; |
---|
90 | bgc.red = random() & 0xFFFF; |
---|
91 | bgc.green = random() & 0xFFFF; |
---|
92 | bgc.blue = random() & 0xFFFF; |
---|
93 | } |
---|
94 | else |
---|
95 | { |
---|
96 | fgc.pixel = fg_pixel; |
---|
97 | bgc.pixel = bg_pixel; |
---|
98 | XQueryColor (dpy, xgwa.colormap, &fgc); |
---|
99 | XQueryColor (dpy, xgwa.colormap, &bgc); |
---|
100 | } |
---|
101 | rgb_to_hsv (fgc.red, fgc.green, fgc.blue, &fgh, &fgs, &fgv); |
---|
102 | rgb_to_hsv (bgc.red, bgc.green, bgc.blue, &bgh, &bgs, &bgv); |
---|
103 | |
---|
104 | colors = (XColor *) malloc (sizeof (XColor) * (ncolors+2)); |
---|
105 | memset(colors, 0, (sizeof (XColor) * (ncolors+2))); |
---|
106 | make_color_ramp (dpy, xgwa.colormap, |
---|
107 | fgh, fgs, fgv, bgh, bgs, bgv, |
---|
108 | colors, &ncolors, |
---|
109 | True, True, False); |
---|
110 | if (ncolors != oncolors) |
---|
111 | fprintf(stderr, "%s: got %d of %d requested colors.\n", |
---|
112 | progname, ncolors, oncolors); |
---|
113 | |
---|
114 | if (ncolors <= 2) |
---|
115 | { |
---|
116 | mono_p = True; |
---|
117 | goto MONO; |
---|
118 | } |
---|
119 | |
---|
120 | gcv.foreground = colors[0].pixel; |
---|
121 | } |
---|
122 | gc = XCreateGC (dpy, window, GCForeground, &gcv); |
---|
123 | } |
---|
124 | |
---|
125 | |
---|
126 | static void |
---|
127 | moire (Display *dpy, Window window, int offset, XColor *colors, int ncolors) |
---|
128 | { |
---|
129 | long x, y, xo, yo; |
---|
130 | int factor = (random() % offset) + 1; |
---|
131 | XGCValues gcv; |
---|
132 | XWindowAttributes xgwa; |
---|
133 | XImage *image; |
---|
134 | int depth; |
---|
135 | XGetWindowAttributes (dpy, window, &xgwa); |
---|
136 | |
---|
137 | xo = (random() % xgwa.width) - xgwa.width/2; |
---|
138 | yo = (random() % xgwa.height) - xgwa.height/2; |
---|
139 | |
---|
140 | depth = visual_depth(DefaultScreenOfDisplay(dpy), xgwa.visual); |
---|
141 | |
---|
142 | image = 0; |
---|
143 | # ifdef HAVE_XSHM_EXTENSION |
---|
144 | if (use_shm) |
---|
145 | { |
---|
146 | image = create_xshm_image(dpy, xgwa.visual, depth, ZPixmap, 0, |
---|
147 | &shm_info, xgwa.width, 1); |
---|
148 | if (!image) |
---|
149 | use_shm = False; |
---|
150 | } |
---|
151 | # endif /* HAVE_XSHM_EXTENSION */ |
---|
152 | |
---|
153 | if (!image) |
---|
154 | { |
---|
155 | image = XCreateImage (dpy, xgwa.visual, |
---|
156 | depth, ZPixmap, 0, /* depth, format, offset */ |
---|
157 | 0, xgwa.width, 1, 8, 0); /* data, w, h, pad, bpl */ |
---|
158 | image->data = (char *) calloc(image->height, image->bytes_per_line); |
---|
159 | } |
---|
160 | |
---|
161 | for (y = 0; y < xgwa.height; y++) |
---|
162 | { |
---|
163 | for (x = 0; x < xgwa.width; x++) |
---|
164 | { |
---|
165 | double xx = x + xo; |
---|
166 | double yy = y + yo; |
---|
167 | double i = ((xx * xx) + (yy * yy)) / (double) factor; |
---|
168 | if (mono_p) |
---|
169 | gcv.foreground = ((((long) i) & 1) ? fg_pixel : bg_pixel); |
---|
170 | else |
---|
171 | gcv.foreground = colors[((long) i) % ncolors].pixel; |
---|
172 | XPutPixel (image, x, 0, gcv.foreground); |
---|
173 | } |
---|
174 | |
---|
175 | # ifdef HAVE_XSHM_EXTENSION |
---|
176 | if (use_shm) |
---|
177 | XShmPutImage(dpy, window, gc, image, 0, 0, 0, y, xgwa.width, 1, False); |
---|
178 | else |
---|
179 | # endif /* HAVE_XSHM_EXTENSION */ |
---|
180 | XPutImage (dpy, window, gc, image, 0, 0, 0, y, xgwa.width, 1); |
---|
181 | |
---|
182 | XSync(dpy, False); |
---|
183 | } |
---|
184 | |
---|
185 | # ifdef HAVE_XSHM_EXTENSION |
---|
186 | if (!use_shm) |
---|
187 | # endif /* HAVE_XSHM_EXTENSION */ |
---|
188 | if (image->data) |
---|
189 | { |
---|
190 | free(image->data); |
---|
191 | image->data = 0; |
---|
192 | } |
---|
193 | |
---|
194 | # ifdef HAVE_XSHM_EXTENSION |
---|
195 | if (use_shm) |
---|
196 | destroy_xshm_image (dpy, image, &shm_info); |
---|
197 | else |
---|
198 | # endif /* HAVE_XSHM_EXTENSION */ |
---|
199 | XDestroyImage (image); |
---|
200 | } |
---|
201 | |
---|
202 | |
---|
203 | char *progclass = "Moire"; |
---|
204 | |
---|
205 | char *defaults [] = { |
---|
206 | ".background: blue", |
---|
207 | ".foreground: red", |
---|
208 | "*random: true", |
---|
209 | "*delay: 5", |
---|
210 | "*ncolors: 64", |
---|
211 | "*offset: 50", |
---|
212 | #ifdef HAVE_XSHM_EXTENSION |
---|
213 | "*useSHM: True", |
---|
214 | #endif /* HAVE_XSHM_EXTENSION */ |
---|
215 | 0 |
---|
216 | }; |
---|
217 | |
---|
218 | XrmOptionDescRec options [] = { |
---|
219 | { "-random", ".random", XrmoptionNoArg, "True" }, |
---|
220 | { "-no-random", ".random", XrmoptionNoArg, "False" }, |
---|
221 | { "-delay", ".delay", XrmoptionSepArg, 0 }, |
---|
222 | { "-ncolors", ".ncolors", XrmoptionSepArg, 0 }, |
---|
223 | { "-offset", ".offset", XrmoptionSepArg, 0 }, |
---|
224 | #ifdef HAVE_XSHM_EXTENSION |
---|
225 | { "-shm", ".useSHM", XrmoptionNoArg, "True" }, |
---|
226 | { "-no-shm", ".useSHM", XrmoptionNoArg, "False" }, |
---|
227 | #endif /* HAVE_XSHM_EXTENSION */ |
---|
228 | { 0, 0, 0, 0 } |
---|
229 | }; |
---|
230 | |
---|
231 | void |
---|
232 | screenhack (Display *dpy, Window window) |
---|
233 | { |
---|
234 | int delay = get_integer_resource ("delay", "Integer"); |
---|
235 | while (1) |
---|
236 | { |
---|
237 | init_moire (dpy, window); |
---|
238 | moire (dpy, window, offset, colors, ncolors); |
---|
239 | XSync (dpy, False); |
---|
240 | screenhack_handle_events (dpy); |
---|
241 | if (delay) |
---|
242 | sleep(delay); |
---|
243 | } |
---|
244 | } |
---|