X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fpiecewise.c;h=09fc4b621609ae0e2e371759a8c4562500f6b59c;hp=e0de4c65e5cb7219bf791b745c1c60b916497701;hb=49f5b54f312fe4ac2e9bc47581a72451bd0e8439;hpb=ccb7f4903325f92555a9722bba74b58346654ba0 diff --git a/hacks/piecewise.c b/hacks/piecewise.c index e0de4c65..09fc4b62 100644 --- a/hacks/piecewise.c +++ b/hacks/piecewise.c @@ -25,21 +25,100 @@ #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; @@ -56,7 +135,7 @@ tree *splay(cut c, tree *t) { /* top-down splaying loop */ for (;;) { - v = c(x); + v = c(st, x); if (v == 0) break; /*** success ***/ else if (v < 0) { @@ -64,7 +143,7 @@ tree *splay(cut c, tree *t) { if (!y) break; /*** trivial ***/ else { - vv = c(y); + vv = c(st, y); if (vv == 0) { *rl = x; /*** zig ***/ rl = &x->l; @@ -110,7 +189,7 @@ tree *splay(cut c, tree *t) { if (!y) break; /*** trivial ***/ else { - vv = c(y); + vv = c(st, y); if (vv == 0) { *lr = x; /*** zig ***/ lr = &x->r; @@ -161,7 +240,8 @@ tree *splay(cut c, tree *t) { return x; } -tree *splay_min(tree *t) { +static tree *splay_min(tree *t) +{ tree *r, **rl; tree *x, *y, *z; @@ -200,7 +280,8 @@ tree *splay_min(tree *t) { return x; } -tree *splay_max(tree *t) { +static tree *splay_max(tree *t) +{ tree *l, **lr; tree *x, *y, *z; @@ -241,39 +322,16 @@ tree *splay_max(tree *t) { /******** 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; @@ -282,16 +340,17 @@ inline void fringe_add_intersection(fringe *f, double x, double y) { 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; @@ -325,12 +384,14 @@ circle *init_circles(int n, int w, int h) { } /* 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; @@ -353,33 +414,21 @@ void move_circle(circle *c, int w, int h) { /******** 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))) { @@ -404,7 +453,8 @@ void event_insert(event **eq, event *e) { } } -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; @@ -412,10 +462,11 @@ void circle_start_event(event **eq, circle *c) { 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; @@ -423,10 +474,11 @@ void circle_finish_event(event **eq, circle *c) { 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; @@ -437,7 +489,8 @@ event *event_next(event **eq) { } } -void event_shred(event *e) { +static void event_shred(event *e) +{ if (e) { event_shred(e->l); event_shred(e->r); @@ -447,11 +500,13 @@ void event_shred(event *e) { /******** 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; @@ -490,7 +545,7 @@ void fringe_intersect(event **eq, double y, fringe *lo, fringe *hi) { 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)) { @@ -517,55 +572,56 @@ void fringe_intersect(event **eq, double y, fringe *lo, fringe *hi) { #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; @@ -573,9 +629,9 @@ fringe *fringe_start(event **eq, fringe *f, double x, double y, fringe *lo, frin 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; @@ -584,25 +640,22 @@ fringe *fringe_start(event **eq, fringe *f, double x, double y, fringe *lo, frin } } -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; @@ -612,12 +665,13 @@ int fringe_double_splay(fringe *f, double x, double y, fringe *lo, fringe *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; @@ -625,8 +679,9 @@ fringe *fringe_cross(event **eq, fringe *f, double x, double y, fringe *lo, frin 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; @@ -635,7 +690,7 @@ fringe *fringe_finish(event **eq, fringe *f, double x, double y, fringe *lo, fri 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; @@ -644,7 +699,8 @@ fringe *fringe_finish(event **eq, fringe *f, double x, double y, fringe *lo, fri /******** 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; @@ -663,22 +719,22 @@ void sweep(int n, circle *c) { eq = 0; for (i=0;ikind) { 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; } @@ -688,7 +744,8 @@ void sweep(int n, circle *c) { /******** 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; @@ -715,18 +772,16 @@ void adjust_circle_visibility(circle *c) { 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); @@ -736,15 +791,15 @@ void draw_circle(Display *dpy, Drawable w, GC gc, circle *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); \ } \ } @@ -758,42 +813,6 @@ void draw_circle(Display *dpy, Drawable w, GC gc, circle *c) { /******** 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) { @@ -812,109 +831,165 @@ 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;idpy, st->b, st->erase_gc, 0, 0, st->xgwa.width, st->xgwa.height); + + sweep(st, st->count, st->circles); + for (i=0;icount;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) +{ +} + +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: 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 + }; + +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)