1 /* xscreensaver, Copyright (c) 1999 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
13 #include "screenhack.h"
15 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
17 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
19 #define countof(x) (sizeof(x)/sizeof(*(x)))
20 #define ABS(x) ((x)<0?-(x):(x))
21 #define MAX(x,y) ((x)<(y)?(y):(x))
22 #define MIN(x,y) ((x)>(y)?(y):(x))
23 #define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n))))
24 #define RANDSIGN() ((random() & 1) ? 1 : -1)
32 struct disc *discs[4];
33 int x, y, size, size2;
36 XWindowAttributes xgwa;
37 Pixmap b, ba, bb; /* double-buffer to reduce flicker */
38 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
40 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
46 int theta; /* 0 - 360*64 */
51 void (*draw) (struct state *, Drawable, struct disc *,
52 int x, int y, int radius);
57 draw_letters (struct state *st, Drawable d, struct disc *disc,
58 int x, int y, int radius)
61 double th2 = 2 * M_PI * (disc->theta / ((double) 360*64));
68 points[0].x = x + radius * 0.8 * cos(th - 0.07);
69 points[0].y = y + radius * 0.8 * sin(th - 0.07);
71 points[1].x = x + radius * 0.7 * cos(th - 0.05);
72 points[1].y = y + radius * 0.7 * sin(th - 0.05);
74 points[2].x = x + radius * 0.78 * cos(th);
75 points[2].y = y + radius * 0.78 * sin(th);
77 points[3].x = x + radius * 0.7 * cos(th + 0.05);
78 points[3].y = y + radius * 0.7 * sin(th + 0.05);
80 points[4].x = x + radius * 0.8 * cos(th + 0.07);
81 points[4].y = y + radius * 0.8 * sin(th + 0.07);
83 XDrawLines (st->dpy, d, disc->gc, points, 5, CoordModeOrigin);
87 th = th2 + (2 * M_PI * 0.08333);
89 points[0].x = x + radius * 0.78 * cos(th - 0.13);
90 points[0].y = y + radius * 0.78 * sin(th - 0.13);
92 points[1].x = x + radius * 0.8 * cos(th - 0.08);
93 points[1].y = y + radius * 0.8 * sin(th - 0.08);
95 points[2].x = x + radius * 0.78 * cos(th - 0.03);
96 points[2].y = y + radius * 0.78 * sin(th - 0.03);
98 points[3].x = x + radius * 0.76 * cos(th - 0.03);
99 points[3].y = y + radius * 0.76 * sin(th - 0.03);
101 points[4].x = x + radius * 0.75 * cos(th - 0.08);
102 points[4].y = y + radius * 0.75 * sin(th - 0.08);
104 points[5].x = x + radius * 0.74 * cos(th - 0.03);
105 points[5].y = y + radius * 0.74 * sin(th - 0.03);
107 points[6].x = x + radius * 0.72 * cos(th - 0.03);
108 points[6].y = y + radius * 0.72 * sin(th - 0.03);
110 points[7].x = x + radius * 0.7 * cos(th - 0.08);
111 points[7].y = y + radius * 0.7 * sin(th - 0.08);
113 points[8].x = x + radius * 0.72 * cos(th - 0.13);
114 points[8].y = y + radius * 0.72 * sin(th - 0.13);
116 XDrawLines (st->dpy, d, disc->gc, points, 9, CoordModeOrigin);
120 points[0].x = x + radius * 0.78 * cos(th + 0.03);
121 points[0].y = y + radius * 0.78 * sin(th + 0.03);
123 points[1].x = x + radius * 0.8 * cos(th + 0.08);
124 points[1].y = y + radius * 0.8 * sin(th + 0.08);
126 points[2].x = x + radius * 0.78 * cos(th + 0.13);
127 points[2].y = y + radius * 0.78 * sin(th + 0.13);
129 points[3].x = x + radius * 0.72 * cos(th + 0.13);
130 points[3].y = y + radius * 0.72 * sin(th + 0.13);
132 points[4].x = x + radius * 0.7 * cos(th + 0.08);
133 points[4].y = y + radius * 0.7 * sin(th + 0.08);
135 points[5].x = x + radius * 0.72 * cos(th + 0.03);
136 points[5].y = y + radius * 0.72 * sin(th + 0.03);
138 points[6] = points[0];
140 XDrawLines (st->dpy, d, disc->gc, points, 7, CoordModeOrigin);
144 th = th2 + (2 * M_PI * 0.16666);
146 points[0].x = x + radius * 0.78 * cos(th - 0.13);
147 points[0].y = y + radius * 0.78 * sin(th - 0.13);
149 points[1].x = x + radius * 0.8 * cos(th - 0.08);
150 points[1].y = y + radius * 0.8 * sin(th - 0.08);
152 points[2].x = x + radius * 0.78 * cos(th - 0.03);
153 points[2].y = y + radius * 0.78 * sin(th - 0.03);
155 points[3].x = x + radius * 0.76 * cos(th - 0.03);
156 points[3].y = y + radius * 0.76 * sin(th - 0.03);
158 points[4].x = x + radius * 0.75 * cos(th - 0.08);
159 points[4].y = y + radius * 0.75 * sin(th - 0.08);
161 points[5].x = x + radius * 0.74 * cos(th - 0.03);
162 points[5].y = y + radius * 0.74 * sin(th - 0.03);
164 points[6].x = x + radius * 0.72 * cos(th - 0.03);
165 points[6].y = y + radius * 0.72 * sin(th - 0.03);
167 points[7].x = x + radius * 0.7 * cos(th - 0.08);
168 points[7].y = y + radius * 0.7 * sin(th - 0.08);
170 points[8].x = x + radius * 0.72 * cos(th - 0.13);
171 points[8].y = y + radius * 0.72 * sin(th - 0.13);
173 XDrawLines (st->dpy, d, disc->gc, points, 9, CoordModeOrigin);
177 points[0].x = x + radius * 0.78 * cos(th + 0.03);
178 points[0].y = y + radius * 0.78 * sin(th + 0.03);
180 points[1].x = x + radius * 0.8 * cos(th + 0.08);
181 points[1].y = y + radius * 0.8 * sin(th + 0.08);
183 points[2].x = x + radius * 0.78 * cos(th + 0.13);
184 points[2].y = y + radius * 0.78 * sin(th + 0.13);
186 points[3].x = x + radius * 0.76 * cos(th + 0.13);
187 points[3].y = y + radius * 0.76 * sin(th + 0.13);
189 points[4].x = x + radius * 0.75 * cos(th + 0.08);
190 points[4].y = y + radius * 0.75 * sin(th + 0.08);
192 points[5].x = x + radius * 0.74 * cos(th + 0.13);
193 points[5].y = y + radius * 0.74 * sin(th + 0.13);
195 points[6].x = x + radius * 0.72 * cos(th + 0.13);
196 points[6].y = y + radius * 0.72 * sin(th + 0.13);
198 points[7].x = x + radius * 0.7 * cos(th + 0.08);
199 points[7].y = y + radius * 0.7 * sin(th + 0.08);
201 points[8].x = x + radius * 0.72 * cos(th + 0.03);
202 points[8].y = y + radius * 0.72 * sin(th + 0.03);
204 XDrawLines (st->dpy, d, disc->gc, points, 9, CoordModeOrigin);
208 th = th2 + (2 * M_PI * 0.25);
210 points[0].x = x + radius * 0.7 * cos(th - 0.05);
211 points[0].y = y + radius * 0.7 * sin(th - 0.05);
213 points[1].x = x + radius * 0.8 * cos(th - 0.05);
214 points[1].y = y + radius * 0.8 * sin(th - 0.05);
216 points[2].x = x + radius * 0.7 * cos(th + 0.05);
217 points[2].y = y + radius * 0.7 * sin(th + 0.05);
219 points[3].x = x + radius * 0.8 * cos(th + 0.05);
220 points[3].y = y + radius * 0.8 * sin(th + 0.05);
222 XDrawLines (st->dpy, d, disc->gc, points, 4, CoordModeOrigin);
226 th = th2 + (2 * M_PI * 0.33333);
228 points[0].x = x + radius * 0.78 * cos(th - 0.05);
229 points[0].y = y + radius * 0.78 * sin(th - 0.05);
231 points[1].x = x + radius * 0.8 * cos(th);
232 points[1].y = y + radius * 0.8 * sin(th);
234 points[2].x = x + radius * 0.78 * cos(th + 0.05);
235 points[2].y = y + radius * 0.78 * sin(th + 0.05);
237 points[3].x = x + radius * 0.76 * cos(th + 0.05);
238 points[3].y = y + radius * 0.76 * sin(th + 0.05);
240 points[4].x = x + radius * 0.75 * cos(th);
241 points[4].y = y + radius * 0.75 * sin(th);
243 points[5].x = x + radius * 0.74 * cos(th + 0.05);
244 points[5].y = y + radius * 0.74 * sin(th + 0.05);
246 points[6].x = x + radius * 0.72 * cos(th + 0.05);
247 points[6].y = y + radius * 0.72 * sin(th + 0.05);
249 points[7].x = x + radius * 0.7 * cos(th);
250 points[7].y = y + radius * 0.7 * sin(th);
252 points[8].x = x + radius * 0.72 * cos(th - 0.05);
253 points[8].y = y + radius * 0.72 * sin(th - 0.05);
255 XDrawLines (st->dpy, d, disc->gc, points, 9, CoordModeOrigin);
259 th = th2 + (2 * M_PI * 0.41666);
261 points[0].x = x + radius * 0.78 * cos(th + 0.05);
262 points[0].y = y + radius * 0.78 * sin(th + 0.05);
264 points[1].x = x + radius * 0.8 * cos(th);
265 points[1].y = y + radius * 0.8 * sin(th);
267 points[2].x = x + radius * 0.78 * cos(th - 0.05);
268 points[2].y = y + radius * 0.78 * sin(th - 0.05);
270 points[3].x = x + radius * 0.72 * cos(th - 0.05);
271 points[3].y = y + radius * 0.72 * sin(th - 0.05);
273 points[4].x = x + radius * 0.7 * cos(th);
274 points[4].y = y + radius * 0.7 * sin(th);
276 points[5].x = x + radius * 0.72 * cos(th + 0.05);
277 points[5].y = y + radius * 0.72 * sin(th + 0.05);
279 points[6].x = x + radius * 0.74 * cos(th + 0.05);
280 points[6].y = y + radius * 0.74 * sin(th + 0.05);
282 points[7].x = x + radius * 0.76 * cos(th);
283 points[7].y = y + radius * 0.76 * sin(th);
285 points[8].x = x + radius * 0.74 * cos(th - 0.05);
286 points[8].y = y + radius * 0.74 * sin(th - 0.05);
288 XDrawLines (st->dpy, d, disc->gc, points, 9, CoordModeOrigin);
293 th = th2 + (2 * M_PI * 0.5);
295 points[0].x = x + radius * 0.8 * cos(th + 0.05);
296 points[0].y = y + radius * 0.8 * sin(th + 0.05);
298 points[1].x = x + radius * 0.8 * cos(th - 0.05);
299 points[1].y = y + radius * 0.8 * sin(th - 0.05);
301 points[2].x = x + radius * 0.75 * cos(th - 0.05);
302 points[2].y = y + radius * 0.75 * sin(th - 0.05);
304 points[3].x = x + radius * 0.75 * cos(th + 0.025);
305 points[3].y = y + radius * 0.75 * sin(th + 0.025);
307 points[4].x = x + radius * 0.75 * cos(th - 0.05);
308 points[4].y = y + radius * 0.75 * sin(th - 0.05);
310 points[5].x = x + radius * 0.7 * cos(th - 0.05);
311 points[5].y = y + radius * 0.7 * sin(th - 0.05);
313 points[6].x = x + radius * 0.7 * cos(th + 0.05);
314 points[6].y = y + radius * 0.7 * sin(th + 0.05);
316 XDrawLines (st->dpy, d, disc->gc, points, 7, CoordModeOrigin);
320 th = th2 + (2 * M_PI * 0.58333);
322 points[0].x = x + radius * 0.77 * cos(th - 0.06);
323 points[0].y = y + radius * 0.77 * sin(th - 0.06);
325 points[1].x = x + radius * 0.8 * cos(th - 0.03);
326 points[1].y = y + radius * 0.8 * sin(th - 0.03);
328 points[2].x = x + radius * 0.7 * cos(th - 0.03);
329 points[2].y = y + radius * 0.7 * sin(th - 0.03);
331 XDrawLines (st->dpy, d, disc->gc, points, 3, CoordModeOrigin);
335 points[0].x = x + radius * 0.78 * cos(th + 0.02);
336 points[0].y = y + radius * 0.78 * sin(th + 0.02);
338 points[1].x = x + radius * 0.8 * cos(th + 0.07);
339 points[1].y = y + radius * 0.8 * sin(th + 0.07);
341 points[2].x = x + radius * 0.78 * cos(th + 0.11);
342 points[2].y = y + radius * 0.78 * sin(th + 0.11);
344 points[3].x = x + radius * 0.76 * cos(th + 0.11);
345 points[3].y = y + radius * 0.76 * sin(th + 0.11);
347 points[4].x = x + radius * 0.74 * cos(th + 0.02);
348 points[4].y = y + radius * 0.74 * sin(th + 0.02);
350 points[5].x = x + radius * 0.71 * cos(th + 0.03);
351 points[5].y = y + radius * 0.71 * sin(th + 0.03);
353 points[6].x = x + radius * 0.7 * cos(th + 0.03);
354 points[6].y = y + radius * 0.7 * sin(th + 0.03);
356 points[7].x = x + radius * 0.7 * cos(th + 0.13);
357 points[7].y = y + radius * 0.7 * sin(th + 0.13);
359 XDrawLines (st->dpy, d, disc->gc, points, 8, CoordModeOrigin);
363 th = th2 + (2 * M_PI * 0.66666);
365 points[0].x = x + radius * 0.77 * cos(th - 0.06);
366 points[0].y = y + radius * 0.77 * sin(th - 0.06);
368 points[1].x = x + radius * 0.8 * cos(th - 0.03);
369 points[1].y = y + radius * 0.8 * sin(th - 0.03);
371 points[2].x = x + radius * 0.7 * cos(th - 0.03);
372 points[2].y = y + radius * 0.7 * sin(th - 0.03);
374 XDrawLines (st->dpy, d, disc->gc, points, 3, CoordModeOrigin);
378 points[0].x = x + radius * 0.8 * cos(th + 0.11);
379 points[0].y = y + radius * 0.8 * sin(th + 0.11);
381 points[1].x = x + radius * 0.8 * cos(th + 0.02);
382 points[1].y = y + radius * 0.8 * sin(th + 0.02);
384 points[2].x = x + radius * 0.76 * cos(th + 0.02);
385 points[2].y = y + radius * 0.76 * sin(th + 0.02);
387 points[3].x = x + radius * 0.77 * cos(th + 0.06);
388 points[3].y = y + radius * 0.77 * sin(th + 0.06);
390 points[4].x = x + radius * 0.76 * cos(th + 0.10);
391 points[4].y = y + radius * 0.76 * sin(th + 0.10);
393 points[5].x = x + radius * 0.73 * cos(th + 0.11);
394 points[5].y = y + radius * 0.73 * sin(th + 0.11);
396 points[6].x = x + radius * 0.72 * cos(th + 0.10);
397 points[6].y = y + radius * 0.72 * sin(th + 0.10);
399 points[7].x = x + radius * 0.7 * cos(th + 0.06);
400 points[7].y = y + radius * 0.7 * sin(th + 0.06);
402 points[8].x = x + radius * 0.72 * cos(th + 0.02);
403 points[8].y = y + radius * 0.72 * sin(th + 0.02);
405 XDrawLines (st->dpy, d, disc->gc, points, 9, CoordModeOrigin);
409 th = th2 + (2 * M_PI * 0.75);
411 points[0].x = x + radius * 0.78 * cos(th + 0.05);
412 points[0].y = y + radius * 0.78 * sin(th + 0.05);
414 points[1].x = x + radius * 0.8 * cos(th);
415 points[1].y = y + radius * 0.8 * sin(th);
417 points[2].x = x + radius * 0.78 * cos(th - 0.05);
418 points[2].y = y + radius * 0.78 * sin(th - 0.05);
420 points[3].x = x + radius * 0.76 * cos(th - 0.05);
421 points[3].y = y + radius * 0.76 * sin(th - 0.05);
423 points[4].x = x + radius * 0.74 * cos(th + 0.05);
424 points[4].y = y + radius * 0.74 * sin(th + 0.05);
426 points[5].x = x + radius * 0.72 * cos(th + 0.05);
427 points[5].y = y + radius * 0.72 * sin(th + 0.05);
429 points[6].x = x + radius * 0.7 * cos(th);
430 points[6].y = y + radius * 0.7 * sin(th);
432 points[7].x = x + radius * 0.72 * cos(th - 0.05);
433 points[7].y = y + radius * 0.72 * sin(th - 0.05);
435 XDrawLines (st->dpy, d, disc->gc, points, 8, CoordModeOrigin);
439 th = th2 + (2 * M_PI * 0.83333);
441 points[0].x = x + radius * 0.78 * cos(th - 0.13);
442 points[0].y = y + radius * 0.78 * sin(th - 0.13);
444 points[1].x = x + radius * 0.8 * cos(th - 0.08);
445 points[1].y = y + radius * 0.8 * sin(th - 0.08);
447 points[2].x = x + radius * 0.78 * cos(th - 0.03);
448 points[2].y = y + radius * 0.78 * sin(th - 0.03);
450 points[3].x = x + radius * 0.76 * cos(th - 0.03);
451 points[3].y = y + radius * 0.76 * sin(th - 0.03);
453 points[4].x = x + radius * 0.74 * cos(th - 0.12);
454 points[4].y = y + radius * 0.74 * sin(th - 0.12);
456 points[5].x = x + radius * 0.71 * cos(th - 0.13);
457 points[5].y = y + radius * 0.71 * sin(th - 0.13);
459 points[6].x = x + radius * 0.7 * cos(th - 0.13);
460 points[6].y = y + radius * 0.7 * sin(th - 0.13);
462 points[7].x = x + radius * 0.7 * cos(th - 0.02);
463 points[7].y = y + radius * 0.7 * sin(th - 0.02);
465 XDrawLines (st->dpy, d, disc->gc, points, 8, CoordModeOrigin);
469 points[0].x = x + radius * 0.77 * cos(th + 0.03);
470 points[0].y = y + radius * 0.77 * sin(th + 0.03);
472 points[1].x = x + radius * 0.8 * cos(th + 0.06);
473 points[1].y = y + radius * 0.8 * sin(th + 0.06);
475 points[2].x = x + radius * 0.7 * cos(th + 0.06);
476 points[2].y = y + radius * 0.7 * sin(th + 0.06);
478 XDrawLines (st->dpy, d, disc->gc, points, 3, CoordModeOrigin);
482 th = th2 + (2 * M_PI * 0.91666);
484 points[0].x = x + radius * 0.78 * cos(th - 0.13);
485 points[0].y = y + radius * 0.78 * sin(th - 0.13);
487 points[1].x = x + radius * 0.8 * cos(th - 0.08);
488 points[1].y = y + radius * 0.8 * sin(th - 0.08);
490 points[2].x = x + radius * 0.78 * cos(th - 0.03);
491 points[2].y = y + radius * 0.78 * sin(th - 0.03);
493 points[3].x = x + radius * 0.76 * cos(th - 0.03);
494 points[3].y = y + radius * 0.76 * sin(th - 0.03);
496 points[4].x = x + radius * 0.74 * cos(th - 0.12);
497 points[4].y = y + radius * 0.74 * sin(th - 0.12);
499 points[5].x = x + radius * 0.71 * cos(th - 0.13);
500 points[5].y = y + radius * 0.71 * sin(th - 0.13);
502 points[6].x = x + radius * 0.7 * cos(th - 0.13);
503 points[6].y = y + radius * 0.7 * sin(th - 0.13);
505 points[7].x = x + radius * 0.7 * cos(th - 0.02);
506 points[7].y = y + radius * 0.7 * sin(th - 0.02);
508 XDrawLines (st->dpy, d, disc->gc, points, 8, CoordModeOrigin);
512 points[0].x = x + radius * 0.69 * cos(th + 0.09);
513 points[0].y = y + radius * 0.69 * sin(th + 0.09);
515 points[1].x = x + radius * 0.8 * cos(th + 0.09);
516 points[1].y = y + radius * 0.8 * sin(th + 0.09);
518 points[2].x = x + radius * 0.72 * cos(th + 0.01);
519 points[2].y = y + radius * 0.72 * sin(th + 0.01);
521 points[3].x = x + radius * 0.72 * cos(th + 0.13);
522 points[3].y = y + radius * 0.72 * sin(th + 0.13);
524 XDrawLines (st->dpy, d, disc->gc, points, 4, CoordModeOrigin);
529 draw_ticks (struct state *st, Drawable d, struct disc *disc,
530 int x, int y, int radius)
534 double tick = (M_PI * 2) / 72;
536 for (i = 0; i < 72; i++)
538 int radius2 = radius;
539 double th = (i * tick) + (2 * M_PI * (disc->theta / ((double) 360*64)));
542 radius2 -= radius / 16;
544 radius2 -= radius / 8;
546 segs[i].x1 = x + radius * cos(th);
547 segs[i].y1 = y + radius * sin(th);
548 segs[i].x2 = x + radius2 * cos(th);
549 segs[i].y2 = y + radius2 * sin(th);
551 XDrawSegments (st->dpy, d, disc->gc, segs, countof(segs));
553 draw_letters (st, d, disc, x, y, radius);
558 draw_thin_arrow (struct state *st, Drawable d, struct disc *disc,
559 int x, int y, int radius)
564 double tick = ((M_PI * 2) / 72) * 2;
567 radius2 = radius - (radius / 8) * 3;
569 th = 2 * M_PI * (disc->theta / ((double) 360*64));
571 points[0].x = x + radius * cos(th); /* tip */
572 points[0].y = y + radius * sin(th);
574 points[1].x = x + radius2 * cos(th - tick); /* tip left */
575 points[1].y = y + radius2 * sin(th - tick);
577 points[2].x = x + radius2 * cos(th + tick); /* tip right */
578 points[2].y = y + radius2 * sin(th + tick);
580 XDrawLine (st->dpy, d, disc->gc,
581 (int) (x + radius2 * cos(th)),
582 (int) (y + radius2 * sin(th)),
583 (int) (x + -radius * cos(th)),
584 (int) (y + -radius * sin(th)));
586 XFillPolygon (st->dpy, d, disc->gc, points, 3, Convex, CoordModeOrigin);
591 draw_thick_arrow (struct state *st, Drawable d, struct disc *disc,
592 int x, int y, int radius)
596 int radius2, radius3;
597 double tick = ((M_PI * 2) / 72) * 2;
600 radius2 = radius - (radius / 8) * 3;
601 radius3 = radius - (radius / 8) * 2;
602 th = 2 * M_PI * (disc->theta / ((double) 360*64));
604 points[0].x = x + radius * cos(th); /* tip */
605 points[0].y = y + radius * sin(th);
607 points[1].x = x + radius2 * cos(th - tick); /* tip left */
608 points[1].y = y + radius2 * sin(th - tick);
610 points[2].x = x + radius2 * cos(th + tick); /* tip right */
611 points[2].y = y + radius2 * sin(th + tick);
613 points[3] = points[0];
615 XDrawLines (st->dpy, d, disc->gc, points, 4, CoordModeOrigin);
617 points[0].x = x + radius2 * cos(th - tick/2); /* top left */
618 points[0].y = y + radius2 * sin(th - tick/2);
620 points[1].x = x + -radius2 * cos(th + tick/2); /* bottom left */
621 points[1].y = y + -radius2 * sin(th + tick/2);
623 points[2].x = x + -radius3 * cos(th); /* bottom */
624 points[2].y = y + -radius3 * sin(th);
626 points[3].x = x + -radius * cos(th); /* bottom spike */
627 points[3].y = y + -radius * sin(th);
629 points[4] = points[2]; /* return */
631 points[5].x = x + -radius2 * cos(th - tick/2); /* bottom right */
632 points[5].y = y + -radius2 * sin(th - tick/2);
634 points[6].x = x + radius2 * cos(th + tick/2); /* top right */
635 points[6].y = y + radius2 * sin(th + tick/2);
637 XDrawLines (st->dpy, d, disc->gc, points, 7, CoordModeOrigin);
643 roll_disc (struct disc *disc)
645 double th = disc->theta;
647 th = -(th + disc->velocity);
649 th = (th + disc->velocity);
656 disc->theta = (disc->theta > 0 ? th : -th);
658 disc->velocity += disc->acceleration;
660 if (disc->velocity > disc->limit ||
661 disc->velocity < -disc->limit)
662 disc->acceleration = -disc->acceleration;
664 /* Alter direction of rotational acceleration randomly. */
665 if (! (random() % 120))
666 disc->acceleration = -disc->acceleration;
668 /* Change acceleration very occasionally. */
669 if (! (random() % 200))
672 disc->acceleration *= 1.2;
674 disc->acceleration *= 0.8;
680 init_spin (struct disc *disc)
683 disc->theta = RAND(360*64);
684 disc->velocity = RAND(16) * RANDSIGN();
685 disc->acceleration = RAND(16) * RANDSIGN();
690 draw_compass (struct state *st)
695 st->discs[i]->draw (st, st->b, st->discs[i], st->x, st->y, st->size);
696 roll_disc (st->discs[i]);
702 draw_pointer (struct state *st)
704 int radius = st->size;
705 GC dot_gc = st->discs[0]->gc;
707 int size = radius * 0.1;
711 points[0].x = st->x - size;
712 points[0].y = st->y - radius - size;
714 points[1].x = st->x + size;
715 points[1].y = st->y - radius - size;
718 points[2].y = st->y - radius;
720 XFillPolygon (st->dpy, st->b, st->ptr_gc, points, 3, Convex, CoordModeOrigin);
724 points[0].x = st->x - (radius * 0.85);
725 points[0].y = st->y - (radius * 0.8);
727 points[1].x = st->x - (radius * 1.1);
728 points[1].y = st->y - (radius * 0.55);
730 points[2].x = st->x - (radius * 0.6);
731 points[2].y = st->y - (radius * 0.65);
733 XFillPolygon (st->dpy, st->b, st->ptr_gc, points, 3, Convex, CoordModeOrigin);
737 points[0].x = st->x - (radius * 1.05);
740 points[1].x = st->x - (radius * 1.1);
741 points[1].y = st->y - (radius * 0.025);
743 points[2].x = st->x - (radius * 1.1);
744 points[2].y = st->y + (radius * 0.025);
746 XFillPolygon (st->dpy, st->b, dot_gc, points, 3, Convex, CoordModeOrigin);
750 points[0].x = st->x + (radius * 1.05);
753 points[1].x = st->x + (radius * 1.1);
754 points[1].y = st->y - (radius * 0.025);
756 points[2].x = st->x + (radius * 1.1);
757 points[2].y = st->y + (radius * 0.025);
759 XFillPolygon (st->dpy, st->b, dot_gc, points, 3, Convex, CoordModeOrigin);
764 points[0].y = st->y + (radius * 1.05);
766 points[1].x = st->x - (radius * 0.025);
767 points[1].y = st->y + (radius * 1.1);
769 points[2].x = st->x + (radius * 0.025);
770 points[2].y = st->y + (radius * 1.1);
772 XFillPolygon (st->dpy, st->b, dot_gc, points, 3, Convex, CoordModeOrigin);
776 points[0].x = st->x + (radius * 0.74);
777 points[0].y = st->y + (radius * 0.74);
779 points[1].x = st->x + (radius * 0.78);
780 points[1].y = st->y + (radius * 0.75);
782 points[2].x = st->x + (radius * 0.75);
783 points[2].y = st->y + (radius * 0.78);
785 XFillPolygon (st->dpy, st->b, dot_gc, points, 3, Convex, CoordModeOrigin);
789 points[0].x = st->x + (radius * 0.74);
790 points[0].y = st->y - (radius * 0.74);
792 points[1].x = st->x + (radius * 0.78);
793 points[1].y = st->y - (radius * 0.75);
795 points[2].x = st->x + (radius * 0.75);
796 points[2].y = st->y - (radius * 0.78);
798 XFillPolygon (st->dpy, st->b, dot_gc, points, 3, Convex, CoordModeOrigin);
802 points[0].x = st->x - (radius * 0.74);
803 points[0].y = st->y + (radius * 0.74);
805 points[1].x = st->x - (radius * 0.78);
806 points[1].y = st->y + (radius * 0.75);
808 points[2].x = st->x - (radius * 0.75);
809 points[2].y = st->y + (radius * 0.78);
811 XFillPolygon (st->dpy, st->b, dot_gc, points, 3, Convex, CoordModeOrigin);
816 compass_init (Display *dpy, Window window)
818 struct state *st = (struct state *) calloc (1, sizeof(*st));
822 st->delay = get_integer_resource (st->dpy, "delay", "Integer");
823 st->dbuf = get_boolean_resource (st->dpy, "doubleBuffer", "Boolean");
825 # ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */
829 XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
830 st->size2 = MIN(st->xgwa.width, st->xgwa.height);
832 if (st->size2 > 600) st->size2 = 600;
834 st->size = (st->size2 / 2) * 0.8;
836 st->x = st->xgwa.width/2;
837 st->y = st->xgwa.height/2;
841 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
842 st->b = st->backb = xdbe_get_backbuffer (st->dpy, st->window, XdbeUndefined);
843 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
849 st->ba = XCreatePixmap (st->dpy, st->window, st->size2, st->size2, st->xgwa.depth);
850 st->bb = XCreatePixmap (st->dpy, st->window, st->size2, st->size2, st->xgwa.depth);
859 st->discs[0] = (struct disc *) calloc (1, sizeof (struct disc));
860 st->discs[1] = (struct disc *) calloc (1, sizeof (struct disc));
861 st->discs[2] = (struct disc *) calloc (1, sizeof (struct disc));
864 gcv.foreground = get_pixel_resource (st->dpy, st->xgwa.colormap,
865 "foreground", "Foreground");
866 gcv.line_width = MAX(2, (st->size/60));
867 gcv.join_style = JoinBevel;
868 st->discs[0]->draw = draw_ticks;
869 st->discs[0]->gc = XCreateGC (st->dpy, st->b, GCForeground|GCLineWidth|GCJoinStyle,
871 init_spin (st->discs[0]);
873 gcv.foreground = get_pixel_resource (st->dpy, st->xgwa.colormap,
874 "arrow2Foreground", "Foreground");
875 gcv.line_width = MAX(4, (st->size / 30));
876 st->discs[1]->draw = draw_thick_arrow;
877 st->discs[1]->gc = XCreateGC (st->dpy, st->b, GCForeground|GCLineWidth, &gcv);
878 init_spin (st->discs[1]);
880 gcv.foreground = get_pixel_resource (st->dpy, st->xgwa.colormap,
881 "arrow1Foreground", "Foreground");
882 gcv.line_width = MAX(4, (st->size / 30));
883 st->discs[2]->draw = draw_thin_arrow;
884 st->discs[2]->gc = XCreateGC (st->dpy, st->b, GCForeground|GCLineWidth, &gcv);
885 init_spin (st->discs[2]);
887 gcv.foreground = get_pixel_resource (st->dpy, st->xgwa.colormap,
888 "pointerForeground", "Foreground");
889 st->ptr_gc = XCreateGC (st->dpy, st->b, GCForeground|GCLineWidth, &gcv);
891 gcv.foreground = get_pixel_resource (st->dpy, st->xgwa.colormap,
892 "background", "Background");
893 st->erase_gc = XCreateGC (st->dpy, st->b, GCForeground, &gcv);
895 if (st->ba) XFillRectangle (st->dpy, st->ba, st->erase_gc, 0, 0, st->size2, st->size2);
896 if (st->bb) XFillRectangle (st->dpy, st->bb, st->erase_gc, 0, 0, st->size2, st->size2);
902 compass_draw (Display *dpy, Window window, void *closure)
904 struct state *st = (struct state *) closure;
905 XFillRectangle (st->dpy, st->b, st->erase_gc, 0, 0, st->xgwa.width, st->xgwa.height);
910 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
913 XdbeSwapInfo info[1];
914 info[0].swap_window = st->window;
915 info[0].swap_action = XdbeUndefined;
916 XdbeSwapBuffers (st->dpy, info, 1);
919 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
922 XCopyArea (st->dpy, st->b, st->window, st->erase_gc, 0, 0,
923 st->size2, st->size2,
924 st->xgwa.width/2 - st->x,
925 st->xgwa.height/2 - st->y);
926 st->b = (st->b == st->ba ? st->bb : st->ba);
933 compass_reshape (Display *dpy, Window window, void *closure,
934 unsigned int w, unsigned int h)
936 struct state *st = (struct state *) closure;
937 XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
938 st->size2 = MIN(st->xgwa.width, st->xgwa.height);
939 st->x = st->xgwa.width/2;
940 st->y = st->xgwa.height/2;
944 compass_event (Display *dpy, Window window, void *closure, XEvent *event)
950 compass_free (Display *dpy, Window window, void *closure)
956 static const char *compass_defaults [] = {
957 ".background: #000000",
958 ".foreground: #DDFFFF",
959 "*arrow1Foreground: #FFF66A",
960 "*arrow2Foreground: #F7D64A",
961 "*pointerForeground: #FF0000",
963 "*doubleBuffer: True",
964 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
966 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
970 static XrmOptionDescRec compass_options [] = {
971 { "-delay", ".delay", XrmoptionSepArg, 0 },
972 { "-db", ".doubleBuffer", XrmoptionNoArg, "True" },
973 { "-no-db", ".doubleBuffer", XrmoptionNoArg, "False" },
978 XSCREENSAVER_MODULE ("Compass", compass)