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)
27 int theta; /* 0 - 360*64 */
32 void (*draw) (Display *, Drawable, struct disc *,
33 int x, int y, int radius);
38 draw_letters (Display *dpy, Drawable d, struct disc *disc,
39 int x, int y, int radius)
42 double th2 = 2 * M_PI * (disc->theta / ((double) 360*64));
49 points[0].x = x + radius * 0.8 * cos(th - 0.07);
50 points[0].y = y + radius * 0.8 * sin(th - 0.07);
52 points[1].x = x + radius * 0.7 * cos(th - 0.05);
53 points[1].y = y + radius * 0.7 * sin(th - 0.05);
55 points[2].x = x + radius * 0.78 * cos(th);
56 points[2].y = y + radius * 0.78 * sin(th);
58 points[3].x = x + radius * 0.7 * cos(th + 0.05);
59 points[3].y = y + radius * 0.7 * sin(th + 0.05);
61 points[4].x = x + radius * 0.8 * cos(th + 0.07);
62 points[4].y = y + radius * 0.8 * sin(th + 0.07);
64 XDrawLines (dpy, d, disc->gc, points, 5, CoordModeOrigin);
68 th = th2 + (2 * M_PI * 0.08333);
70 points[0].x = x + radius * 0.78 * cos(th - 0.13);
71 points[0].y = y + radius * 0.78 * sin(th - 0.13);
73 points[1].x = x + radius * 0.8 * cos(th - 0.08);
74 points[1].y = y + radius * 0.8 * sin(th - 0.08);
76 points[2].x = x + radius * 0.78 * cos(th - 0.03);
77 points[2].y = y + radius * 0.78 * sin(th - 0.03);
79 points[3].x = x + radius * 0.76 * cos(th - 0.03);
80 points[3].y = y + radius * 0.76 * sin(th - 0.03);
82 points[4].x = x + radius * 0.75 * cos(th - 0.08);
83 points[4].y = y + radius * 0.75 * sin(th - 0.08);
85 points[5].x = x + radius * 0.74 * cos(th - 0.03);
86 points[5].y = y + radius * 0.74 * sin(th - 0.03);
88 points[6].x = x + radius * 0.72 * cos(th - 0.03);
89 points[6].y = y + radius * 0.72 * sin(th - 0.03);
91 points[7].x = x + radius * 0.7 * cos(th - 0.08);
92 points[7].y = y + radius * 0.7 * sin(th - 0.08);
94 points[8].x = x + radius * 0.72 * cos(th - 0.13);
95 points[8].y = y + radius * 0.72 * sin(th - 0.13);
97 XDrawLines (dpy, d, disc->gc, points, 9, CoordModeOrigin);
101 points[0].x = x + radius * 0.78 * cos(th + 0.03);
102 points[0].y = y + radius * 0.78 * sin(th + 0.03);
104 points[1].x = x + radius * 0.8 * cos(th + 0.08);
105 points[1].y = y + radius * 0.8 * sin(th + 0.08);
107 points[2].x = x + radius * 0.78 * cos(th + 0.13);
108 points[2].y = y + radius * 0.78 * sin(th + 0.13);
110 points[3].x = x + radius * 0.72 * cos(th + 0.13);
111 points[3].y = y + radius * 0.72 * sin(th + 0.13);
113 points[4].x = x + radius * 0.7 * cos(th + 0.08);
114 points[4].y = y + radius * 0.7 * sin(th + 0.08);
116 points[5].x = x + radius * 0.72 * cos(th + 0.03);
117 points[5].y = y + radius * 0.72 * sin(th + 0.03);
119 points[6] = points[0];
121 XDrawLines (dpy, d, disc->gc, points, 7, CoordModeOrigin);
125 th = th2 + (2 * M_PI * 0.16666);
127 points[0].x = x + radius * 0.78 * cos(th - 0.13);
128 points[0].y = y + radius * 0.78 * sin(th - 0.13);
130 points[1].x = x + radius * 0.8 * cos(th - 0.08);
131 points[1].y = y + radius * 0.8 * sin(th - 0.08);
133 points[2].x = x + radius * 0.78 * cos(th - 0.03);
134 points[2].y = y + radius * 0.78 * sin(th - 0.03);
136 points[3].x = x + radius * 0.76 * cos(th - 0.03);
137 points[3].y = y + radius * 0.76 * sin(th - 0.03);
139 points[4].x = x + radius * 0.75 * cos(th - 0.08);
140 points[4].y = y + radius * 0.75 * sin(th - 0.08);
142 points[5].x = x + radius * 0.74 * cos(th - 0.03);
143 points[5].y = y + radius * 0.74 * sin(th - 0.03);
145 points[6].x = x + radius * 0.72 * cos(th - 0.03);
146 points[6].y = y + radius * 0.72 * sin(th - 0.03);
148 points[7].x = x + radius * 0.7 * cos(th - 0.08);
149 points[7].y = y + radius * 0.7 * sin(th - 0.08);
151 points[8].x = x + radius * 0.72 * cos(th - 0.13);
152 points[8].y = y + radius * 0.72 * sin(th - 0.13);
154 XDrawLines (dpy, d, disc->gc, points, 9, CoordModeOrigin);
158 points[0].x = x + radius * 0.78 * cos(th + 0.03);
159 points[0].y = y + radius * 0.78 * sin(th + 0.03);
161 points[1].x = x + radius * 0.8 * cos(th + 0.08);
162 points[1].y = y + radius * 0.8 * sin(th + 0.08);
164 points[2].x = x + radius * 0.78 * cos(th + 0.13);
165 points[2].y = y + radius * 0.78 * sin(th + 0.13);
167 points[3].x = x + radius * 0.76 * cos(th + 0.13);
168 points[3].y = y + radius * 0.76 * sin(th + 0.13);
170 points[4].x = x + radius * 0.75 * cos(th + 0.08);
171 points[4].y = y + radius * 0.75 * sin(th + 0.08);
173 points[5].x = x + radius * 0.74 * cos(th + 0.13);
174 points[5].y = y + radius * 0.74 * sin(th + 0.13);
176 points[6].x = x + radius * 0.72 * cos(th + 0.13);
177 points[6].y = y + radius * 0.72 * sin(th + 0.13);
179 points[7].x = x + radius * 0.7 * cos(th + 0.08);
180 points[7].y = y + radius * 0.7 * sin(th + 0.08);
182 points[8].x = x + radius * 0.72 * cos(th + 0.03);
183 points[8].y = y + radius * 0.72 * sin(th + 0.03);
185 XDrawLines (dpy, d, disc->gc, points, 9, CoordModeOrigin);
189 th = th2 + (2 * M_PI * 0.25);
191 points[0].x = x + radius * 0.7 * cos(th - 0.05);
192 points[0].y = y + radius * 0.7 * sin(th - 0.05);
194 points[1].x = x + radius * 0.8 * cos(th - 0.05);
195 points[1].y = y + radius * 0.8 * sin(th - 0.05);
197 points[2].x = x + radius * 0.7 * cos(th + 0.05);
198 points[2].y = y + radius * 0.7 * sin(th + 0.05);
200 points[3].x = x + radius * 0.8 * cos(th + 0.05);
201 points[3].y = y + radius * 0.8 * sin(th + 0.05);
203 XDrawLines (dpy, d, disc->gc, points, 4, CoordModeOrigin);
207 th = th2 + (2 * M_PI * 0.33333);
209 points[0].x = x + radius * 0.78 * cos(th - 0.05);
210 points[0].y = y + radius * 0.78 * sin(th - 0.05);
212 points[1].x = x + radius * 0.8 * cos(th);
213 points[1].y = y + radius * 0.8 * sin(th);
215 points[2].x = x + radius * 0.78 * cos(th + 0.05);
216 points[2].y = y + radius * 0.78 * sin(th + 0.05);
218 points[3].x = x + radius * 0.76 * cos(th + 0.05);
219 points[3].y = y + radius * 0.76 * sin(th + 0.05);
221 points[4].x = x + radius * 0.75 * cos(th);
222 points[4].y = y + radius * 0.75 * sin(th);
224 points[5].x = x + radius * 0.74 * cos(th + 0.05);
225 points[5].y = y + radius * 0.74 * sin(th + 0.05);
227 points[6].x = x + radius * 0.72 * cos(th + 0.05);
228 points[6].y = y + radius * 0.72 * sin(th + 0.05);
230 points[7].x = x + radius * 0.7 * cos(th);
231 points[7].y = y + radius * 0.7 * sin(th);
233 points[8].x = x + radius * 0.72 * cos(th - 0.05);
234 points[8].y = y + radius * 0.72 * sin(th - 0.05);
236 XDrawLines (dpy, d, disc->gc, points, 9, CoordModeOrigin);
240 th = th2 + (2 * M_PI * 0.41666);
242 points[0].x = x + radius * 0.78 * cos(th + 0.05);
243 points[0].y = y + radius * 0.78 * sin(th + 0.05);
245 points[1].x = x + radius * 0.8 * cos(th);
246 points[1].y = y + radius * 0.8 * sin(th);
248 points[2].x = x + radius * 0.78 * cos(th - 0.05);
249 points[2].y = y + radius * 0.78 * sin(th - 0.05);
251 points[3].x = x + radius * 0.72 * cos(th - 0.05);
252 points[3].y = y + radius * 0.72 * sin(th - 0.05);
254 points[4].x = x + radius * 0.7 * cos(th);
255 points[4].y = y + radius * 0.7 * sin(th);
257 points[5].x = x + radius * 0.72 * cos(th + 0.05);
258 points[5].y = y + radius * 0.72 * sin(th + 0.05);
260 points[6].x = x + radius * 0.74 * cos(th + 0.05);
261 points[6].y = y + radius * 0.74 * sin(th + 0.05);
263 points[7].x = x + radius * 0.76 * cos(th);
264 points[7].y = y + radius * 0.76 * sin(th);
266 points[8].x = x + radius * 0.74 * cos(th - 0.05);
267 points[8].y = y + radius * 0.74 * sin(th - 0.05);
269 XDrawLines (dpy, d, disc->gc, points, 9, CoordModeOrigin);
274 th = th2 + (2 * M_PI * 0.5);
276 points[0].x = x + radius * 0.8 * cos(th + 0.05);
277 points[0].y = y + radius * 0.8 * sin(th + 0.05);
279 points[1].x = x + radius * 0.8 * cos(th - 0.05);
280 points[1].y = y + radius * 0.8 * sin(th - 0.05);
282 points[2].x = x + radius * 0.75 * cos(th - 0.05);
283 points[2].y = y + radius * 0.75 * sin(th - 0.05);
285 points[3].x = x + radius * 0.75 * cos(th + 0.025);
286 points[3].y = y + radius * 0.75 * sin(th + 0.025);
288 points[4].x = x + radius * 0.75 * cos(th - 0.05);
289 points[4].y = y + radius * 0.75 * sin(th - 0.05);
291 points[5].x = x + radius * 0.7 * cos(th - 0.05);
292 points[5].y = y + radius * 0.7 * sin(th - 0.05);
294 points[6].x = x + radius * 0.7 * cos(th + 0.05);
295 points[6].y = y + radius * 0.7 * sin(th + 0.05);
297 XDrawLines (dpy, d, disc->gc, points, 7, CoordModeOrigin);
301 th = th2 + (2 * M_PI * 0.58333);
303 points[0].x = x + radius * 0.77 * cos(th - 0.06);
304 points[0].y = y + radius * 0.77 * sin(th - 0.06);
306 points[1].x = x + radius * 0.8 * cos(th - 0.03);
307 points[1].y = y + radius * 0.8 * sin(th - 0.03);
309 points[2].x = x + radius * 0.7 * cos(th - 0.03);
310 points[2].y = y + radius * 0.7 * sin(th - 0.03);
312 XDrawLines (dpy, d, disc->gc, points, 3, CoordModeOrigin);
316 points[0].x = x + radius * 0.78 * cos(th + 0.02);
317 points[0].y = y + radius * 0.78 * sin(th + 0.02);
319 points[1].x = x + radius * 0.8 * cos(th + 0.07);
320 points[1].y = y + radius * 0.8 * sin(th + 0.07);
322 points[2].x = x + radius * 0.78 * cos(th + 0.11);
323 points[2].y = y + radius * 0.78 * sin(th + 0.11);
325 points[3].x = x + radius * 0.76 * cos(th + 0.11);
326 points[3].y = y + radius * 0.76 * sin(th + 0.11);
328 points[4].x = x + radius * 0.74 * cos(th + 0.02);
329 points[4].y = y + radius * 0.74 * sin(th + 0.02);
331 points[5].x = x + radius * 0.71 * cos(th + 0.03);
332 points[5].y = y + radius * 0.71 * sin(th + 0.03);
334 points[6].x = x + radius * 0.7 * cos(th + 0.03);
335 points[6].y = y + radius * 0.7 * sin(th + 0.03);
337 points[7].x = x + radius * 0.7 * cos(th + 0.13);
338 points[7].y = y + radius * 0.7 * sin(th + 0.13);
340 XDrawLines (dpy, d, disc->gc, points, 8, CoordModeOrigin);
344 th = th2 + (2 * M_PI * 0.66666);
346 points[0].x = x + radius * 0.77 * cos(th - 0.06);
347 points[0].y = y + radius * 0.77 * sin(th - 0.06);
349 points[1].x = x + radius * 0.8 * cos(th - 0.03);
350 points[1].y = y + radius * 0.8 * sin(th - 0.03);
352 points[2].x = x + radius * 0.7 * cos(th - 0.03);
353 points[2].y = y + radius * 0.7 * sin(th - 0.03);
355 XDrawLines (dpy, d, disc->gc, points, 3, CoordModeOrigin);
359 points[0].x = x + radius * 0.8 * cos(th + 0.11);
360 points[0].y = y + radius * 0.8 * sin(th + 0.11);
362 points[1].x = x + radius * 0.8 * cos(th + 0.02);
363 points[1].y = y + radius * 0.8 * sin(th + 0.02);
365 points[2].x = x + radius * 0.76 * cos(th + 0.02);
366 points[2].y = y + radius * 0.76 * sin(th + 0.02);
368 points[3].x = x + radius * 0.77 * cos(th + 0.06);
369 points[3].y = y + radius * 0.77 * sin(th + 0.06);
371 points[4].x = x + radius * 0.76 * cos(th + 0.10);
372 points[4].y = y + radius * 0.76 * sin(th + 0.10);
374 points[5].x = x + radius * 0.73 * cos(th + 0.11);
375 points[5].y = y + radius * 0.73 * sin(th + 0.11);
377 points[6].x = x + radius * 0.72 * cos(th + 0.10);
378 points[6].y = y + radius * 0.72 * sin(th + 0.10);
380 points[7].x = x + radius * 0.7 * cos(th + 0.06);
381 points[7].y = y + radius * 0.7 * sin(th + 0.06);
383 points[8].x = x + radius * 0.72 * cos(th + 0.02);
384 points[8].y = y + radius * 0.72 * sin(th + 0.02);
386 XDrawLines (dpy, d, disc->gc, points, 9, CoordModeOrigin);
390 th = th2 + (2 * M_PI * 0.75);
392 points[0].x = x + radius * 0.78 * cos(th + 0.05);
393 points[0].y = y + radius * 0.78 * sin(th + 0.05);
395 points[1].x = x + radius * 0.8 * cos(th);
396 points[1].y = y + radius * 0.8 * sin(th);
398 points[2].x = x + radius * 0.78 * cos(th - 0.05);
399 points[2].y = y + radius * 0.78 * sin(th - 0.05);
401 points[3].x = x + radius * 0.76 * cos(th - 0.05);
402 points[3].y = y + radius * 0.76 * sin(th - 0.05);
404 points[4].x = x + radius * 0.74 * cos(th + 0.05);
405 points[4].y = y + radius * 0.74 * sin(th + 0.05);
407 points[5].x = x + radius * 0.72 * cos(th + 0.05);
408 points[5].y = y + radius * 0.72 * sin(th + 0.05);
410 points[6].x = x + radius * 0.7 * cos(th);
411 points[6].y = y + radius * 0.7 * sin(th);
413 points[7].x = x + radius * 0.72 * cos(th - 0.05);
414 points[7].y = y + radius * 0.72 * sin(th - 0.05);
416 XDrawLines (dpy, d, disc->gc, points, 8, CoordModeOrigin);
420 th = th2 + (2 * M_PI * 0.83333);
422 points[0].x = x + radius * 0.78 * cos(th - 0.13);
423 points[0].y = y + radius * 0.78 * sin(th - 0.13);
425 points[1].x = x + radius * 0.8 * cos(th - 0.08);
426 points[1].y = y + radius * 0.8 * sin(th - 0.08);
428 points[2].x = x + radius * 0.78 * cos(th - 0.03);
429 points[2].y = y + radius * 0.78 * sin(th - 0.03);
431 points[3].x = x + radius * 0.76 * cos(th - 0.03);
432 points[3].y = y + radius * 0.76 * sin(th - 0.03);
434 points[4].x = x + radius * 0.74 * cos(th - 0.12);
435 points[4].y = y + radius * 0.74 * sin(th - 0.12);
437 points[5].x = x + radius * 0.71 * cos(th - 0.13);
438 points[5].y = y + radius * 0.71 * sin(th - 0.13);
440 points[6].x = x + radius * 0.7 * cos(th - 0.13);
441 points[6].y = y + radius * 0.7 * sin(th - 0.13);
443 points[7].x = x + radius * 0.7 * cos(th - 0.02);
444 points[7].y = y + radius * 0.7 * sin(th - 0.02);
446 XDrawLines (dpy, d, disc->gc, points, 8, CoordModeOrigin);
450 points[0].x = x + radius * 0.77 * cos(th + 0.03);
451 points[0].y = y + radius * 0.77 * sin(th + 0.03);
453 points[1].x = x + radius * 0.8 * cos(th + 0.06);
454 points[1].y = y + radius * 0.8 * sin(th + 0.06);
456 points[2].x = x + radius * 0.7 * cos(th + 0.06);
457 points[2].y = y + radius * 0.7 * sin(th + 0.06);
459 XDrawLines (dpy, d, disc->gc, points, 3, CoordModeOrigin);
463 th = th2 + (2 * M_PI * 0.91666);
465 points[0].x = x + radius * 0.78 * cos(th - 0.13);
466 points[0].y = y + radius * 0.78 * sin(th - 0.13);
468 points[1].x = x + radius * 0.8 * cos(th - 0.08);
469 points[1].y = y + radius * 0.8 * sin(th - 0.08);
471 points[2].x = x + radius * 0.78 * cos(th - 0.03);
472 points[2].y = y + radius * 0.78 * sin(th - 0.03);
474 points[3].x = x + radius * 0.76 * cos(th - 0.03);
475 points[3].y = y + radius * 0.76 * sin(th - 0.03);
477 points[4].x = x + radius * 0.74 * cos(th - 0.12);
478 points[4].y = y + radius * 0.74 * sin(th - 0.12);
480 points[5].x = x + radius * 0.71 * cos(th - 0.13);
481 points[5].y = y + radius * 0.71 * sin(th - 0.13);
483 points[6].x = x + radius * 0.7 * cos(th - 0.13);
484 points[6].y = y + radius * 0.7 * sin(th - 0.13);
486 points[7].x = x + radius * 0.7 * cos(th - 0.02);
487 points[7].y = y + radius * 0.7 * sin(th - 0.02);
489 XDrawLines (dpy, d, disc->gc, points, 8, CoordModeOrigin);
493 points[0].x = x + radius * 0.69 * cos(th + 0.09);
494 points[0].y = y + radius * 0.69 * sin(th + 0.09);
496 points[1].x = x + radius * 0.8 * cos(th + 0.09);
497 points[1].y = y + radius * 0.8 * sin(th + 0.09);
499 points[2].x = x + radius * 0.72 * cos(th + 0.01);
500 points[2].y = y + radius * 0.72 * sin(th + 0.01);
502 points[3].x = x + radius * 0.72 * cos(th + 0.13);
503 points[3].y = y + radius * 0.72 * sin(th + 0.13);
505 XDrawLines (dpy, d, disc->gc, points, 4, CoordModeOrigin);
510 draw_ticks (Display *dpy, Drawable d, struct disc *disc,
511 int x, int y, int radius)
515 double tick = (M_PI * 2) / 72;
517 for (i = 0; i < 72; i++)
519 int radius2 = radius;
520 double th = (i * tick) + (2 * M_PI * (disc->theta / ((double) 360*64)));
523 radius2 -= radius / 16;
525 radius2 -= radius / 8;
527 segs[i].x1 = x + radius * cos(th);
528 segs[i].y1 = y + radius * sin(th);
529 segs[i].x2 = x + radius2 * cos(th);
530 segs[i].y2 = y + radius2 * sin(th);
532 XDrawSegments (dpy, d, disc->gc, segs, countof(segs));
534 draw_letters (dpy, d, disc, x, y, radius);
539 draw_thin_arrow (Display *dpy, Drawable d, struct disc *disc,
540 int x, int y, int radius)
545 double tick = ((M_PI * 2) / 72) * 2;
548 radius2 = radius - (radius / 8) * 3;
550 th = 2 * M_PI * (disc->theta / ((double) 360*64));
552 points[0].x = x + radius * cos(th); /* tip */
553 points[0].y = y + radius * sin(th);
555 points[1].x = x + radius2 * cos(th - tick); /* tip left */
556 points[1].y = y + radius2 * sin(th - tick);
558 points[2].x = x + radius2 * cos(th + tick); /* tip right */
559 points[2].y = y + radius2 * sin(th + tick);
561 XDrawLine (dpy, d, disc->gc,
562 (int) (x + radius2 * cos(th)),
563 (int) (y + radius2 * sin(th)),
564 (int) (x + -radius * cos(th)),
565 (int) (y + -radius * sin(th)));
567 XFillPolygon (dpy, d, disc->gc, points, 3, Convex, CoordModeOrigin);
572 draw_thick_arrow (Display *dpy, Drawable d, struct disc *disc,
573 int x, int y, int radius)
577 int radius2, radius3;
578 double tick = ((M_PI * 2) / 72) * 2;
581 radius2 = radius - (radius / 8) * 3;
582 radius3 = radius - (radius / 8) * 2;
583 th = 2 * M_PI * (disc->theta / ((double) 360*64));
585 points[0].x = x + radius * cos(th); /* tip */
586 points[0].y = y + radius * sin(th);
588 points[1].x = x + radius2 * cos(th - tick); /* tip left */
589 points[1].y = y + radius2 * sin(th - tick);
591 points[2].x = x + radius2 * cos(th + tick); /* tip right */
592 points[2].y = y + radius2 * sin(th + tick);
594 points[3] = points[0];
596 XDrawLines (dpy, d, disc->gc, points, 4, CoordModeOrigin);
598 points[0].x = x + radius2 * cos(th - tick/2); /* top left */
599 points[0].y = y + radius2 * sin(th - tick/2);
601 points[1].x = x + -radius2 * cos(th + tick/2); /* bottom left */
602 points[1].y = y + -radius2 * sin(th + tick/2);
604 points[2].x = x + -radius3 * cos(th); /* bottom */
605 points[2].y = y + -radius3 * sin(th);
607 points[3].x = x + -radius * cos(th); /* bottom spike */
608 points[3].y = y + -radius * sin(th);
610 points[4] = points[2]; /* return */
612 points[5].x = x + -radius2 * cos(th - tick/2); /* bottom right */
613 points[5].y = y + -radius2 * sin(th - tick/2);
615 points[6].x = x + radius2 * cos(th + tick/2); /* top right */
616 points[6].y = y + radius2 * sin(th + tick/2);
618 XDrawLines (dpy, d, disc->gc, points, 7, CoordModeOrigin);
624 roll_disc (struct disc *disc)
626 double th = disc->theta;
628 th = -(th + disc->velocity);
630 th = (th + disc->velocity);
637 disc->theta = (disc->theta > 0 ? th : -th);
639 disc->velocity += disc->acceleration;
641 if (disc->velocity > disc->limit ||
642 disc->velocity < -disc->limit)
643 disc->acceleration = -disc->acceleration;
645 /* Alter direction of rotational acceleration randomly. */
646 if (! (random() % 120))
647 disc->acceleration = -disc->acceleration;
649 /* Change acceleration very occasionally. */
650 if (! (random() % 200))
653 disc->acceleration *= 1.2;
655 disc->acceleration *= 0.8;
661 init_spin (struct disc *disc)
664 disc->theta = RAND(360*64);
665 disc->velocity = RAND(16) * RANDSIGN();
666 disc->acceleration = RAND(16) * RANDSIGN();
671 draw_compass (Display *dpy, Drawable d, struct disc **discs,
672 int x, int y, int radius)
677 discs[i]->draw (dpy, d, discs[i], x, y, radius);
678 roll_disc (discs[i]);
684 draw_pointer (Display *dpy, Drawable d, GC ptr_gc, GC dot_gc,
685 int x, int y, int radius)
688 int size = radius * 0.1;
692 points[0].x = x - size;
693 points[0].y = y - radius - size;
695 points[1].x = x + size;
696 points[1].y = y - radius - size;
699 points[2].y = y - radius;
701 XFillPolygon (dpy, d, ptr_gc, points, 3, Convex, CoordModeOrigin);
705 points[0].x = x - (radius * 0.85);
706 points[0].y = y - (radius * 0.8);
708 points[1].x = x - (radius * 1.1);
709 points[1].y = y - (radius * 0.55);
711 points[2].x = x - (radius * 0.6);
712 points[2].y = y - (radius * 0.65);
714 XFillPolygon (dpy, d, ptr_gc, points, 3, Convex, CoordModeOrigin);
718 points[0].x = x - (radius * 1.05);
721 points[1].x = x - (radius * 1.1);
722 points[1].y = y - (radius * 0.025);
724 points[2].x = x - (radius * 1.1);
725 points[2].y = y + (radius * 0.025);
727 XFillPolygon (dpy, d, dot_gc, points, 3, Convex, CoordModeOrigin);
731 points[0].x = x + (radius * 1.05);
734 points[1].x = x + (radius * 1.1);
735 points[1].y = y - (radius * 0.025);
737 points[2].x = x + (radius * 1.1);
738 points[2].y = y + (radius * 0.025);
740 XFillPolygon (dpy, d, dot_gc, points, 3, Convex, CoordModeOrigin);
745 points[0].y = y + (radius * 1.05);
747 points[1].x = x - (radius * 0.025);
748 points[1].y = y + (radius * 1.1);
750 points[2].x = x + (radius * 0.025);
751 points[2].y = y + (radius * 1.1);
753 XFillPolygon (dpy, d, dot_gc, points, 3, Convex, CoordModeOrigin);
757 points[0].x = x + (radius * 0.74);
758 points[0].y = y + (radius * 0.74);
760 points[1].x = x + (radius * 0.78);
761 points[1].y = y + (radius * 0.75);
763 points[2].x = x + (radius * 0.75);
764 points[2].y = y + (radius * 0.78);
766 XFillPolygon (dpy, d, dot_gc, points, 3, Convex, CoordModeOrigin);
770 points[0].x = x + (radius * 0.74);
771 points[0].y = y - (radius * 0.74);
773 points[1].x = x + (radius * 0.78);
774 points[1].y = y - (radius * 0.75);
776 points[2].x = x + (radius * 0.75);
777 points[2].y = y - (radius * 0.78);
779 XFillPolygon (dpy, d, dot_gc, points, 3, Convex, CoordModeOrigin);
783 points[0].x = x - (radius * 0.74);
784 points[0].y = y + (radius * 0.74);
786 points[1].x = x - (radius * 0.78);
787 points[1].y = y + (radius * 0.75);
789 points[2].x = x - (radius * 0.75);
790 points[2].y = y + (radius * 0.78);
792 XFillPolygon (dpy, d, dot_gc, points, 3, Convex, CoordModeOrigin);
796 char *progclass = "Compass";
798 char *defaults [] = {
799 ".background: #000000",
800 ".foreground: #DDFFFF",
801 "*arrow1Foreground: #FFF66A",
802 "*arrow2Foreground: #F7D64A",
803 "*pointerForeground: #FF0000",
805 "*doubleBuffer: True",
806 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
808 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
812 XrmOptionDescRec options [] = {
813 { "-delay", ".delay", XrmoptionSepArg, 0 },
814 { "-db", ".doubleBuffer", XrmoptionNoArg, "True" },
815 { "-no-db", ".doubleBuffer", XrmoptionNoArg, "False" },
820 screenhack (Display *dpy, Window window)
823 int delay = get_integer_resource ("delay", "Integer");
824 Bool dbuf = get_boolean_resource ("doubleBuffer", "Boolean");
825 struct disc *discs[4];
826 int x, y, size, size2;
829 XWindowAttributes xgwa;
830 Pixmap b=0, ba=0, bb=0; /* double-buffer to reduce flicker */
831 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
832 XdbeBackBuffer backb = 0;
833 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
835 XGetWindowAttributes (dpy, window, &xgwa);
836 size2 = MIN(xgwa.width, xgwa.height);
838 if (size2 > 600) size2 = 600;
840 size = (size2 / 2) * 0.8;
847 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
848 b = backb = xdbe_get_backbuffer (dpy, window, XdbeUndefined);
849 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
855 ba = XCreatePixmap (dpy, window, size2, size2, xgwa.depth);
856 bb = XCreatePixmap (dpy, window, size2, size2, xgwa.depth);
865 discs[0] = (struct disc *) calloc (1, sizeof (struct disc));
866 discs[1] = (struct disc *) calloc (1, sizeof (struct disc));
867 discs[2] = (struct disc *) calloc (1, sizeof (struct disc));
870 gcv.foreground = get_pixel_resource ("foreground", "Foreground",
872 gcv.line_width = MAX(2, (size/60));
873 gcv.join_style = JoinBevel;
874 discs[0]->draw = draw_ticks;
875 discs[0]->gc = XCreateGC (dpy, b, GCForeground|GCLineWidth|GCJoinStyle,
877 init_spin (discs[0]);
879 gcv.foreground = get_pixel_resource ("arrow2Foreground", "Foreground",
881 gcv.line_width = MAX(4, (size / 30));
882 discs[1]->draw = draw_thick_arrow;
883 discs[1]->gc = XCreateGC (dpy, b, GCForeground|GCLineWidth, &gcv);
884 init_spin (discs[1]);
886 gcv.foreground = get_pixel_resource ("arrow1Foreground", "Foreground",
888 gcv.line_width = MAX(4, (size / 30));
889 discs[2]->draw = draw_thin_arrow;
890 discs[2]->gc = XCreateGC (dpy, b, GCForeground|GCLineWidth, &gcv);
891 init_spin (discs[2]);
893 gcv.foreground = get_pixel_resource ("pointerForeground", "Foreground",
895 ptr_gc = XCreateGC (dpy, b, GCForeground|GCLineWidth, &gcv);
897 gcv.foreground = get_pixel_resource ("background", "Background",
899 erase_gc = XCreateGC (dpy, b, GCForeground, &gcv);
901 if (ba) XFillRectangle (dpy, ba, erase_gc, 0, 0, size2, size2);
902 if (bb) XFillRectangle (dpy, bb, erase_gc, 0, 0, size2, size2);
906 XFillRectangle (dpy, b, erase_gc, 0, 0, xgwa.width, xgwa.height);
908 draw_compass (dpy, b, discs, x, y, size);
909 draw_pointer (dpy, b, ptr_gc, discs[0]->gc, x, y, size);
911 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
914 XdbeSwapInfo info[1];
915 info[0].swap_window = window;
916 info[0].swap_action = XdbeUndefined;
917 XdbeSwapBuffers (dpy, info, 1);
920 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
923 XCopyArea (dpy, b, window, erase_gc, 0, 0,
927 b = (b == ba ? bb : ba);
931 screenhack_handle_events (dpy);