#define X_PI (180 * 64)
-/******** splaying code */
+#define START 0
+#define CROSS 1
+#define FINISH 2
+
+#define ARC_BUFFER_SIZE 256
+
typedef struct _tree {
struct _tree *l, *r; /* left and right children */
/* extra stuff would go here */
} tree;
-typedef int (*cut)(tree*); /* cut x is <, =, or > 0 given a <, =, or > x for some a */
+
+struct _fringe;
+
+typedef struct _circle {
+ int r; /* radius */
+ double x, y; /* position */
+ double dx, dy; /* velocity */
+
+ int visible; /* default visibility */
+ struct _fringe *lo, *hi; /* lo and hi fringes */
+
+ int ni; /* number of intersections */
+ int *i; /* sorted intersection list */
+ } circle;
+
+typedef struct _fringe {
+ struct _fringe *l, *r; /* left and right children for splay trees */
+
+ circle *c; /* associated circle */
+ int side; /* 0 for lo, 1 for hi */
+
+ int mni; /* size of intersection array */
+ int ni; /* number of intersections */
+ int *i; /* sorted intersection list */
+ } fringe;
+
+
+typedef struct _event {
+ struct _event *l, *r; /* left and right children for splay tree */
+
+ int kind; /* type of event */
+ double x, y; /* position */
+ fringe *lo, *hi; /* fringes */
+ } event;
+
+
+struct state {
+ Display *dpy;
+ Window window;
+
+ double event_cut_y;
+
+ double fringe_start_cut_x;
+ double fringe_start_cut_y;
+
+ double fringe_double_cut_x;
+ double fringe_double_cut_y;
+ fringe *fringe_double_cut_lo;
+ fringe *fringe_double_cut_hi;
+
+ int arc_buffer_count;
+ XArc arc_buffer[ARC_BUFFER_SIZE];
+
+ Bool dbuf;
+ XColor *colors;
+ XGCValues gcv;
+ GC erase_gc, draw_gc;
+ XWindowAttributes xgwa;
+ Pixmap b, ba, bb; /* double-buffering pixmap */
+
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+ XdbeBackBuffer backb;
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
+
+ int count, delay, ncolors, colorspeed, color_index, flags, iterations;
+ int color_iterations;
+ circle *circles;
+};
+
+typedef int (*cut)(struct state *, tree*); /* cut x is <, =, or > 0 given a <, =, or > x for some a */
+
+
+
+/******** splaying code */
/* Top-down splay routine. Reference:
* "Self-adjusting Binary Search Trees", Sleator and Tarjan,
* JACM Volume 32, No 3, July 1985, pp 652-686.
* See page 668 for specific splay transformations */
-tree *splay(cut c, tree *t) {
+static tree *splay(struct state *st, cut c, tree *t)
+{
int v, vv;
tree *l, *r;
tree **lr, **rl;
/* top-down splaying loop */
for (;;) {
- v = c(x);
+ v = c(st, x);
if (v == 0)
break; /*** success ***/
else if (v < 0) {
if (!y)
break; /*** trivial ***/
else {
- vv = c(y);
+ vv = c(st, y);
if (vv == 0) {
*rl = x; /*** zig ***/
rl = &x->l;
if (!y)
break; /*** trivial ***/
else {
- vv = c(y);
+ vv = c(st, y);
if (vv == 0) {
*lr = x; /*** zig ***/
lr = &x->r;
return x;
}
-tree *splay_min(tree *t) {
+static tree *splay_min(tree *t)
+{
tree *r, **rl;
tree *x, *y, *z;
return x;
}
-tree *splay_max(tree *t) {
+static tree *splay_max(tree *t)
+{
tree *l, **lr;
tree *x, *y, *z;
/******** circles and fringe */
-struct _fringe;
-
-typedef struct _circle {
- int r; /* radius */
- double x, y; /* position */
- double dx, dy; /* velocity */
-
- int visible; /* default visibility */
- struct _fringe *lo, *hi; /* lo and hi fringes */
-
- int ni; /* number of intersections */
- int *i; /* sorted intersection list */
- } circle;
-
-typedef struct _fringe {
- struct _fringe *l, *r; /* left and right children for splay trees */
-
- circle *c; /* associated circle */
- int side; /* 0 for lo, 1 for hi */
-
- int mni; /* size of intersection array */
- int ni; /* number of intersections */
- int *i; /* sorted intersection list */
- } fringe;
-
-inline double fringe_x(fringe *f, double y) {
+static inline double fringe_x(fringe *f, double y)
+{
double dy, d;
dy = f->c->y - y;
d = sqrt(f->c->r * f->c->r - dy * dy);
return f->side ? f->c->x + d : f->c->x - d;
}
-inline void fringe_add_intersection(fringe *f, double x, double y) {
+static inline void fringe_add_intersection(fringe *f, double x, double y)
+{
f->ni++;
if (f->mni < f->ni) {
f->mni += 2;
f->i[f->ni-1] = rint(atan2(y - f->c->y, x - f->c->x) * X_PI / M_PI);
}
-circle *init_circles(int n, int w, int h) {
+static circle *init_circles(struct state *st, int n, int w, int h)
+{
int i, r0, dr, speed;
double v, a;
double minradius, maxradius;
fringe *s = malloc(sizeof(fringe) * n * 2); /* never freed */
circle *c = malloc(sizeof(circle) * n);
- speed = get_integer_resource("speed", "Speed");
- minradius = get_float_resource("minradius", "Float");
- maxradius = get_float_resource("maxradius", "Float");
+ speed = get_integer_resource(st->dpy, "speed", "Speed");
+ minradius = get_float_resource(st->dpy, "minradius", "Float");
+ maxradius = get_float_resource(st->dpy, "maxradius", "Float");
if (maxradius < minradius)
maxradius = minradius;
dr = floor(maxradius * h) - r0 + 1;
for (i=0;i<n;i++) {
- c[i].r = r0 + random() % dr;
+ c[i].r = r0 + ((dr > 0) ? random() % dr : 0);
c[i].x = c[i].r + frand(w - 1 - 2 * c[i].r);
c[i].y = c[i].r + frand(h - 1 - 2 * c[i].r);
c[i].visible = random() & 1;
}
/* this is a hack, but I guess that's what I writing anyways */
-void tweak_circle(circle *c) {
+static void tweak_circle(circle *c)
+{
c->x += frand(2) - 1;
c->y += frand(1) + 0.1;
}
-void move_circle(circle *c, int w, int h) {
+static void move_circle(circle *c, int w, int h)
+{
c->x += c->dx;
if (c->x < c->r) {
c->x = c->r;
/******** event queue */
-#define START 0
-#define CROSS 1
-#define FINISH 2
-
-typedef struct _event {
- struct _event *l, *r; /* left and right children for splay tree */
-
- int kind; /* type of event */
- double x, y; /* position */
- fringe *lo, *hi; /* fringes */
- } event;
-
-static double event_cut_y;
-
-int event_cut(event *e) {
- return event_cut_y == e->y ? 0 : event_cut_y < e->y ? -1 : 1;
+static int event_cut(struct state *st, event *e)
+{
+ return st->event_cut_y == e->y ? 0 : st->event_cut_y < e->y ? -1 : 1;
}
-void event_insert(event **eq, event *e) {
+static void event_insert(struct state *st, event **eq, event *e)
+{
if (!*eq) {
e->l = e->r = 0;
*eq = e;
return; /* avoid leak */
}
- event_cut_y = e->y;
- *eq = (event*)splay((cut)event_cut, (tree*)*eq);
+ st->event_cut_y = e->y;
+ *eq = (event*)splay(st, (cut)event_cut, (tree*)*eq);
if (e->y == (*eq)->y) {
if (!((e->lo == (*eq)->lo && e->hi == (*eq)->hi) || (e->lo == (*eq)->hi && e->hi == (*eq)->lo))) {
}
}
-void circle_start_event(event **eq, circle *c) {
+static void circle_start_event(struct state *st, event **eq, circle *c)
+{
event *s;
s = malloc(sizeof(event));
s->kind = START;
s->y = c->y - c->r;
s->lo = c->lo;
s->hi = c->hi;
- event_insert(eq, s);
+ event_insert(st, eq, s);
}
-void circle_finish_event(event **eq, circle *c) {
+static void circle_finish_event(struct state *st, event **eq, circle *c)
+{
event *f;
f = malloc(sizeof(event));
f->kind = FINISH;
f->y = c->y + c->r;
f->lo = c->lo;
f->hi = c->hi;
- event_insert(eq, f);
+ event_insert(st, eq, f);
}
-event *event_next(event **eq) {
+static event *event_next(event **eq)
+{
event *e;
if (!*eq)
return 0;
}
}
-void event_shred(event *e) {
+static void event_shred(event *e)
+{
if (e) {
event_shred(e->l);
event_shred(e->r);
/******** fringe intersection */
-inline int check_fringe_intersection(double ye, fringe *lo, fringe *hi, double x, double y) {
+static inline int check_fringe_intersection(double ye, fringe *lo, fringe *hi, double x, double y)
+{
return ye <= y && ((x < lo->c->x) ^ lo->side) && ((x < hi->c->x) ^ hi->side);
}
-void fringe_intersect(event **eq, double y, fringe *lo, fringe *hi) {
+static void fringe_intersect(struct state *st, event **eq, double y, fringe *lo, fringe *hi)
+{
event *e;
double dx, dy, sd, rs, rd, d, sx, sy, rp, sqd;
double x1, y1, x2, y2;
e->kind = CROSS; \
e->x = xi; e->y = yi; \
e->lo = ilo; e->hi = ihi; \
- event_insert(eq, e); \
+ event_insert(st, eq, e); \
}
if (CHECK(x1, y1)) {
#define PANIC ((fringe*)1) /* by alignment, no fringe should every be 1 */
-fringe *check_lo(event **eq, double y, fringe *f, fringe *hi) {
+static fringe *check_lo(struct state *st, event **eq, double y, fringe *f, fringe *hi)
+{
if (f) {
f = (fringe*)splay_max((tree*)f);
- fringe_intersect(eq, y, f, hi);
+ fringe_intersect(st, eq, y, f, hi);
}
return f;
}
-fringe *check_hi(event **eq, double y, fringe *lo, fringe *f) {
+static fringe *check_hi(struct state *st, event **eq, double y, fringe *lo, fringe *f)
+{
if (f) {
f = (fringe*)splay_min((tree*)f);
- fringe_intersect(eq, y, lo, f);
+ fringe_intersect(st, eq, y, lo, f);
}
return f;
}
-double fringe_start_cut_x;
-double fringe_start_cut_y;
-
-int fringe_start_cut(fringe *f) {
- double x = fringe_x(f, fringe_start_cut_y);
- return fringe_start_cut_x == x ? 0 : fringe_start_cut_x < x ? -1 : 1;
+static int fringe_start_cut(struct state *st, fringe *f)
+{
+ double x = fringe_x(f, st->fringe_start_cut_y);
+ return st->fringe_start_cut_x == x ? 0 : st->fringe_start_cut_x < x ? -1 : 1;
}
-fringe *fringe_start(event **eq, fringe *f, double x, double y, fringe *lo, fringe *hi) {
+static fringe *fringe_start(struct state *st, event **eq, fringe *f, double x, double y, fringe *lo, fringe *hi)
+{
double sx;
if (!f) {
- circle_finish_event(eq, lo->c);
+ circle_finish_event(st, eq, lo->c);
lo->l = 0;
lo->r = hi;
hi->l = hi->r = 0;
return lo;
}
- fringe_start_cut_x = x;
- fringe_start_cut_y = y;
- f = (fringe*)splay((cut)fringe_start_cut, (tree*)f);
+ st->fringe_start_cut_x = x;
+ st->fringe_start_cut_y = y;
+ f = (fringe*)splay(st, (cut)fringe_start_cut, (tree*)f);
sx = fringe_x(f, y);
if (x == sx) { /* time to cheat my way out of handling degeneracies */
tweak_circle(lo->c);
- circle_start_event(eq, lo->c);
+ circle_start_event(st, eq, lo->c);
return f;
}
else if (x < sx) {
- circle_finish_event(eq, lo->c);
- f->l = check_lo(eq, y, f->l, lo);
- fringe_intersect(eq, y, hi, f);
+ circle_finish_event(st, eq, lo->c);
+ f->l = check_lo(st, eq, y, f->l, lo);
+ fringe_intersect(st, eq, y, hi, f);
lo->l = f->l;
lo->r = f;
f->l = hi;
return lo;
}
else {
- circle_finish_event(eq, lo->c);
- fringe_intersect(eq, y, f, lo);
- f->r = check_hi(eq, y, hi, f->r);
+ circle_finish_event(st, eq, lo->c);
+ fringe_intersect(st, eq, y, f, lo);
+ f->r = check_hi(st, eq, y, hi, f->r);
hi->r = f->r;
hi->l = f;
f->r = lo;
}
}
-double fringe_double_cut_x;
-double fringe_double_cut_y;
-fringe *fringe_double_cut_lo;
-fringe *fringe_double_cut_hi;
-
-int fringe_double_cut(fringe *f) {
+static int fringe_double_cut(struct state *st, fringe *f)
+{
double x;
- if (f == fringe_double_cut_lo || f == fringe_double_cut_hi)
+ if (f == st->fringe_double_cut_lo || f == st->fringe_double_cut_hi)
return 0;
- x = fringe_x(f, fringe_double_cut_y);
- return fringe_double_cut_x == x ? 0 : fringe_double_cut_x < x ? -1 : 1;
+ x = fringe_x(f, st->fringe_double_cut_y);
+ return st->fringe_double_cut_x == x ? 0 : st->fringe_double_cut_x < x ? -1 : 1;
}
-int fringe_double_splay(fringe *f, double x, double y, fringe *lo, fringe *hi) {
- fringe_double_cut_x = x;
- fringe_double_cut_y = y;
- fringe_double_cut_lo = lo;
- fringe_double_cut_hi = hi;
- f = (fringe*)splay((cut)fringe_double_cut, (tree*)f);
+static int fringe_double_splay(struct state *st, fringe *f, double x, double y, fringe *lo, fringe *hi)
+{
+ st->fringe_double_cut_x = x;
+ st->fringe_double_cut_y = y;
+ st->fringe_double_cut_lo = lo;
+ st->fringe_double_cut_hi = hi;
+ f = (fringe*)splay(st, (cut)fringe_double_cut, (tree*)f);
if (f == lo)
return (f->r = (fringe*)splay_min((tree*)f->r)) == hi;
return 0;
}
-fringe *fringe_cross(event **eq, fringe *f, double x, double y, fringe *lo, fringe *hi) {
+static fringe *fringe_cross(struct state *st, event **eq, fringe *f, double x, double y, fringe *lo, fringe *hi)
+{
fringe *l, *r;
- if (!fringe_double_splay(f, x, y, lo, hi))
+ if (!fringe_double_splay(st, f, x, y, lo, hi))
return PANIC;
- l = check_lo(eq, y, lo->l, hi);
- r = check_hi(eq, y, lo, hi->r);
+ l = check_lo(st, eq, y, lo->l, hi);
+ r = check_hi(st, eq, y, lo, hi->r);
lo->l = hi;
lo->r = r;
hi->l = l;
return lo;
}
-fringe *fringe_finish(event **eq, fringe *f, double x, double y, fringe *lo, fringe *hi) {
- if (!fringe_double_splay(f, x, y, lo, hi))
+static fringe *fringe_finish(struct state *st, event **eq, fringe *f, double x, double y, fringe *lo, fringe *hi)
+{
+ if (!fringe_double_splay(st, f, x, y, lo, hi))
return PANIC;
else if (!lo->l)
return hi->r;
else {
lo->l = (fringe*)splay_max((tree*)lo->l);
hi->r = (fringe*)splay_min((tree*)hi->r);
- fringe_intersect(eq, y, lo->l, hi->r);
+ fringe_intersect(st, eq, y, lo->l, hi->r);
lo->l->r = hi->r;
hi->r->l = 0;
return lo->l;
/******** plane sweep */
-void sweep(int n, circle *c) {
+static void sweep(struct state *st, int n, circle *c)
+{
int i;
event *eq, *e;
fringe *f;
eq = 0;
for (i=0;i<n;i++)
- circle_start_event(&eq, c+i);
+ circle_start_event(st, &eq, c+i);
f = 0;
while ((e = event_next(&eq))) {
switch (e->kind) {
case START:
- f = fringe_start(&eq, f, e->x, e->y, e->lo, e->hi);
+ f = fringe_start(st, &eq, f, e->x, e->y, e->lo, e->hi);
break;
case CROSS:
- f = fringe_cross(&eq, f, e->x, e->y, e->lo, e->hi);
+ f = fringe_cross(st, &eq, f, e->x, e->y, e->lo, e->hi);
CHECK_PANIC();
fringe_add_intersection(e->lo, e->x, e->y);
fringe_add_intersection(e->hi, e->x, e->y);
break;
case FINISH:
- f = fringe_finish(&eq, f, e->x, e->y, e->lo, e->hi);
+ f = fringe_finish(st, &eq, f, e->x, e->y, e->lo, e->hi);
CHECK_PANIC();
break;
}
/******** circle drawing */
-void adjust_circle_visibility(circle *c) {
+static void adjust_circle_visibility(circle *c)
+{
int i, j, n, a;
int *in;
n = c->lo->ni + c->hi->ni;
c->i = in;
}
-#define ARC_BUFFER_SIZE 256
-int arc_buffer_count = 0;
-XArc arc_buffer[ARC_BUFFER_SIZE];
-
-void flush_arc_buffer(Display *dpy, Drawable w, GC gc) {
- if (arc_buffer_count) {
- XDrawArcs(dpy, w, gc, arc_buffer, arc_buffer_count);
- arc_buffer_count = 0;
+static void flush_arc_buffer(struct state *st, Drawable w, GC gc)
+{
+ if (st->arc_buffer_count) {
+ XDrawArcs(st->dpy, w, gc, st->arc_buffer, st->arc_buffer_count);
+ st->arc_buffer_count = 0;
}
}
-void draw_circle(Display *dpy, Drawable w, GC gc, circle *c) {
+static void draw_circle(struct state *st, Drawable w, GC gc, circle *c)
+{
int i, xi, yi, di;
adjust_circle_visibility(c);
#define ARC(p, a1, a2) { \
if (((p) & 1) ^ c->visible) { \
- arc_buffer[arc_buffer_count].x = xi; \
- arc_buffer[arc_buffer_count].y = yi; \
- arc_buffer[arc_buffer_count].width = di; \
- arc_buffer[arc_buffer_count].height = di; \
- arc_buffer[arc_buffer_count].angle1 = -(a1); \
- arc_buffer[arc_buffer_count].angle2 = (a1) - (a2); \
- arc_buffer_count++; \
- if (arc_buffer_count == ARC_BUFFER_SIZE) \
- flush_arc_buffer(dpy, w, gc); \
+ st->arc_buffer[st->arc_buffer_count].x = xi; \
+ st->arc_buffer[st->arc_buffer_count].y = yi; \
+ st->arc_buffer[st->arc_buffer_count].width = di; \
+ st->arc_buffer[st->arc_buffer_count].height = di; \
+ st->arc_buffer[st->arc_buffer_count].angle1 = -(a1); \
+ st->arc_buffer[st->arc_buffer_count].angle2 = (a1) - (a2); \
+ st->arc_buffer_count++; \
+ if (st->arc_buffer_count == ARC_BUFFER_SIZE) \
+ flush_arc_buffer(st, w, gc); \
} \
}
/******** toplevel */
-char *progclass = "Piecewise";
-
-char *defaults [] = {
- ".background: black",
- ".foreground: white",
- "*delay: 5000",
- "*speed: 15",
- "*ncolors: 256",
- ".colorspeed: 10",
-
- ".count: 32",
- ".minradius: 0.05",
- ".maxradius: 0.2",
-
- "*doubleBuffer: True",
-#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
- "*useDBE: True",
-#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
- 0
- };
-
-XrmOptionDescRec options [] = {
- { "-delay", ".delay", XrmoptionSepArg, 0 },
- { "-ncolors", ".ncolors", XrmoptionSepArg, 0 },
- { "-speed", ".speed", XrmoptionSepArg, 0 },
- { "-colorspeed", ".colorspeed", XrmoptionSepArg, 0 },
-
- { "-count", ".count", XrmoptionSepArg, 0 },
- { "-minradius", ".minradius", XrmoptionSepArg, 0 },
- { "-maxradius", ".maxradius", XrmoptionSepArg, 0 },
-
- { "-db", ".doubleBuffer", XrmoptionNoArg, "True" },
- { "-no-db", ".doubleBuffer", XrmoptionNoArg, "False" },
- { 0, 0, 0, 0 }
- };
-
static void
check_for_leaks (void)
{
#endif /* HAVE_SBRK */
}
+static void *
+piecewise_init (Display *dd, Window ww)
+{
+ struct state *st = (struct state *) calloc (1, sizeof(*st));
+ st->dpy = dd;
+ st->window = ww;
-void screenhack(Display *dpy, Window window) {
- int i;
- Bool dbuf;
- XColor *colors;
- XGCValues gcv;
- GC erase_gc, draw_gc;
- XWindowAttributes xgwa;
- Pixmap b = 0, ba = 0, bb = 0; /* double-buffering pixmap */
-
-#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
- XdbeBackBuffer backb = 0;
-#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
+ st->count = get_integer_resource(st->dpy, "count", "Integer");
+ st->delay = get_integer_resource(st->dpy, "delay", "Integer");
+ st->ncolors = get_integer_resource(st->dpy, "ncolors", "Integer");
+ st->colorspeed = get_integer_resource(st->dpy, "colorspeed", "Integer");
+ st->dbuf = get_boolean_resource(st->dpy, "doubleBuffer", "Boolean");
- int count, delay, ncolors, colorspeed, color_index, flags, iterations;
- int color_iterations;
- circle *circles;
-
- count = get_integer_resource("count", "Integer");
- delay = get_integer_resource("delay", "Integer");
- ncolors = get_integer_resource("ncolors", "Integer");
- colorspeed = get_integer_resource("colorspeed", "Integer");
- dbuf = get_boolean_resource("doubleBuffer", "Boolean");
+# ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */
+ st->dbuf = False;
+# endif
- color_iterations = colorspeed ? 100 / colorspeed : 100000;
- if (!color_iterations)
- color_iterations = 1;
+ st->color_iterations = st->colorspeed ? 100 / st->colorspeed : 100000;
+ if (!st->color_iterations)
+ st->color_iterations = 1;
- XGetWindowAttributes(dpy, window, &xgwa);
- colors = calloc(sizeof(XColor), ncolors);
+ XGetWindowAttributes(st->dpy, st->window, &st->xgwa);
+ st->colors = calloc(sizeof(XColor), st->ncolors);
- if (get_boolean_resource("mono", "Boolean")) {
+ if (get_boolean_resource(st->dpy, "mono", "Boolean")) {
MONO:
- ncolors = 1;
- colors[0].pixel = get_pixel_resource("foreground", "Foreground", dpy, xgwa.colormap);
+ st->ncolors = 1;
+ st->colors[0].pixel = get_pixel_resource(st->dpy, st->xgwa.colormap, "foreground", "Foreground");
}
else {
- make_color_loop(dpy, xgwa.colormap, 0, 1, 1, 120, 1, 1, 240, 1, 1, colors, &ncolors, True, False);
- if (ncolors < 2)
+ make_color_loop(st->dpy, st->xgwa.colormap, 0, 1, 1, 120, 1, 1, 240, 1, 1, st->colors, &st->ncolors, True, False);
+ if (st->ncolors < 2)
goto MONO;
}
- if (dbuf) {
+ if (st->dbuf) {
#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
- b = backb = xdbe_get_backbuffer(dpy, window, XdbeUndefined);
+ st->b = st->backb = xdbe_get_backbuffer(st->dpy, st->window, XdbeUndefined);
#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
- if (!b) {
- ba = XCreatePixmap(dpy, window, xgwa.width, xgwa.height,xgwa.depth);
- bb = XCreatePixmap(dpy, window, xgwa.width, xgwa.height,xgwa.depth);
- b = ba;
+ if (!st->b) {
+ st->ba = XCreatePixmap(st->dpy, st->window, st->xgwa.width, st->xgwa.height,st->xgwa.depth);
+ st->bb = XCreatePixmap(st->dpy, st->window, st->xgwa.width, st->xgwa.height,st->xgwa.depth);
+ st->b = st->ba;
}
}
else
- b = window;
+ st->b = st->window;
/* erasure gc */
- gcv.foreground = get_pixel_resource("background", "Background", dpy, xgwa.colormap);
- erase_gc = XCreateGC (dpy, b, GCForeground, &gcv);
+ st->gcv.foreground = get_pixel_resource(st->dpy, st->xgwa.colormap, "background", "Background");
+ st->erase_gc = XCreateGC (st->dpy, st->b, GCForeground, &st->gcv);
/* drawing gc */
- flags = GCForeground;
- color_index = random() % ncolors;
- gcv.foreground = colors[color_index].pixel;
- draw_gc = XCreateGC(dpy, b, flags, &gcv);
+ st->flags = GCForeground;
+ st->color_index = random() % st->ncolors;
+ st->gcv.foreground = st->colors[st->color_index].pixel;
+ st->draw_gc = XCreateGC(st->dpy, st->b, st->flags, &st->gcv);
/* initialize circles */
- circles = init_circles(count, xgwa.width, xgwa.height);
+ st->circles = init_circles(st, st->count, st->xgwa.width, st->xgwa.height);
- iterations = 0;
- for (;;) {
- XFillRectangle (dpy, b, erase_gc, 0, 0, xgwa.width, xgwa.height);
+ st->iterations = 0;
- sweep(count, circles);
- for (i=0;i<count;i++) {
- draw_circle(dpy, b, draw_gc, circles+i);
- move_circle(circles+i, xgwa.width, xgwa.height);
- }
- flush_arc_buffer(dpy, b, draw_gc);
+ return st;
+}
- if (++iterations % color_iterations == 0) {
- color_index = (color_index + 1) % ncolors;
- XSetForeground(dpy, draw_gc, colors[color_index].pixel);
- }
+static unsigned long
+piecewise_draw (Display *dpy, Window window, void *closure)
+{
+ struct state *st = (struct state *) closure;
+ int i;
+
+ XFillRectangle (st->dpy, st->b, st->erase_gc, 0, 0, st->xgwa.width, st->xgwa.height);
+
+ sweep(st, st->count, st->circles);
+ for (i=0;i<st->count;i++) {
+ draw_circle(st, st->b, st->draw_gc, st->circles+i);
+ move_circle(st->circles+i, st->xgwa.width, st->xgwa.height);
+ }
+ flush_arc_buffer(st, st->b, st->draw_gc);
+
+ if (++st->iterations % st->color_iterations == 0) {
+ st->color_index = (st->color_index + 1) % st->ncolors;
+ XSetForeground(st->dpy, st->draw_gc, st->colors[st->color_index].pixel);
+ }
#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
- if (backb) {
- XdbeSwapInfo info[1];
- info[0].swap_window = window;
- info[0].swap_action = XdbeUndefined;
- XdbeSwapBuffers (dpy, info, 1);
- }
- else
+ 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 (dbuf) {
- XCopyArea (dpy, b, window, erase_gc, 0, 0, xgwa.width, xgwa.height, 0, 0);
- b = (b == ba ? bb : ba);
- }
-
- XSync(dpy, False);
- screenhack_handle_events(dpy);
- if (delay)
- usleep(delay);
- check_for_leaks();
+ if (st->dbuf) {
+ XCopyArea (st->dpy, st->b, st->window, st->erase_gc, 0, 0, st->xgwa.width, st->xgwa.height, 0, 0);
+ st->b = (st->b == st->ba ? st->bb : st->ba);
}
- }
+
+ check_for_leaks();
+ return st->delay;
+}
+
+static void
+piecewise_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);
+}
+
+static Bool
+piecewise_event (Display *dpy, Window window, void *closure, XEvent *event)
+{
+ return False;
+}
+
+static void
+piecewise_free (Display *dpy, Window window, void *closure)
+{
+ struct state *st = (struct state *) closure;
+ free (st);
+}
+
+
+
+static const char *piecewise_defaults [] = {
+ ".background: black",
+ ".foreground: white",
+ "*delay: 10000",
+ "*speed: 15",
+ "*ncolors: 256",
+ ".colorspeed: 10",
+
+ ".count: 32",
+ ".minradius: 0.05",
+ ".maxradius: 0.2",
+
+ "*doubleBuffer: True",
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+ "*useDBE: True",
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
+ 0
+ };
+
+static XrmOptionDescRec piecewise_options [] = {
+ { "-delay", ".delay", XrmoptionSepArg, 0 },
+ { "-ncolors", ".ncolors", XrmoptionSepArg, 0 },
+ { "-speed", ".speed", XrmoptionSepArg, 0 },
+ { "-colorspeed", ".colorspeed", XrmoptionSepArg, 0 },
+
+ { "-count", ".count", XrmoptionSepArg, 0 },
+ { "-minradius", ".minradius", XrmoptionSepArg, 0 },
+ { "-maxradius", ".maxradius", XrmoptionSepArg, 0 },
+
+ { "-db", ".doubleBuffer", XrmoptionNoArg, "True" },
+ { "-no-db", ".doubleBuffer", XrmoptionNoArg, "False" },
+ { 0, 0, 0, 0 }
+ };
+
+
+XSCREENSAVER_MODULE ("Piecewise", piecewise)