source: trunk/third/xscreensaver/hacks/compass.c @ 20148

Revision 20148, 26.2 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20147, which included commits to RCS files with non-trunk default branches.
Line 
1/* xscreensaver, Copyright (c) 1999 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 <math.h>
13#include "screenhack.h"
14
15#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
16# include "xdbe.h"
17#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
18
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)
25
26struct disc {
27  int theta;            /* 0 - 360*64 */
28  int velocity;
29  int acceleration;
30  int limit;
31  GC gc;
32  void (*draw) (Display *, Drawable, struct disc *,
33                int x, int y, int radius);
34};
35
36
37static void
38draw_letters (Display *dpy, Drawable d, struct disc *disc,
39              int x, int y, int radius)
40{
41  XPoint points[50];
42  double th2 = 2 * M_PI * (disc->theta / ((double) 360*64));
43  double th;
44
45  /* W */
46
47  th = th2;
48
49  points[0].x = x + radius * 0.8 * cos(th - 0.07);
50  points[0].y = y + radius * 0.8 * sin(th - 0.07);
51
52  points[1].x = x + radius * 0.7 * cos(th - 0.05);
53  points[1].y = y + radius * 0.7 * sin(th - 0.05);
54
55  points[2].x = x + radius * 0.78 * cos(th);
56  points[2].y = y + radius * 0.78 * sin(th);
57
58  points[3].x = x + radius * 0.7 * cos(th + 0.05);
59  points[3].y = y + radius * 0.7 * sin(th + 0.05);
60
61  points[4].x = x + radius * 0.8 * cos(th + 0.07);
62  points[4].y = y + radius * 0.8 * sin(th + 0.07);
63
64  XDrawLines (dpy, d, disc->gc, points, 5, CoordModeOrigin);
65
66  /* 30 (1) */
67
68  th = th2 + (2 * M_PI * 0.08333);
69
70  points[0].x = x + radius * 0.78 * cos(th - 0.13);
71  points[0].y = y + radius * 0.78 * sin(th - 0.13);
72
73  points[1].x = x + radius * 0.8  * cos(th - 0.08);
74  points[1].y = y + radius * 0.8  * sin(th - 0.08);
75
76  points[2].x = x + radius * 0.78 * cos(th - 0.03);
77  points[2].y = y + radius * 0.78 * sin(th - 0.03);
78
79  points[3].x = x + radius * 0.76 * cos(th - 0.03);
80  points[3].y = y + radius * 0.76 * sin(th - 0.03);
81
82  points[4].x = x + radius * 0.75 * cos(th - 0.08);
83  points[4].y = y + radius * 0.75 * sin(th - 0.08);
84
85  points[5].x = x + radius * 0.74 * cos(th - 0.03);
86  points[5].y = y + radius * 0.74 * sin(th - 0.03);
87
88  points[6].x = x + radius * 0.72 * cos(th - 0.03);
89  points[6].y = y + radius * 0.72 * sin(th - 0.03);
90
91  points[7].x = x + radius * 0.7  * cos(th - 0.08);
92  points[7].y = y + radius * 0.7  * sin(th - 0.08);
93
94  points[8].x = x + radius * 0.72  * cos(th - 0.13);
95  points[8].y = y + radius * 0.72  * sin(th - 0.13);
96
97  XDrawLines (dpy, d, disc->gc, points, 9, CoordModeOrigin);
98
99  /* 30 (2) */
100
101  points[0].x = x + radius * 0.78 * cos(th + 0.03);
102  points[0].y = y + radius * 0.78 * sin(th + 0.03);
103
104  points[1].x = x + radius * 0.8  * cos(th + 0.08);
105  points[1].y = y + radius * 0.8  * sin(th + 0.08);
106
107  points[2].x = x + radius * 0.78 * cos(th + 0.13);
108  points[2].y = y + radius * 0.78 * sin(th + 0.13);
109
110  points[3].x = x + radius * 0.72 * cos(th + 0.13);
111  points[3].y = y + radius * 0.72 * sin(th + 0.13);
112
113  points[4].x = x + radius * 0.7  * cos(th + 0.08);
114  points[4].y = y + radius * 0.7  * sin(th + 0.08);
115
116  points[5].x = x + radius * 0.72  * cos(th + 0.03);
117  points[5].y = y + radius * 0.72  * sin(th + 0.03);
118
119  points[6] = points[0];
120
121  XDrawLines (dpy, d, disc->gc, points, 7, CoordModeOrigin);
122
123  /* 33 (1) */
124
125  th = th2 + (2 * M_PI * 0.16666);
126
127  points[0].x = x + radius * 0.78 * cos(th - 0.13);
128  points[0].y = y + radius * 0.78 * sin(th - 0.13);
129
130  points[1].x = x + radius * 0.8  * cos(th - 0.08);
131  points[1].y = y + radius * 0.8  * sin(th - 0.08);
132
133  points[2].x = x + radius * 0.78 * cos(th - 0.03);
134  points[2].y = y + radius * 0.78 * sin(th - 0.03);
135
136  points[3].x = x + radius * 0.76 * cos(th - 0.03);
137  points[3].y = y + radius * 0.76 * sin(th - 0.03);
138
139  points[4].x = x + radius * 0.75 * cos(th - 0.08);
140  points[4].y = y + radius * 0.75 * sin(th - 0.08);
141
142  points[5].x = x + radius * 0.74 * cos(th - 0.03);
143  points[5].y = y + radius * 0.74 * sin(th - 0.03);
144
145  points[6].x = x + radius * 0.72 * cos(th - 0.03);
146  points[6].y = y + radius * 0.72 * sin(th - 0.03);
147
148  points[7].x = x + radius * 0.7  * cos(th - 0.08);
149  points[7].y = y + radius * 0.7  * sin(th - 0.08);
150
151  points[8].x = x + radius * 0.72  * cos(th - 0.13);
152  points[8].y = y + radius * 0.72  * sin(th - 0.13);
153
154  XDrawLines (dpy, d, disc->gc, points, 9, CoordModeOrigin);
155
156  /* 33 (2) */
157
158  points[0].x = x + radius * 0.78 * cos(th + 0.03);
159  points[0].y = y + radius * 0.78 * sin(th + 0.03);
160
161  points[1].x = x + radius * 0.8  * cos(th + 0.08);
162  points[1].y = y + radius * 0.8  * sin(th + 0.08);
163
164  points[2].x = x + radius * 0.78 * cos(th + 0.13);
165  points[2].y = y + radius * 0.78 * sin(th + 0.13);
166
167  points[3].x = x + radius * 0.76 * cos(th + 0.13);
168  points[3].y = y + radius * 0.76 * sin(th + 0.13);
169
170  points[4].x = x + radius * 0.75 * cos(th + 0.08);
171  points[4].y = y + radius * 0.75 * sin(th + 0.08);
172
173  points[5].x = x + radius * 0.74 * cos(th + 0.13);
174  points[5].y = y + radius * 0.74 * sin(th + 0.13);
175
176  points[6].x = x + radius * 0.72 * cos(th + 0.13);
177  points[6].y = y + radius * 0.72 * sin(th + 0.13);
178
179  points[7].x = x + radius * 0.7  * cos(th + 0.08);
180  points[7].y = y + radius * 0.7  * sin(th + 0.08);
181
182  points[8].x = x + radius * 0.72  * cos(th + 0.03);
183  points[8].y = y + radius * 0.72  * sin(th + 0.03);
184
185  XDrawLines (dpy, d, disc->gc, points, 9, CoordModeOrigin);
186
187  /* N */
188
189  th = th2 + (2 * M_PI * 0.25);
190
191  points[0].x = x + radius * 0.7 * cos(th - 0.05);
192  points[0].y = y + radius * 0.7 * sin(th - 0.05);
193
194  points[1].x = x + radius * 0.8 * cos(th - 0.05);
195  points[1].y = y + radius * 0.8 * sin(th - 0.05);
196
197  points[2].x = x + radius * 0.7 * cos(th + 0.05);
198  points[2].y = y + radius * 0.7 * sin(th + 0.05);
199
200  points[3].x = x + radius * 0.8 * cos(th + 0.05);
201  points[3].y = y + radius * 0.8 * sin(th + 0.05);
202
203  XDrawLines (dpy, d, disc->gc, points, 4, CoordModeOrigin);
204
205  /* 3 */
206
207  th = th2 + (2 * M_PI * 0.33333);
208
209  points[0].x = x + radius * 0.78 * cos(th - 0.05);
210  points[0].y = y + radius * 0.78 * sin(th - 0.05);
211
212  points[1].x = x + radius * 0.8  * cos(th);
213  points[1].y = y + radius * 0.8  * sin(th);
214
215  points[2].x = x + radius * 0.78 * cos(th + 0.05);
216  points[2].y = y + radius * 0.78 * sin(th + 0.05);
217
218  points[3].x = x + radius * 0.76 * cos(th + 0.05);
219  points[3].y = y + radius * 0.76 * sin(th + 0.05);
220
221  points[4].x = x + radius * 0.75 * cos(th);
222  points[4].y = y + radius * 0.75 * sin(th);
223
224  points[5].x = x + radius * 0.74 * cos(th + 0.05);
225  points[5].y = y + radius * 0.74 * sin(th + 0.05);
226
227  points[6].x = x + radius * 0.72 * cos(th + 0.05);
228  points[6].y = y + radius * 0.72 * sin(th + 0.05);
229
230  points[7].x = x + radius * 0.7  * cos(th);
231  points[7].y = y + radius * 0.7  * sin(th);
232
233  points[8].x = x + radius * 0.72  * cos(th - 0.05);
234  points[8].y = y + radius * 0.72  * sin(th - 0.05);
235
236  XDrawLines (dpy, d, disc->gc, points, 9, CoordModeOrigin);
237
238  /* 6 */
239
240  th = th2 + (2 * M_PI * 0.41666);
241
242  points[0].x = x + radius * 0.78 * cos(th + 0.05);
243  points[0].y = y + radius * 0.78 * sin(th + 0.05);
244
245  points[1].x = x + radius * 0.8  * cos(th);
246  points[1].y = y + radius * 0.8  * sin(th);
247
248  points[2].x = x + radius * 0.78 * cos(th - 0.05);
249  points[2].y = y + radius * 0.78 * sin(th - 0.05);
250
251  points[3].x = x + radius * 0.72 * cos(th - 0.05);
252  points[3].y = y + radius * 0.72 * sin(th - 0.05);
253
254  points[4].x = x + radius * 0.7  * cos(th);
255  points[4].y = y + radius * 0.7  * sin(th);
256
257  points[5].x = x + radius * 0.72 * cos(th + 0.05);
258  points[5].y = y + radius * 0.72 * sin(th + 0.05);
259
260  points[6].x = x + radius * 0.74 * cos(th + 0.05);
261  points[6].y = y + radius * 0.74 * sin(th + 0.05);
262
263  points[7].x = x + radius * 0.76 * cos(th);
264  points[7].y = y + radius * 0.76 * sin(th);
265
266  points[8].x = x + radius * 0.74 * cos(th - 0.05);
267  points[8].y = y + radius * 0.74 * sin(th - 0.05);
268
269  XDrawLines (dpy, d, disc->gc, points, 9, CoordModeOrigin);
270
271
272  /* E */
273
274  th = th2 + (2 * M_PI * 0.5);
275
276  points[0].x = x + radius * 0.8 * cos(th + 0.05);
277  points[0].y = y + radius * 0.8 * sin(th + 0.05);
278
279  points[1].x = x + radius * 0.8 * cos(th - 0.05);
280  points[1].y = y + radius * 0.8 * sin(th - 0.05);
281
282  points[2].x = x + radius * 0.75 * cos(th - 0.05);
283  points[2].y = y + radius * 0.75 * sin(th - 0.05);
284
285  points[3].x = x + radius * 0.75 * cos(th + 0.025);
286  points[3].y = y + radius * 0.75 * sin(th + 0.025);
287
288  points[4].x = x + radius * 0.75 * cos(th - 0.05);
289  points[4].y = y + radius * 0.75 * sin(th - 0.05);
290
291  points[5].x = x + radius * 0.7 * cos(th - 0.05);
292  points[5].y = y + radius * 0.7 * sin(th - 0.05);
293
294  points[6].x = x + radius * 0.7 * cos(th + 0.05);
295  points[6].y = y + radius * 0.7 * sin(th + 0.05);
296
297  XDrawLines (dpy, d, disc->gc, points, 7, CoordModeOrigin);
298
299  /* 12 (1) */
300
301  th = th2 + (2 * M_PI * 0.58333);
302
303  points[0].x = x + radius * 0.77 * cos(th - 0.06);
304  points[0].y = y + radius * 0.77 * sin(th - 0.06);
305
306  points[1].x = x + radius * 0.8  * cos(th - 0.03);
307  points[1].y = y + radius * 0.8  * sin(th - 0.03);
308
309  points[2].x = x + radius * 0.7  * cos(th - 0.03);
310  points[2].y = y + radius * 0.7  * sin(th - 0.03);
311
312  XDrawLines (dpy, d, disc->gc, points, 3, CoordModeOrigin);
313
314  /* 12 (2) */
315
316  points[0].x = x + radius * 0.78 * cos(th + 0.02);
317  points[0].y = y + radius * 0.78 * sin(th + 0.02);
318
319  points[1].x = x + radius * 0.8  * cos(th + 0.07);
320  points[1].y = y + radius * 0.8  * sin(th + 0.07);
321
322  points[2].x = x + radius * 0.78 * cos(th + 0.11);
323  points[2].y = y + radius * 0.78 * sin(th + 0.11);
324
325  points[3].x = x + radius * 0.76 * cos(th + 0.11);
326  points[3].y = y + radius * 0.76 * sin(th + 0.11);
327
328  points[4].x = x + radius * 0.74 * cos(th + 0.02);
329  points[4].y = y + radius * 0.74 * sin(th + 0.02);
330
331  points[5].x = x + radius * 0.71 * cos(th + 0.03);
332  points[5].y = y + radius * 0.71 * sin(th + 0.03);
333
334  points[6].x = x + radius * 0.7  * cos(th + 0.03);
335  points[6].y = y + radius * 0.7  * sin(th + 0.03);
336
337  points[7].x = x + radius * 0.7  * cos(th + 0.13);
338  points[7].y = y + radius * 0.7  * sin(th + 0.13);
339
340  XDrawLines (dpy, d, disc->gc, points, 8, CoordModeOrigin);
341
342  /* 15 (1) */
343
344  th = th2 + (2 * M_PI * 0.66666);
345
346  points[0].x = x + radius * 0.77 * cos(th - 0.06);
347  points[0].y = y + radius * 0.77 * sin(th - 0.06);
348
349  points[1].x = x + radius * 0.8  * cos(th - 0.03);
350  points[1].y = y + radius * 0.8  * sin(th - 0.03);
351
352  points[2].x = x + radius * 0.7  * cos(th - 0.03);
353  points[2].y = y + radius * 0.7  * sin(th - 0.03);
354
355  XDrawLines (dpy, d, disc->gc, points, 3, CoordModeOrigin);
356
357  /* 15 (2) */
358
359  points[0].x = x + radius * 0.8  * cos(th + 0.11);
360  points[0].y = y + radius * 0.8  * sin(th + 0.11);
361
362  points[1].x = x + radius * 0.8  * cos(th + 0.02);
363  points[1].y = y + radius * 0.8  * sin(th + 0.02);
364
365  points[2].x = x + radius * 0.76 * cos(th + 0.02);
366  points[2].y = y + radius * 0.76 * sin(th + 0.02);
367
368  points[3].x = x + radius * 0.77 * cos(th + 0.06);
369  points[3].y = y + radius * 0.77 * sin(th + 0.06);
370
371  points[4].x = x + radius * 0.76 * cos(th + 0.10);
372  points[4].y = y + radius * 0.76 * sin(th + 0.10);
373
374  points[5].x = x + radius * 0.73 * cos(th + 0.11);
375  points[5].y = y + radius * 0.73 * sin(th + 0.11);
376
377  points[6].x = x + radius * 0.72 * cos(th + 0.10);
378  points[6].y = y + radius * 0.72 * sin(th + 0.10);
379
380  points[7].x = x + radius * 0.7  * cos(th + 0.06);
381  points[7].y = y + radius * 0.7  * sin(th + 0.06);
382
383  points[8].x = x + radius * 0.72 * cos(th + 0.02);
384  points[8].y = y + radius * 0.72 * sin(th + 0.02);
385
386  XDrawLines (dpy, d, disc->gc, points, 9, CoordModeOrigin);
387
388  /* S */
389
390  th = th2 + (2 * M_PI * 0.75);
391
392  points[0].x = x + radius * 0.78 * cos(th + 0.05);
393  points[0].y = y + radius * 0.78 * sin(th + 0.05);
394
395  points[1].x = x + radius * 0.8  * cos(th);
396  points[1].y = y + radius * 0.8  * sin(th);
397
398  points[2].x = x + radius * 0.78 * cos(th - 0.05);
399  points[2].y = y + radius * 0.78 * sin(th - 0.05);
400
401  points[3].x = x + radius * 0.76 * cos(th - 0.05);
402  points[3].y = y + radius * 0.76 * sin(th - 0.05);
403
404  points[4].x = x + radius * 0.74 * cos(th + 0.05);
405  points[4].y = y + radius * 0.74 * sin(th + 0.05);
406
407  points[5].x = x + radius * 0.72 * cos(th + 0.05);
408  points[5].y = y + radius * 0.72 * sin(th + 0.05);
409
410  points[6].x = x + radius * 0.7  * cos(th);
411  points[6].y = y + radius * 0.7  * sin(th);
412
413  points[7].x = x + radius * 0.72  * cos(th - 0.05);
414  points[7].y = y + radius * 0.72  * sin(th - 0.05);
415
416  XDrawLines (dpy, d, disc->gc, points, 8, CoordModeOrigin);
417
418  /* 21 (1) */
419
420  th = th2 + (2 * M_PI * 0.83333);
421
422  points[0].x = x + radius * 0.78 * cos(th - 0.13);
423  points[0].y = y + radius * 0.78 * sin(th - 0.13);
424
425  points[1].x = x + radius * 0.8  * cos(th - 0.08);
426  points[1].y = y + radius * 0.8  * sin(th - 0.08);
427
428  points[2].x = x + radius * 0.78 * cos(th - 0.03);
429  points[2].y = y + radius * 0.78 * sin(th - 0.03);
430
431  points[3].x = x + radius * 0.76 * cos(th - 0.03);
432  points[3].y = y + radius * 0.76 * sin(th - 0.03);
433
434  points[4].x = x + radius * 0.74 * cos(th - 0.12);
435  points[4].y = y + radius * 0.74 * sin(th - 0.12);
436
437  points[5].x = x + radius * 0.71 * cos(th - 0.13);
438  points[5].y = y + radius * 0.71 * sin(th - 0.13);
439
440  points[6].x = x + radius * 0.7  * cos(th - 0.13);
441  points[6].y = y + radius * 0.7  * sin(th - 0.13);
442
443  points[7].x = x + radius * 0.7  * cos(th - 0.02);
444  points[7].y = y + radius * 0.7  * sin(th - 0.02);
445
446  XDrawLines (dpy, d, disc->gc, points, 8, CoordModeOrigin);
447
448  /* 21 (2) */
449
450  points[0].x = x + radius * 0.77 * cos(th + 0.03);
451  points[0].y = y + radius * 0.77 * sin(th + 0.03);
452
453  points[1].x = x + radius * 0.8  * cos(th + 0.06);
454  points[1].y = y + radius * 0.8  * sin(th + 0.06);
455
456  points[2].x = x + radius * 0.7  * cos(th + 0.06);
457  points[2].y = y + radius * 0.7  * sin(th + 0.06);
458
459  XDrawLines (dpy, d, disc->gc, points, 3, CoordModeOrigin);
460
461  /* 24 (1) */
462
463  th = th2 + (2 * M_PI * 0.91666);
464
465  points[0].x = x + radius * 0.78 * cos(th - 0.13);
466  points[0].y = y + radius * 0.78 * sin(th - 0.13);
467
468  points[1].x = x + radius * 0.8  * cos(th - 0.08);
469  points[1].y = y + radius * 0.8  * sin(th - 0.08);
470
471  points[2].x = x + radius * 0.78 * cos(th - 0.03);
472  points[2].y = y + radius * 0.78 * sin(th - 0.03);
473
474  points[3].x = x + radius * 0.76 * cos(th - 0.03);
475  points[3].y = y + radius * 0.76 * sin(th - 0.03);
476
477  points[4].x = x + radius * 0.74 * cos(th - 0.12);
478  points[4].y = y + radius * 0.74 * sin(th - 0.12);
479
480  points[5].x = x + radius * 0.71 * cos(th - 0.13);
481  points[5].y = y + radius * 0.71 * sin(th - 0.13);
482
483  points[6].x = x + radius * 0.7  * cos(th - 0.13);
484  points[6].y = y + radius * 0.7  * sin(th - 0.13);
485
486  points[7].x = x + radius * 0.7  * cos(th - 0.02);
487  points[7].y = y + radius * 0.7  * sin(th - 0.02);
488
489  XDrawLines (dpy, d, disc->gc, points, 8, CoordModeOrigin);
490
491  /* 24 (2) */
492
493  points[0].x = x + radius * 0.69 * cos(th + 0.09);
494  points[0].y = y + radius * 0.69 * sin(th + 0.09);
495
496  points[1].x = x + radius * 0.8  * cos(th + 0.09);
497  points[1].y = y + radius * 0.8  * sin(th + 0.09);
498
499  points[2].x = x + radius * 0.72 * cos(th + 0.01);
500  points[2].y = y + radius * 0.72 * sin(th + 0.01);
501
502  points[3].x = x + radius * 0.72 * cos(th + 0.13);
503  points[3].y = y + radius * 0.72 * sin(th + 0.13);
504
505  XDrawLines (dpy, d, disc->gc, points, 4, CoordModeOrigin);
506}
507
508
509static void
510draw_ticks (Display *dpy, Drawable d, struct disc *disc,
511            int x, int y, int radius)
512{
513  XSegment segs[72];
514  int i;
515  double tick = (M_PI * 2) / 72;
516
517  for (i = 0; i < 72; i++)
518    {
519      int radius2 = radius;
520      double th = (i * tick) + (2 * M_PI * (disc->theta / ((double) 360*64)));
521
522      if (i % 6)
523        radius2 -= radius / 16;
524      else
525        radius2 -= radius / 8;
526
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);
531    }
532  XDrawSegments (dpy, d, disc->gc, segs, countof(segs));
533
534  draw_letters (dpy, d, disc, x, y, radius);
535}
536
537
538static void
539draw_thin_arrow (Display *dpy, Drawable d, struct disc *disc,
540                 int x, int y, int radius)
541{
542  XPoint points[3];
543  double th;
544  int radius2;
545  double tick = ((M_PI * 2) / 72) * 2;
546
547  radius *= 0.9;
548  radius2 = radius - (radius / 8) * 3;
549
550  th = 2 * M_PI * (disc->theta / ((double) 360*64));
551
552  points[0].x = x + radius * cos(th);           /* tip */
553  points[0].y = y + radius * sin(th);
554
555  points[1].x = x + radius2 * cos(th - tick);   /* tip left */
556  points[1].y = y + radius2 * sin(th - tick);
557
558  points[2].x = x + radius2 * cos(th + tick);   /* tip right */
559  points[2].y = y + radius2 * sin(th + tick);
560
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)));
566
567  XFillPolygon (dpy, d, disc->gc, points, 3, Convex, CoordModeOrigin);
568}
569
570
571static void
572draw_thick_arrow (Display *dpy, Drawable d, struct disc *disc,
573                  int x, int y, int radius)
574{
575  XPoint points[10];
576  double th;
577  int radius2, radius3;
578  double tick = ((M_PI * 2) / 72) * 2;
579
580  radius *= 0.9;
581  radius2 = radius - (radius / 8) * 3;
582  radius3 = radius - (radius / 8) * 2;
583  th = 2 * M_PI * (disc->theta / ((double) 360*64));
584
585  points[0].x = x + radius * cos(th);           /* tip */
586  points[0].y = y + radius * sin(th);
587
588  points[1].x = x + radius2 * cos(th - tick);   /* tip left */
589  points[1].y = y + radius2 * sin(th - tick);
590
591  points[2].x = x + radius2 * cos(th + tick);   /* tip right */
592  points[2].y = y + radius2 * sin(th + tick);
593
594  points[3] = points[0];
595
596  XDrawLines (dpy, d, disc->gc, points, 4, CoordModeOrigin);
597
598  points[0].x = x + radius2 * cos(th - tick/2);  /* top left */
599  points[0].y = y + radius2 * sin(th - tick/2);
600
601  points[1].x = x + -radius2 * cos(th + tick/2); /* bottom left */
602  points[1].y = y + -radius2 * sin(th + tick/2);
603
604  points[2].x = x + -radius3 * cos(th);          /* bottom */
605  points[2].y = y + -radius3 * sin(th);
606
607  points[3].x = x + -radius * cos(th);           /* bottom spike */
608  points[3].y = y + -radius * sin(th);
609
610  points[4] = points[2];                         /* return */
611
612  points[5].x = x + -radius2 * cos(th - tick/2); /* bottom right */
613  points[5].y = y + -radius2 * sin(th - tick/2);
614
615  points[6].x = x + radius2 * cos(th + tick/2);  /* top right */
616  points[6].y = y + radius2 * sin(th + tick/2);
617
618  XDrawLines (dpy, d, disc->gc, points, 7, CoordModeOrigin);
619}
620
621
622
623static void
624roll_disc (struct disc *disc)
625{
626  double th = disc->theta;
627  if (th < 0)
628    th = -(th + disc->velocity);
629  else
630    th = (th + disc->velocity);
631
632  if (th > (360*64))
633    th -= (360*64);
634  else if (th < 0)
635    th += (360*64);
636
637  disc->theta = (disc->theta > 0 ? th : -th);
638
639  disc->velocity += disc->acceleration;
640
641  if (disc->velocity > disc->limit ||
642      disc->velocity < -disc->limit)
643    disc->acceleration = -disc->acceleration;
644
645  /* Alter direction of rotational acceleration randomly. */
646  if (! (random() % 120))
647    disc->acceleration = -disc->acceleration;
648
649  /* Change acceleration very occasionally. */
650  if (! (random() % 200))
651    {
652      if (random() & 1)
653        disc->acceleration *= 1.2;
654      else
655        disc->acceleration *= 0.8;
656    }
657}
658
659
660static void
661init_spin (struct disc *disc)
662{
663  disc->limit = 5*64;
664  disc->theta = RAND(360*64);
665  disc->velocity = RAND(16) * RANDSIGN();
666  disc->acceleration = RAND(16) * RANDSIGN();
667}
668
669
670static void
671draw_compass (Display *dpy, Drawable d, struct disc **discs,
672              int x, int y, int radius)
673{
674  int i = 0;
675  while (discs[i])
676    {
677      discs[i]->draw (dpy, d, discs[i], x, y, radius);
678      roll_disc (discs[i]);
679      i++;
680    }
681}
682
683static void
684draw_pointer (Display *dpy, Drawable d, GC ptr_gc, GC dot_gc,
685              int x, int y, int radius)
686{
687  XPoint points[3];
688  int size = radius * 0.1;
689
690  /* top */
691
692  points[0].x = x - size;
693  points[0].y = y - radius - size;
694
695  points[1].x = x + size;
696  points[1].y = y - radius - size;
697
698  points[2].x = x;
699  points[2].y = y - radius;
700 
701  XFillPolygon (dpy, d, ptr_gc, points, 3, Convex, CoordModeOrigin);
702
703  /* top right */
704
705  points[0].x = x - (radius * 0.85);
706  points[0].y = y - (radius * 0.8);
707
708  points[1].x = x - (radius * 1.1);
709  points[1].y = y - (radius * 0.55);
710
711  points[2].x = x - (radius * 0.6);
712  points[2].y = y - (radius * 0.65);
713 
714  XFillPolygon (dpy, d, ptr_gc, points, 3, Convex, CoordModeOrigin);
715
716  /* left */
717
718  points[0].x = x - (radius * 1.05);
719  points[0].y = y;
720
721  points[1].x = x - (radius * 1.1);
722  points[1].y = y - (radius * 0.025);
723
724  points[2].x = x - (radius * 1.1);
725  points[2].y = y + (radius * 0.025);
726 
727  XFillPolygon (dpy, d, dot_gc, points, 3, Convex, CoordModeOrigin);
728
729  /* right */
730
731  points[0].x = x + (radius * 1.05);
732  points[0].y = y;
733
734  points[1].x = x + (radius * 1.1);
735  points[1].y = y - (radius * 0.025);
736
737  points[2].x = x + (radius * 1.1);
738  points[2].y = y + (radius * 0.025);
739 
740  XFillPolygon (dpy, d, dot_gc, points, 3, Convex, CoordModeOrigin);
741
742  /* bottom */
743
744  points[0].x = x;
745  points[0].y = y + (radius * 1.05);
746
747  points[1].x = x - (radius * 0.025);
748  points[1].y = y + (radius * 1.1);
749
750  points[2].x = x + (radius * 0.025);
751  points[2].y = y + (radius * 1.1);
752 
753  XFillPolygon (dpy, d, dot_gc, points, 3, Convex, CoordModeOrigin);
754
755  /* bottom left */
756
757  points[0].x = x + (radius * 0.74);
758  points[0].y = y + (radius * 0.74);
759
760  points[1].x = x + (radius * 0.78);
761  points[1].y = y + (radius * 0.75);
762
763  points[2].x = x + (radius * 0.75);
764  points[2].y = y + (radius * 0.78);
765 
766  XFillPolygon (dpy, d, dot_gc, points, 3, Convex, CoordModeOrigin);
767
768  /* top left */
769
770  points[0].x = x + (radius * 0.74);
771  points[0].y = y - (radius * 0.74);
772
773  points[1].x = x + (radius * 0.78);
774  points[1].y = y - (radius * 0.75);
775
776  points[2].x = x + (radius * 0.75);
777  points[2].y = y - (radius * 0.78);
778 
779  XFillPolygon (dpy, d, dot_gc, points, 3, Convex, CoordModeOrigin);
780
781  /* bottom right */
782
783  points[0].x = x - (radius * 0.74);
784  points[0].y = y + (radius * 0.74);
785
786  points[1].x = x - (radius * 0.78);
787  points[1].y = y + (radius * 0.75);
788
789  points[2].x = x - (radius * 0.75);
790  points[2].y = y + (radius * 0.78);
791 
792  XFillPolygon (dpy, d, dot_gc, points, 3, Convex, CoordModeOrigin);
793}
794
795
796char *progclass = "Compass";
797
798char *defaults [] = {
799  ".background:         #000000",
800  ".foreground:         #DDFFFF",
801  "*arrow1Foreground:   #FFF66A",
802  "*arrow2Foreground:   #F7D64A",
803  "*pointerForeground:  #FF0000",
804  "*delay:              20000",
805  "*doubleBuffer:       True",
806#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
807  "*useDBE:             True",
808#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
809  0
810};
811
812XrmOptionDescRec options [] = {
813  { "-delay",           ".delay",       XrmoptionSepArg, 0 },
814  { "-db",              ".doubleBuffer", XrmoptionNoArg,  "True" },
815  { "-no-db",           ".doubleBuffer", XrmoptionNoArg,  "False" },
816  { 0, 0, 0, 0 }
817};
818
819void
820screenhack (Display *dpy, Window window)
821{
822  XGCValues gcv;
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;
827  GC ptr_gc;
828  GC erase_gc = 0;
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 */
834
835  XGetWindowAttributes (dpy, window, &xgwa);
836  size2 = MIN(xgwa.width, xgwa.height);
837
838  if (size2 > 600) size2 = 600;
839
840  size = (size2 / 2) * 0.8;
841
842  x = xgwa.width/2;
843  y = xgwa.height/2;
844
845  if (dbuf)
846    {
847#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
848      b = backb = xdbe_get_backbuffer (dpy, window, XdbeUndefined);
849#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
850
851      if (!b)
852        {
853          x = size2/2;
854          y = size2/2;
855          ba = XCreatePixmap (dpy, window, size2, size2, xgwa.depth);
856          bb = XCreatePixmap (dpy, window, size2, size2, xgwa.depth);
857          b = ba;
858        }
859    }
860  else
861    {
862      b = window;
863    }
864
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));
868  discs[3] = 0;
869
870  gcv.foreground = get_pixel_resource ("foreground", "Foreground",
871                                       dpy, xgwa.colormap);
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,
876                            &gcv);
877  init_spin (discs[0]);
878
879  gcv.foreground = get_pixel_resource ("arrow2Foreground", "Foreground",
880                                       dpy, xgwa.colormap);
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]);
885
886  gcv.foreground = get_pixel_resource ("arrow1Foreground", "Foreground",
887                                       dpy, xgwa.colormap);
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]);
892
893  gcv.foreground = get_pixel_resource ("pointerForeground", "Foreground",
894                                       dpy, xgwa.colormap);
895  ptr_gc = XCreateGC (dpy, b, GCForeground|GCLineWidth, &gcv);
896
897  gcv.foreground = get_pixel_resource ("background", "Background",
898                                       dpy, xgwa.colormap);
899  erase_gc = XCreateGC (dpy, b, GCForeground, &gcv);
900
901  if (ba) XFillRectangle (dpy, ba, erase_gc, 0, 0, size2, size2);
902  if (bb) XFillRectangle (dpy, bb, erase_gc, 0, 0, size2, size2);
903
904  while (1)
905    {
906      XFillRectangle (dpy, b, erase_gc, 0, 0, xgwa.width, xgwa.height);
907
908      draw_compass (dpy, b, discs, x, y, size);
909      draw_pointer (dpy, b, ptr_gc, discs[0]->gc, x, y, size);
910
911#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
912      if (backb)
913        {
914          XdbeSwapInfo info[1];
915          info[0].swap_window = window;
916          info[0].swap_action = XdbeUndefined;
917          XdbeSwapBuffers (dpy, info, 1);
918        }
919      else
920#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
921      if (dbuf)
922        {
923          XCopyArea (dpy, b, window, erase_gc, 0, 0,
924                     size2, size2,
925                     xgwa.width/2 - x,
926                     xgwa.height/2 - y);
927          b = (b == ba ? bb : ba);
928        }
929
930      XSync (dpy, False);
931      screenhack_handle_events (dpy);
932      if (delay)
933        usleep (delay);
934    }
935}
Note: See TracBrowser for help on using the repository browser.