From d3a98cf6cbc3bd0b9efc570f58e8812c03931c18 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 16 Oct 2018 10:08:48 +0200 Subject: Original 5.40 --- hacks/compass.c | 986 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 986 insertions(+) create mode 100644 hacks/compass.c (limited to 'hacks/compass.c') diff --git a/hacks/compass.c b/hacks/compass.c new file mode 100644 index 0000000..1dc1d3e --- /dev/null +++ b/hacks/compass.c @@ -0,0 +1,986 @@ +/* xscreensaver, Copyright (c) 1999-2018 Jamie Zawinski + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. No representations are made about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + */ + +#include +#include "screenhack.h" + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION +# include "xdbe.h" +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + +#define countof(x) (sizeof(x)/sizeof(*(x))) +#define ABS(x) ((x)<0?-(x):(x)) +#define MAX(x,y) ((x)<(y)?(y):(x)) +#define MIN(x,y) ((x)>(y)?(y):(x)) +#define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n)))) +#define RANDSIGN() ((random() & 1) ? 1 : -1) + +struct state { + Display *dpy; + Window window; + + int delay; + Bool dbuf; + struct disc *discs[4]; + int x, y, size, size2; + GC ptr_gc; + GC erase_gc; + XWindowAttributes xgwa; + Pixmap b, ba, bb; /* double-buffer to reduce flicker */ +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + XdbeBackBuffer backb; +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ +}; + + + +struct disc { + int theta; /* 0 - 360*64 */ + int velocity; + int acceleration; + int limit; + GC gc; + void (*draw) (struct state *, Drawable, struct disc *, + int x, int y, int radius); +}; + + +static void +draw_letters (struct state *st, Drawable d, struct disc *disc, + int x, int y, int radius) +{ + XPoint points[50]; + double th2 = 2 * M_PI * (disc->theta / ((double) 360*64)); + double th; + + /* W */ + + th = th2; + + points[0].x = x + radius * 0.8 * cos(th - 0.07); + points[0].y = y + radius * 0.8 * sin(th - 0.07); + + points[1].x = x + radius * 0.7 * cos(th - 0.05); + points[1].y = y + radius * 0.7 * sin(th - 0.05); + + points[2].x = x + radius * 0.78 * cos(th); + points[2].y = y + radius * 0.78 * sin(th); + + points[3].x = x + radius * 0.7 * cos(th + 0.05); + points[3].y = y + radius * 0.7 * sin(th + 0.05); + + points[4].x = x + radius * 0.8 * cos(th + 0.07); + points[4].y = y + radius * 0.8 * sin(th + 0.07); + + XDrawLines (st->dpy, d, disc->gc, points, 5, CoordModeOrigin); + + /* 30 (1) */ + + th = th2 + (2 * M_PI * 0.08333); + + points[0].x = x + radius * 0.78 * cos(th - 0.13); + points[0].y = y + radius * 0.78 * sin(th - 0.13); + + points[1].x = x + radius * 0.8 * cos(th - 0.08); + points[1].y = y + radius * 0.8 * sin(th - 0.08); + + points[2].x = x + radius * 0.78 * cos(th - 0.03); + points[2].y = y + radius * 0.78 * sin(th - 0.03); + + points[3].x = x + radius * 0.76 * cos(th - 0.03); + points[3].y = y + radius * 0.76 * sin(th - 0.03); + + points[4].x = x + radius * 0.75 * cos(th - 0.08); + points[4].y = y + radius * 0.75 * sin(th - 0.08); + + points[5].x = x + radius * 0.74 * cos(th - 0.03); + points[5].y = y + radius * 0.74 * sin(th - 0.03); + + points[6].x = x + radius * 0.72 * cos(th - 0.03); + points[6].y = y + radius * 0.72 * sin(th - 0.03); + + points[7].x = x + radius * 0.7 * cos(th - 0.08); + points[7].y = y + radius * 0.7 * sin(th - 0.08); + + points[8].x = x + radius * 0.72 * cos(th - 0.13); + points[8].y = y + radius * 0.72 * sin(th - 0.13); + + XDrawLines (st->dpy, d, disc->gc, points, 9, CoordModeOrigin); + + /* 30 (2) */ + + points[0].x = x + radius * 0.78 * cos(th + 0.03); + points[0].y = y + radius * 0.78 * sin(th + 0.03); + + points[1].x = x + radius * 0.8 * cos(th + 0.08); + points[1].y = y + radius * 0.8 * sin(th + 0.08); + + points[2].x = x + radius * 0.78 * cos(th + 0.13); + points[2].y = y + radius * 0.78 * sin(th + 0.13); + + points[3].x = x + radius * 0.72 * cos(th + 0.13); + points[3].y = y + radius * 0.72 * sin(th + 0.13); + + points[4].x = x + radius * 0.7 * cos(th + 0.08); + points[4].y = y + radius * 0.7 * sin(th + 0.08); + + points[5].x = x + radius * 0.72 * cos(th + 0.03); + points[5].y = y + radius * 0.72 * sin(th + 0.03); + + points[6] = points[0]; + + XDrawLines (st->dpy, d, disc->gc, points, 7, CoordModeOrigin); + + /* 33 (1) */ + + th = th2 + (2 * M_PI * 0.16666); + + points[0].x = x + radius * 0.78 * cos(th - 0.13); + points[0].y = y + radius * 0.78 * sin(th - 0.13); + + points[1].x = x + radius * 0.8 * cos(th - 0.08); + points[1].y = y + radius * 0.8 * sin(th - 0.08); + + points[2].x = x + radius * 0.78 * cos(th - 0.03); + points[2].y = y + radius * 0.78 * sin(th - 0.03); + + points[3].x = x + radius * 0.76 * cos(th - 0.03); + points[3].y = y + radius * 0.76 * sin(th - 0.03); + + points[4].x = x + radius * 0.75 * cos(th - 0.08); + points[4].y = y + radius * 0.75 * sin(th - 0.08); + + points[5].x = x + radius * 0.74 * cos(th - 0.03); + points[5].y = y + radius * 0.74 * sin(th - 0.03); + + points[6].x = x + radius * 0.72 * cos(th - 0.03); + points[6].y = y + radius * 0.72 * sin(th - 0.03); + + points[7].x = x + radius * 0.7 * cos(th - 0.08); + points[7].y = y + radius * 0.7 * sin(th - 0.08); + + points[8].x = x + radius * 0.72 * cos(th - 0.13); + points[8].y = y + radius * 0.72 * sin(th - 0.13); + + XDrawLines (st->dpy, d, disc->gc, points, 9, CoordModeOrigin); + + /* 33 (2) */ + + points[0].x = x + radius * 0.78 * cos(th + 0.03); + points[0].y = y + radius * 0.78 * sin(th + 0.03); + + points[1].x = x + radius * 0.8 * cos(th + 0.08); + points[1].y = y + radius * 0.8 * sin(th + 0.08); + + points[2].x = x + radius * 0.78 * cos(th + 0.13); + points[2].y = y + radius * 0.78 * sin(th + 0.13); + + points[3].x = x + radius * 0.76 * cos(th + 0.13); + points[3].y = y + radius * 0.76 * sin(th + 0.13); + + points[4].x = x + radius * 0.75 * cos(th + 0.08); + points[4].y = y + radius * 0.75 * sin(th + 0.08); + + points[5].x = x + radius * 0.74 * cos(th + 0.13); + points[5].y = y + radius * 0.74 * sin(th + 0.13); + + points[6].x = x + radius * 0.72 * cos(th + 0.13); + points[6].y = y + radius * 0.72 * sin(th + 0.13); + + points[7].x = x + radius * 0.7 * cos(th + 0.08); + points[7].y = y + radius * 0.7 * sin(th + 0.08); + + points[8].x = x + radius * 0.72 * cos(th + 0.03); + points[8].y = y + radius * 0.72 * sin(th + 0.03); + + XDrawLines (st->dpy, d, disc->gc, points, 9, CoordModeOrigin); + + /* N */ + + th = th2 + (2 * M_PI * 0.25); + + points[0].x = x + radius * 0.7 * cos(th - 0.05); + points[0].y = y + radius * 0.7 * sin(th - 0.05); + + points[1].x = x + radius * 0.8 * cos(th - 0.05); + points[1].y = y + radius * 0.8 * sin(th - 0.05); + + points[2].x = x + radius * 0.7 * cos(th + 0.05); + points[2].y = y + radius * 0.7 * sin(th + 0.05); + + points[3].x = x + radius * 0.8 * cos(th + 0.05); + points[3].y = y + radius * 0.8 * sin(th + 0.05); + + XDrawLines (st->dpy, d, disc->gc, points, 4, CoordModeOrigin); + + /* 3 */ + + th = th2 + (2 * M_PI * 0.33333); + + points[0].x = x + radius * 0.78 * cos(th - 0.05); + points[0].y = y + radius * 0.78 * sin(th - 0.05); + + points[1].x = x + radius * 0.8 * cos(th); + points[1].y = y + radius * 0.8 * sin(th); + + points[2].x = x + radius * 0.78 * cos(th + 0.05); + points[2].y = y + radius * 0.78 * sin(th + 0.05); + + points[3].x = x + radius * 0.76 * cos(th + 0.05); + points[3].y = y + radius * 0.76 * sin(th + 0.05); + + points[4].x = x + radius * 0.75 * cos(th); + points[4].y = y + radius * 0.75 * sin(th); + + points[5].x = x + radius * 0.74 * cos(th + 0.05); + points[5].y = y + radius * 0.74 * sin(th + 0.05); + + points[6].x = x + radius * 0.72 * cos(th + 0.05); + points[6].y = y + radius * 0.72 * sin(th + 0.05); + + points[7].x = x + radius * 0.7 * cos(th); + points[7].y = y + radius * 0.7 * sin(th); + + points[8].x = x + radius * 0.72 * cos(th - 0.05); + points[8].y = y + radius * 0.72 * sin(th - 0.05); + + XDrawLines (st->dpy, d, disc->gc, points, 9, CoordModeOrigin); + + /* 6 */ + + th = th2 + (2 * M_PI * 0.41666); + + points[0].x = x + radius * 0.78 * cos(th + 0.05); + points[0].y = y + radius * 0.78 * sin(th + 0.05); + + points[1].x = x + radius * 0.8 * cos(th); + points[1].y = y + radius * 0.8 * sin(th); + + points[2].x = x + radius * 0.78 * cos(th - 0.05); + points[2].y = y + radius * 0.78 * sin(th - 0.05); + + points[3].x = x + radius * 0.72 * cos(th - 0.05); + points[3].y = y + radius * 0.72 * sin(th - 0.05); + + points[4].x = x + radius * 0.7 * cos(th); + points[4].y = y + radius * 0.7 * sin(th); + + points[5].x = x + radius * 0.72 * cos(th + 0.05); + points[5].y = y + radius * 0.72 * sin(th + 0.05); + + points[6].x = x + radius * 0.74 * cos(th + 0.05); + points[6].y = y + radius * 0.74 * sin(th + 0.05); + + points[7].x = x + radius * 0.76 * cos(th); + points[7].y = y + radius * 0.76 * sin(th); + + points[8].x = x + radius * 0.74 * cos(th - 0.05); + points[8].y = y + radius * 0.74 * sin(th - 0.05); + + XDrawLines (st->dpy, d, disc->gc, points, 9, CoordModeOrigin); + + + /* E */ + + th = th2 + (2 * M_PI * 0.5); + + points[0].x = x + radius * 0.8 * cos(th + 0.05); + points[0].y = y + radius * 0.8 * sin(th + 0.05); + + points[1].x = x + radius * 0.8 * cos(th - 0.05); + points[1].y = y + radius * 0.8 * sin(th - 0.05); + + points[2].x = x + radius * 0.75 * cos(th - 0.05); + points[2].y = y + radius * 0.75 * sin(th - 0.05); + + points[3].x = x + radius * 0.75 * cos(th + 0.025); + points[3].y = y + radius * 0.75 * sin(th + 0.025); + + points[4].x = x + radius * 0.75 * cos(th - 0.05); + points[4].y = y + radius * 0.75 * sin(th - 0.05); + + points[5].x = x + radius * 0.7 * cos(th - 0.05); + points[5].y = y + radius * 0.7 * sin(th - 0.05); + + points[6].x = x + radius * 0.7 * cos(th + 0.05); + points[6].y = y + radius * 0.7 * sin(th + 0.05); + + XDrawLines (st->dpy, d, disc->gc, points, 7, CoordModeOrigin); + + /* 12 (1) */ + + th = th2 + (2 * M_PI * 0.58333); + + points[0].x = x + radius * 0.77 * cos(th - 0.06); + points[0].y = y + radius * 0.77 * sin(th - 0.06); + + points[1].x = x + radius * 0.8 * cos(th - 0.03); + points[1].y = y + radius * 0.8 * sin(th - 0.03); + + points[2].x = x + radius * 0.7 * cos(th - 0.03); + points[2].y = y + radius * 0.7 * sin(th - 0.03); + + XDrawLines (st->dpy, d, disc->gc, points, 3, CoordModeOrigin); + + /* 12 (2) */ + + points[0].x = x + radius * 0.78 * cos(th + 0.02); + points[0].y = y + radius * 0.78 * sin(th + 0.02); + + points[1].x = x + radius * 0.8 * cos(th + 0.07); + points[1].y = y + radius * 0.8 * sin(th + 0.07); + + points[2].x = x + radius * 0.78 * cos(th + 0.11); + points[2].y = y + radius * 0.78 * sin(th + 0.11); + + points[3].x = x + radius * 0.76 * cos(th + 0.11); + points[3].y = y + radius * 0.76 * sin(th + 0.11); + + points[4].x = x + radius * 0.74 * cos(th + 0.02); + points[4].y = y + radius * 0.74 * sin(th + 0.02); + + points[5].x = x + radius * 0.71 * cos(th + 0.03); + points[5].y = y + radius * 0.71 * sin(th + 0.03); + + points[6].x = x + radius * 0.7 * cos(th + 0.03); + points[6].y = y + radius * 0.7 * sin(th + 0.03); + + points[7].x = x + radius * 0.7 * cos(th + 0.13); + points[7].y = y + radius * 0.7 * sin(th + 0.13); + + XDrawLines (st->dpy, d, disc->gc, points, 8, CoordModeOrigin); + + /* 15 (1) */ + + th = th2 + (2 * M_PI * 0.66666); + + points[0].x = x + radius * 0.77 * cos(th - 0.06); + points[0].y = y + radius * 0.77 * sin(th - 0.06); + + points[1].x = x + radius * 0.8 * cos(th - 0.03); + points[1].y = y + radius * 0.8 * sin(th - 0.03); + + points[2].x = x + radius * 0.7 * cos(th - 0.03); + points[2].y = y + radius * 0.7 * sin(th - 0.03); + + XDrawLines (st->dpy, d, disc->gc, points, 3, CoordModeOrigin); + + /* 15 (2) */ + + points[0].x = x + radius * 0.8 * cos(th + 0.11); + points[0].y = y + radius * 0.8 * sin(th + 0.11); + + points[1].x = x + radius * 0.8 * cos(th + 0.02); + points[1].y = y + radius * 0.8 * sin(th + 0.02); + + points[2].x = x + radius * 0.76 * cos(th + 0.02); + points[2].y = y + radius * 0.76 * sin(th + 0.02); + + points[3].x = x + radius * 0.77 * cos(th + 0.06); + points[3].y = y + radius * 0.77 * sin(th + 0.06); + + points[4].x = x + radius * 0.76 * cos(th + 0.10); + points[4].y = y + radius * 0.76 * sin(th + 0.10); + + points[5].x = x + radius * 0.73 * cos(th + 0.11); + points[5].y = y + radius * 0.73 * sin(th + 0.11); + + points[6].x = x + radius * 0.72 * cos(th + 0.10); + points[6].y = y + radius * 0.72 * sin(th + 0.10); + + points[7].x = x + radius * 0.7 * cos(th + 0.06); + points[7].y = y + radius * 0.7 * sin(th + 0.06); + + points[8].x = x + radius * 0.72 * cos(th + 0.02); + points[8].y = y + radius * 0.72 * sin(th + 0.02); + + XDrawLines (st->dpy, d, disc->gc, points, 9, CoordModeOrigin); + + /* S */ + + th = th2 + (2 * M_PI * 0.75); + + points[0].x = x + radius * 0.78 * cos(th + 0.05); + points[0].y = y + radius * 0.78 * sin(th + 0.05); + + points[1].x = x + radius * 0.8 * cos(th); + points[1].y = y + radius * 0.8 * sin(th); + + points[2].x = x + radius * 0.78 * cos(th - 0.05); + points[2].y = y + radius * 0.78 * sin(th - 0.05); + + points[3].x = x + radius * 0.76 * cos(th - 0.05); + points[3].y = y + radius * 0.76 * sin(th - 0.05); + + points[4].x = x + radius * 0.74 * cos(th + 0.05); + points[4].y = y + radius * 0.74 * sin(th + 0.05); + + points[5].x = x + radius * 0.72 * cos(th + 0.05); + points[5].y = y + radius * 0.72 * sin(th + 0.05); + + points[6].x = x + radius * 0.7 * cos(th); + points[6].y = y + radius * 0.7 * sin(th); + + points[7].x = x + radius * 0.72 * cos(th - 0.05); + points[7].y = y + radius * 0.72 * sin(th - 0.05); + + XDrawLines (st->dpy, d, disc->gc, points, 8, CoordModeOrigin); + + /* 21 (1) */ + + th = th2 + (2 * M_PI * 0.83333); + + points[0].x = x + radius * 0.78 * cos(th - 0.13); + points[0].y = y + radius * 0.78 * sin(th - 0.13); + + points[1].x = x + radius * 0.8 * cos(th - 0.08); + points[1].y = y + radius * 0.8 * sin(th - 0.08); + + points[2].x = x + radius * 0.78 * cos(th - 0.03); + points[2].y = y + radius * 0.78 * sin(th - 0.03); + + points[3].x = x + radius * 0.76 * cos(th - 0.03); + points[3].y = y + radius * 0.76 * sin(th - 0.03); + + points[4].x = x + radius * 0.74 * cos(th - 0.12); + points[4].y = y + radius * 0.74 * sin(th - 0.12); + + points[5].x = x + radius * 0.71 * cos(th - 0.13); + points[5].y = y + radius * 0.71 * sin(th - 0.13); + + points[6].x = x + radius * 0.7 * cos(th - 0.13); + points[6].y = y + radius * 0.7 * sin(th - 0.13); + + points[7].x = x + radius * 0.7 * cos(th - 0.02); + points[7].y = y + radius * 0.7 * sin(th - 0.02); + + XDrawLines (st->dpy, d, disc->gc, points, 8, CoordModeOrigin); + + /* 21 (2) */ + + points[0].x = x + radius * 0.77 * cos(th + 0.03); + points[0].y = y + radius * 0.77 * sin(th + 0.03); + + points[1].x = x + radius * 0.8 * cos(th + 0.06); + points[1].y = y + radius * 0.8 * sin(th + 0.06); + + points[2].x = x + radius * 0.7 * cos(th + 0.06); + points[2].y = y + radius * 0.7 * sin(th + 0.06); + + XDrawLines (st->dpy, d, disc->gc, points, 3, CoordModeOrigin); + + /* 24 (1) */ + + th = th2 + (2 * M_PI * 0.91666); + + points[0].x = x + radius * 0.78 * cos(th - 0.13); + points[0].y = y + radius * 0.78 * sin(th - 0.13); + + points[1].x = x + radius * 0.8 * cos(th - 0.08); + points[1].y = y + radius * 0.8 * sin(th - 0.08); + + points[2].x = x + radius * 0.78 * cos(th - 0.03); + points[2].y = y + radius * 0.78 * sin(th - 0.03); + + points[3].x = x + radius * 0.76 * cos(th - 0.03); + points[3].y = y + radius * 0.76 * sin(th - 0.03); + + points[4].x = x + radius * 0.74 * cos(th - 0.12); + points[4].y = y + radius * 0.74 * sin(th - 0.12); + + points[5].x = x + radius * 0.71 * cos(th - 0.13); + points[5].y = y + radius * 0.71 * sin(th - 0.13); + + points[6].x = x + radius * 0.7 * cos(th - 0.13); + points[6].y = y + radius * 0.7 * sin(th - 0.13); + + points[7].x = x + radius * 0.7 * cos(th - 0.02); + points[7].y = y + radius * 0.7 * sin(th - 0.02); + + XDrawLines (st->dpy, d, disc->gc, points, 8, CoordModeOrigin); + + /* 24 (2) */ + + points[0].x = x + radius * 0.69 * cos(th + 0.09); + points[0].y = y + radius * 0.69 * sin(th + 0.09); + + points[1].x = x + radius * 0.8 * cos(th + 0.09); + points[1].y = y + radius * 0.8 * sin(th + 0.09); + + points[2].x = x + radius * 0.72 * cos(th + 0.01); + points[2].y = y + radius * 0.72 * sin(th + 0.01); + + points[3].x = x + radius * 0.72 * cos(th + 0.13); + points[3].y = y + radius * 0.72 * sin(th + 0.13); + + XDrawLines (st->dpy, d, disc->gc, points, 4, CoordModeOrigin); +} + + +static void +draw_ticks (struct state *st, Drawable d, struct disc *disc, + int x, int y, int radius) +{ + XSegment segs[72]; + int i; + double tick = (M_PI * 2) / 72; + + for (i = 0; i < 72; i++) + { + int radius2 = radius; + double th = (i * tick) + (2 * M_PI * (disc->theta / ((double) 360*64))); + + if (i % 6) + radius2 -= radius / 16; + else + radius2 -= radius / 8; + + segs[i].x1 = x + radius * cos(th); + segs[i].y1 = y + radius * sin(th); + segs[i].x2 = x + radius2 * cos(th); + segs[i].y2 = y + radius2 * sin(th); + } + XDrawSegments (st->dpy, d, disc->gc, segs, countof(segs)); + + draw_letters (st, d, disc, x, y, radius); +} + + +static void +draw_thin_arrow (struct state *st, Drawable d, struct disc *disc, + int x, int y, int radius) +{ + XPoint points[3]; + double th; + int radius2; + double tick = ((M_PI * 2) / 72) * 2; + + radius *= 0.9; + radius2 = radius - (radius / 8) * 3; + + th = 2 * M_PI * (disc->theta / ((double) 360*64)); + + points[0].x = x + radius * cos(th); /* tip */ + points[0].y = y + radius * sin(th); + + points[1].x = x + radius2 * cos(th - tick); /* tip left */ + points[1].y = y + radius2 * sin(th - tick); + + points[2].x = x + radius2 * cos(th + tick); /* tip right */ + points[2].y = y + radius2 * sin(th + tick); + + XDrawLine (st->dpy, d, disc->gc, + (int) (x + radius2 * cos(th)), + (int) (y + radius2 * sin(th)), + (int) (x + -radius * cos(th)), + (int) (y + -radius * sin(th))); + + XFillPolygon (st->dpy, d, disc->gc, points, 3, Convex, CoordModeOrigin); +} + + +static void +draw_thick_arrow (struct state *st, Drawable d, struct disc *disc, + int x, int y, int radius) +{ + XPoint points[10]; + double th; + int radius2, radius3; + double tick = ((M_PI * 2) / 72) * 2; + + radius *= 0.9; + radius2 = radius - (radius / 8) * 3; + radius3 = radius - (radius / 8) * 2; + th = 2 * M_PI * (disc->theta / ((double) 360*64)); + + points[0].x = x + radius * cos(th); /* tip */ + points[0].y = y + radius * sin(th); + + points[1].x = x + radius2 * cos(th - tick); /* tip left */ + points[1].y = y + radius2 * sin(th - tick); + + points[2].x = x + radius2 * cos(th + tick); /* tip right */ + points[2].y = y + radius2 * sin(th + tick); + + points[3] = points[0]; + + XDrawLines (st->dpy, d, disc->gc, points, 4, CoordModeOrigin); + + points[0].x = x + radius2 * cos(th - tick/2); /* top left */ + points[0].y = y + radius2 * sin(th - tick/2); + + points[1].x = x + -radius2 * cos(th + tick/2); /* bottom left */ + points[1].y = y + -radius2 * sin(th + tick/2); + + points[2].x = x + -radius3 * cos(th); /* bottom */ + points[2].y = y + -radius3 * sin(th); + + points[3].x = x + -radius * cos(th); /* bottom spike */ + points[3].y = y + -radius * sin(th); + + points[4] = points[2]; /* return */ + + points[5].x = x + -radius2 * cos(th - tick/2); /* bottom right */ + points[5].y = y + -radius2 * sin(th - tick/2); + + points[6].x = x + radius2 * cos(th + tick/2); /* top right */ + points[6].y = y + radius2 * sin(th + tick/2); + + XDrawLines (st->dpy, d, disc->gc, points, 7, CoordModeOrigin); +} + + + +static void +roll_disc (struct disc *disc) +{ + double th = disc->theta; + if (th < 0) + th = -(th + disc->velocity); + else + th = (th + disc->velocity); + + if (th > (360*64)) + th -= (360*64); + else if (th < 0) + th += (360*64); + + disc->theta = (disc->theta > 0 ? th : -th); + + disc->velocity += disc->acceleration; + + if (disc->velocity > disc->limit || + disc->velocity < -disc->limit) + disc->acceleration = -disc->acceleration; + + /* Alter direction of rotational acceleration randomly. */ + if (! (random() % 120)) + disc->acceleration = -disc->acceleration; + + /* Change acceleration very occasionally. */ + if (! (random() % 200)) + { + if (random() & 1) + disc->acceleration *= 1.2; + else + disc->acceleration *= 0.8; + } +} + + +static void +init_spin (struct disc *disc) +{ + disc->limit = 5*64; + disc->theta = RAND(360*64); + disc->velocity = RAND(16) * RANDSIGN(); + disc->acceleration = RAND(16) * RANDSIGN(); +} + + +static void +draw_compass (struct state *st) +{ + int i = 0; + while (st->discs[i]) + { + st->discs[i]->draw (st, st->b, st->discs[i], st->x, st->y, st->size); + roll_disc (st->discs[i]); + i++; + } +} + +static void +draw_pointer (struct state *st) +{ + int radius = st->size; + GC dot_gc = st->discs[0]->gc; + XPoint points[3]; + int size = radius * 0.1; + + /* top */ + + points[0].x = st->x - size; + points[0].y = st->y - radius - size; + + points[1].x = st->x + size; + points[1].y = st->y - radius - size; + + points[2].x = st->x; + points[2].y = st->y - radius; + + XFillPolygon (st->dpy, st->b, st->ptr_gc, points, 3, Convex, CoordModeOrigin); + + /* top right */ + + points[0].x = st->x - (radius * 0.85); + points[0].y = st->y - (radius * 0.8); + + points[1].x = st->x - (radius * 1.1); + points[1].y = st->y - (radius * 0.55); + + points[2].x = st->x - (radius * 0.6); + points[2].y = st->y - (radius * 0.65); + + XFillPolygon (st->dpy, st->b, st->ptr_gc, points, 3, Convex, CoordModeOrigin); + + /* left */ + + points[0].x = st->x - (radius * 1.05); + points[0].y = st->y; + + points[1].x = st->x - (radius * 1.1); + points[1].y = st->y - (radius * 0.025); + + points[2].x = st->x - (radius * 1.1); + points[2].y = st->y + (radius * 0.025); + + XFillPolygon (st->dpy, st->b, dot_gc, points, 3, Convex, CoordModeOrigin); + + /* right */ + + points[0].x = st->x + (radius * 1.05); + points[0].y = st->y; + + points[1].x = st->x + (radius * 1.1); + points[1].y = st->y - (radius * 0.025); + + points[2].x = st->x + (radius * 1.1); + points[2].y = st->y + (radius * 0.025); + + XFillPolygon (st->dpy, st->b, dot_gc, points, 3, Convex, CoordModeOrigin); + + /* bottom */ + + points[0].x = st->x; + points[0].y = st->y + (radius * 1.05); + + points[1].x = st->x - (radius * 0.025); + points[1].y = st->y + (radius * 1.1); + + points[2].x = st->x + (radius * 0.025); + points[2].y = st->y + (radius * 1.1); + + XFillPolygon (st->dpy, st->b, dot_gc, points, 3, Convex, CoordModeOrigin); + + /* bottom left */ + + points[0].x = st->x + (radius * 0.74); + points[0].y = st->y + (radius * 0.74); + + points[1].x = st->x + (radius * 0.78); + points[1].y = st->y + (radius * 0.75); + + points[2].x = st->x + (radius * 0.75); + points[2].y = st->y + (radius * 0.78); + + XFillPolygon (st->dpy, st->b, dot_gc, points, 3, Convex, CoordModeOrigin); + + /* top left */ + + points[0].x = st->x + (radius * 0.74); + points[0].y = st->y - (radius * 0.74); + + points[1].x = st->x + (radius * 0.78); + points[1].y = st->y - (radius * 0.75); + + points[2].x = st->x + (radius * 0.75); + points[2].y = st->y - (radius * 0.78); + + XFillPolygon (st->dpy, st->b, dot_gc, points, 3, Convex, CoordModeOrigin); + + /* bottom right */ + + points[0].x = st->x - (radius * 0.74); + points[0].y = st->y + (radius * 0.74); + + points[1].x = st->x - (radius * 0.78); + points[1].y = st->y + (radius * 0.75); + + points[2].x = st->x - (radius * 0.75); + points[2].y = st->y + (radius * 0.78); + + XFillPolygon (st->dpy, st->b, dot_gc, points, 3, Convex, CoordModeOrigin); +} + + +static void * +compass_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XGCValues gcv; + st->dpy = dpy; + st->window = window; + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + st->dbuf = get_boolean_resource (st->dpy, "doubleBuffer", "Boolean"); + +# ifdef HAVE_JWXYZ /* Don't second-guess Quartz's double-buffering */ + st->dbuf = False; +# endif + + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + st->size2 = MIN(st->xgwa.width, st->xgwa.height); + + if (st->xgwa.width > st->xgwa.height * 5 || /* goofy aspect ratio */ + st->xgwa.height > st->xgwa.width * 5) + st->size2 = MAX(st->xgwa.width, st->xgwa.height); + + { + int max = 600; + if (st->xgwa.width > 2560) max *= 2; /* Retina displays */ + if (st->size2 > max) st->size2 = max; + } + + st->size = (st->size2 / 2) * 0.8; + + st->x = st->xgwa.width/2; + st->y = st->xgwa.height/2; + + if (st->dbuf) + { +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + st->b = st->backb = xdbe_get_backbuffer (st->dpy, st->window, XdbeUndefined); +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + + if (!st->b) + { + st->x = st->size2/2; + st->y = st->size2/2; + st->ba = XCreatePixmap (st->dpy, st->window, st->size2, st->size2, st->xgwa.depth); + st->bb = XCreatePixmap (st->dpy, st->window, st->size2, st->size2, st->xgwa.depth); + st->b = st->ba; + } + } + else + { + st->b = st->window; + } + + st->discs[0] = (struct disc *) calloc (1, sizeof (struct disc)); + st->discs[1] = (struct disc *) calloc (1, sizeof (struct disc)); + st->discs[2] = (struct disc *) calloc (1, sizeof (struct disc)); + st->discs[3] = 0; + + gcv.foreground = get_pixel_resource (st->dpy, st->xgwa.colormap, + "foreground", "Foreground"); + gcv.line_width = MAX(2, (st->size/60)); + gcv.join_style = JoinBevel; + st->discs[0]->draw = draw_ticks; + st->discs[0]->gc = XCreateGC (st->dpy, st->b, GCForeground|GCLineWidth|GCJoinStyle, + &gcv); + init_spin (st->discs[0]); + + gcv.foreground = get_pixel_resource (st->dpy, st->xgwa.colormap, + "arrow2Foreground", "Foreground"); + gcv.line_width = MAX(4, (st->size / 30)); + st->discs[1]->draw = draw_thick_arrow; + st->discs[1]->gc = XCreateGC (st->dpy, st->b, GCForeground|GCLineWidth, &gcv); + init_spin (st->discs[1]); + + gcv.foreground = get_pixel_resource (st->dpy, st->xgwa.colormap, + "arrow1Foreground", "Foreground"); + gcv.line_width = MAX(4, (st->size / 30)); + st->discs[2]->draw = draw_thin_arrow; + st->discs[2]->gc = XCreateGC (st->dpy, st->b, GCForeground|GCLineWidth, &gcv); + init_spin (st->discs[2]); + + gcv.foreground = get_pixel_resource (st->dpy, st->xgwa.colormap, + "pointerForeground", "Foreground"); + st->ptr_gc = XCreateGC (st->dpy, st->b, GCForeground|GCLineWidth, &gcv); + + gcv.foreground = get_pixel_resource (st->dpy, st->xgwa.colormap, + "background", "Background"); + st->erase_gc = XCreateGC (st->dpy, st->b, GCForeground, &gcv); + + if (st->ba) XFillRectangle (st->dpy, st->ba, st->erase_gc, 0, 0, st->size2, st->size2); + if (st->bb) XFillRectangle (st->dpy, st->bb, st->erase_gc, 0, 0, st->size2, st->size2); + + return st; +} + +static unsigned long +compass_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + XFillRectangle (st->dpy, st->b, st->erase_gc, 0, 0, st->xgwa.width, st->xgwa.height); + + draw_compass (st); + draw_pointer (st); + +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + if (st->backb) + { + XdbeSwapInfo info[1]; + info[0].swap_window = st->window; + info[0].swap_action = XdbeUndefined; + XdbeSwapBuffers (st->dpy, info, 1); + } + else +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + if (st->dbuf) + { + XCopyArea (st->dpy, st->b, st->window, st->erase_gc, 0, 0, + st->size2, st->size2, + st->xgwa.width/2 - st->x, + st->xgwa.height/2 - st->y); + st->b = (st->b == st->ba ? st->bb : st->ba); + } + + return st->delay; +} + +static void +compass_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + st->size2 = MIN(st->xgwa.width, st->xgwa.height); + st->x = st->xgwa.width/2; + st->y = st->xgwa.height/2; +} + +static Bool +compass_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +compass_free (Display *dpy, Window window, void *closure) +{ +} + + + +static const char *compass_defaults [] = { + ".background: #000000", + ".foreground: #DDFFFF", + "*arrow1Foreground: #FFF66A", + "*arrow2Foreground: #F7D64A", + "*pointerForeground: #FF0000", + "*delay: 20000", + "*doubleBuffer: True", +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + "*useDBE: True", +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + 0 +}; + +static XrmOptionDescRec compass_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-db", ".doubleBuffer", XrmoptionNoArg, "True" }, + { "-no-db", ".doubleBuffer", XrmoptionNoArg, "False" }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("Compass", compass) -- cgit v1.2.3-55-g7522