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

Revision 20148, 20.9 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/* piecewise, 21jan2003
2 * Geoffrey Irving <irving@caltech.edu>
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation.  No representations are made about the suitability of this
9 * software for any purpose.  It is provided "as is" without express or
10 * implied warranty.
11 */
12
13#include <stdarg.h>
14#include <math.h>
15#include "screenhack.h"
16
17#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
18# include "xdbe.h"
19#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
20
21#define X_PI (180 * 64)
22
23/******** splaying code */
24
25typedef struct _tree {
26  struct _tree *l, *r;   /* left and right children */
27                         /* extra stuff would go here */
28  } tree;
29
30typedef int (*cut)(tree*);    /* cut x is <, =, or > 0 given a <, =, or > x for some a */
31
32/* Top-down splay routine.  Reference:
33 *   "Self-adjusting Binary Search Trees", Sleator and Tarjan,
34 *   JACM Volume 32, No 3, July 1985, pp 652-686.
35 * See page 668 for specific splay transformations */
36
37tree *splay(cut c, tree *t) {
38  int v, vv;
39  tree *l, *r;
40  tree **lr, **rl;
41  tree *x, *y, *z;
42
43  if (!t)
44    return 0;
45
46  /* initialization */
47  x = t;
48  l = r = 0;
49  lr = &l;
50  rl = &r;
51
52  /* top-down splaying loop */
53  for (;;) {
54    v = c(x);
55    if (v == 0)
56      break;               /*** success ***/
57    else if (v < 0) {
58      y = x->l;
59      if (!y)
60        break;             /*** trivial ***/
61      else {
62        vv = c(y);
63        if (vv == 0) {
64          *rl = x;         /*** zig ***/
65          rl = &x->l;
66          x = y;
67          break;
68          }
69        else if (vv < 0) {
70          z = y->l;
71          if (!z) {
72            *rl = x;       /*** zig ***/
73            rl = &x->l;
74            x = y;
75            break;
76            }
77          else {
78            x->l = y->r;   /*** zig-zig ***/
79            y->r = x;
80            *rl = y;
81            rl = &y->l;
82            x = z;
83            }
84          }
85        else { /* vv > 0 */
86          z = y->r;
87          if (!z) {
88            *rl = x;       /*** zig ***/
89            rl = &x->l;
90            x = y;
91            break;
92            }
93          else {           /*** zig-zag ***/
94            *lr = y;
95            lr = &y->r;
96            *rl = x;
97            rl = &x->l;
98            x = z;
99            }
100          }
101        }
102      }
103    else { /* v > 0 */
104      y = x->r;
105      if (!y)
106        break;             /*** trivial ***/
107      else {
108        vv = c(y);
109        if (vv == 0) {
110          *lr = x;         /*** zig ***/
111          lr = &x->r;
112          x = y;
113          break;
114          }
115        else if (vv > 0) {
116          z = y->r;
117          if (!z) {
118            *lr = x;       /*** zig ***/
119            lr = &x->r;
120            x = y;
121            break;
122            }
123          else {
124            x->r = y->l;   /*** zig-zig ***/
125            y->l = x;
126            *lr = y;
127            lr = &y->r;
128            x = z;
129            }
130          }
131        else { /* vv < 0 */
132          z = y->l;
133          if (!z) {
134            *lr = x;       /*** zig ***/
135            lr = &x->r;
136            x = y;
137            break;
138            }
139          else {           /*** zig-zag ***/
140            *rl = y;
141            rl = &y->l;
142            *lr = x;
143            lr = &x->r;
144            x = z;
145            }
146          }
147        }
148      }
149    }
150
151  /* completion */
152  *lr = x->l;
153  x->l = l;
154  *rl = x->r;
155  x->r = r;
156  return x;
157  }
158
159tree *splay_min(tree *t) {
160  tree *r, **rl;
161  tree *x, *y, *z;
162
163  if (!t)
164    return 0;
165
166  x = t;
167  r = 0;
168  rl = &r;
169
170  for (;;) {
171    y = x->l;
172    if (!y)
173      break;           /*** trivial ***/
174    else {
175      z = y->l;
176      if (!z) {
177        *rl = x;       /*** zig ***/
178        rl = &x->l;
179        x = y;
180        break;
181        }
182      else {
183        x->l = y->r;   /*** zig-zig ***/
184        y->r = x;
185        *rl = y;
186        rl = &y->l;
187        x = z;
188        }
189      }
190    }
191
192  x->l = 0;
193  *rl = x->r;
194  x->r = r;
195  return x;
196  }
197
198tree *splay_max(tree *t) {
199  tree *l, **lr;
200  tree *x, *y, *z;
201
202  if (!t)
203    return 0;
204
205  x = t;
206  l = 0;
207  lr = &l;
208
209  for (;;) {
210    y = x->r;
211    if (!y)
212      break;           /*** trivial ***/
213    else {
214      z = y->r;
215      if (!z) {
216        *lr = x;       /*** zig ***/
217        lr = &x->r;
218        x = y;
219        break;
220        }
221      else {
222        x->r = y->l;   /*** zig-zig ***/
223        y->l = x;
224        *lr = y;
225        lr = &y->r;
226        x = z;
227        }
228      }
229    }
230
231  *lr = x->l;
232  x->l = l;
233  x->r = 0;
234  return x;
235  }
236
237/******** circles and fringe */
238
239struct _fringe;
240
241typedef struct _circle {
242  int r;                    /* radius */
243  double x, y;              /* position */
244  double dx, dy;            /* velocity */
245
246  int visible;              /* default visibility */
247  struct _fringe *lo, *hi;  /* lo and hi fringes */
248
249  int ni;                   /* number of intersections */
250  int *i;                   /* sorted intersection list */
251  } circle;             
252
253typedef struct _fringe {
254  struct _fringe *l, *r;  /* left and right children for splay trees */
255
256  circle *c;              /* associated circle */
257  int side;               /* 0 for lo, 1 for hi */
258
259  int mni;                /* size of intersection array */
260  int ni;                 /* number of intersections */
261  int *i;                 /* sorted intersection list */
262  } fringe;
263
264inline double fringe_x(fringe *f, double y) {
265  double dy, d;
266  dy = f->c->y - y;
267  d = sqrt(f->c->r * f->c->r - dy * dy);
268  return f->side ? f->c->x + d : f->c->x - d;
269  }
270
271inline void fringe_add_intersection(fringe *f, double x, double y) {
272  f->ni++;
273  if (f->mni < f->ni) {
274    f->mni += 2;
275    f->i = realloc(f->i, sizeof(int) * f->mni);
276    }
277  f->i[f->ni-1] = rint(atan2(y - f->c->y, x - f->c->x) * X_PI / M_PI);
278  }
279
280circle *init_circles(int n, int w, int h) {
281  int i, r0, dr, speed;
282  double v, a;
283  double minradius, maxradius;
284  fringe *s = malloc(sizeof(fringe) * n * 2);    /* never freed */
285  circle *c = malloc(sizeof(circle) * n);
286
287  speed = get_integer_resource("speed", "Speed");
288  minradius = get_float_resource("minradius", "Float");
289  maxradius = get_float_resource("maxradius", "Float");
290  if (maxradius < minradius)
291    maxradius = minradius;
292
293  r0 = ceil(minradius * h);
294  dr = floor(maxradius * h) - r0 + 1;
295
296  for (i=0;i<n;i++) {
297    c[i].r = r0 + random() % dr;
298    c[i].x = c[i].r + frand(w - 1 - 2 * c[i].r);
299    c[i].y = c[i].r + frand(h - 1 - 2 * c[i].r);
300    c[i].visible = random() & 1;
301
302    c[i].ni = 0;
303    c[i].i = 0;
304
305    a = frand(2 * M_PI);
306    v = (1 + frand(0.5)) * speed / 10.0;
307    c[i].dx = v * cos(a);
308    c[i].dy = v * sin(a);
309
310    c[i].lo = s+i+i;
311    c[i].hi = s+i+i+1;
312    c[i].lo->c = c[i].hi->c = c+i;
313    c[i].lo->side = 0;
314    c[i].hi->side = 1;
315    c[i].lo->mni = c[i].lo->ni = c[i].hi->mni = c[i].hi->ni = 0;
316    c[i].lo->i = c[i].hi->i = 0;
317    }
318
319  return c;
320  }
321
322/* this is a hack, but I guess that's what I writing anyways */
323void tweak_circle(circle *c) {
324  c->x += frand(2) - 1;
325  c->y += frand(1) + 0.1;
326  }
327
328void move_circle(circle *c, int w, int h) {
329  c->x += c->dx;
330  if (c->x < c->r) {
331    c->x = c->r;
332    c->dx = -c->dx;
333    }
334  else if (c->x >= w - c->r) {
335    c->x = w - 1 - c->r;
336    c->dx = -c->dx;
337    }
338  c->y += c->dy;
339  if (c->y < c->r) {
340    c->y = c->r;
341    c->dy = -c->dy;
342    }
343  else if (c->y >= h - c->r) {
344    c->y = h - 1 - c->r;
345    c->dy = -c->dy;
346    }
347  }
348
349/******** event queue */
350
351#define START 0
352#define CROSS 1
353#define FINISH 2
354
355typedef struct _event {
356  struct _event *l, *r;    /* left and right children for splay tree */
357
358  int kind;                /* type of event */
359  double x, y;             /* position */
360  fringe *lo, *hi;         /* fringes */
361  } event;
362
363static double event_cut_y;
364
365int event_cut(event *e) {
366  return event_cut_y == e->y ? 0 : event_cut_y < e->y ? -1 : 1;
367  }
368
369void event_insert(event **eq, event *e) {
370  if (!*eq) {
371    e->l = e->r = 0;
372    *eq = e;
373    }
374
375  event_cut_y = e->y;
376  *eq = (event*)splay((cut)event_cut, (tree*)*eq);
377
378  if (e->y == (*eq)->y) {
379    if (!((e->lo == (*eq)->lo && e->hi == (*eq)->hi) || (e->lo == (*eq)->hi && e->hi == (*eq)->lo))) {
380      e->l = (*eq)->l;
381      e->r = 0;             /* doing this instead of dying might be dangerous */
382      (*eq)->l = e;           
383      }
384    }
385  else if (e->y < (*eq)->y) {
386    e->l = (*eq)->l;
387    e->r = *eq;
388    (*eq)->l = 0;
389    *eq = e;
390    }
391  else {
392    e->l = *eq;
393    e->r = (*eq)->r;
394    (*eq)->r = 0;
395    *eq = e;
396    }
397  }
398
399void circle_start_event(event **eq, circle *c) {
400  event *s;
401  s = malloc(sizeof(event));
402  s->kind = START;
403  s->x = c->x;
404  s->y = c->y - c->r;
405  s->lo = c->lo;
406  s->hi = c->hi;
407  event_insert(eq, s);
408  }
409
410void circle_finish_event(event **eq, circle *c) {
411  event *f;
412  f = malloc(sizeof(event));
413  f->kind = FINISH;
414  f->x = c->x;
415  f->y = c->y + c->r;
416  f->lo = c->lo;
417  f->hi = c->hi;
418  event_insert(eq, f);
419  }
420
421event *event_next(event **eq) {
422  event *e;
423  if (!*eq)
424    return 0;
425  else {
426    e = (event*)splay_min((tree*)*eq);
427    *eq = e->r;
428    return e;
429    }
430  }
431
432void event_shred(event *e) {
433  if (e) {
434    event_shred(e->l);
435    event_shred(e->r);
436    free(e);
437    }
438  }
439
440/******** fringe intersection */
441
442inline int check_fringe_intersection(double ye, fringe *lo, fringe *hi, double x, double y) {
443  return ye <= y && ((x < lo->c->x) ^ lo->side) && ((x < hi->c->x) ^ hi->side);
444  }
445
446void fringe_intersect(event **eq, double y, fringe *lo, fringe *hi) {
447  event *e;
448  double dx, dy, sd, rs, rd, d, sx, sy, rp, sqd;
449  double x1, y1, x2, y2;
450
451  if (lo->c == hi->c)
452    return;
453
454  dx = hi->c->x - lo->c->x;
455  dy = hi->c->y - lo->c->y;
456  sd = dx * dx + dy * dy;
457
458  if (sd == 0)
459    return;
460
461  rs = hi->c->r + lo->c->r;
462  rd = hi->c->r - lo->c->r;
463  d = (rd * rd - sd) * (sd - rs * rs);
464
465  if (d <= 0)
466    return;
467 
468  sd = 0.5 / sd;
469  rp = rs * rd;
470  sqd = sqrt(d);
471  sx = (lo->c->x + hi->c->x) / 2;
472  sy = (lo->c->y + hi->c->y) / 2;
473  x1 = sx + sd * (dy * sqd - dx * rp);
474  y1 = sy - sd * (dx * sqd + dy * rp);
475  x2 = sx - sd * (dy * sqd + dx * rp);
476  y2 = sy + sd * (dx * sqd - dy * rp);
477
478  #define CHECK(xi, yi) (y <= yi && ((xi < lo->c->x) ^ lo->side) && ((xi < hi->c->x) ^ hi->side))
479
480  #define ADD_CROSS(xi, yi, ilo, ihi) {  \
481    e = malloc(sizeof(event));           \
482    e->kind = CROSS;                     \
483    e->x = xi; e->y = yi;                \
484    e->lo = ilo; e->hi = ihi;            \
485    event_insert(eq, e);                 \
486    }
487
488  if (CHECK(x1, y1)) {
489    if (CHECK(x2, y2)) {
490      if (y1 < y2) {
491        ADD_CROSS(x1, y1, lo, hi);
492        ADD_CROSS(x2, y2, hi, lo);
493        }
494      else {
495        ADD_CROSS(x1, y1, hi, lo);
496        ADD_CROSS(x2, y2, lo, hi);
497        }
498      }
499    else
500      ADD_CROSS(x1, y1, lo, hi);
501    }
502  else if (CHECK(x2, y2))
503    ADD_CROSS(x2, y2, lo, hi);
504
505  return;
506  }
507
508/******** fringe trees and event handling */
509
510#define PANIC ((fringe*)1)     /* by alignment, no fringe should every be 1 */
511
512fringe *check_lo(event **eq, double y, fringe *f, fringe *hi) {
513  if (f) {
514    f = (fringe*)splay_max((tree*)f);
515    fringe_intersect(eq, y, f, hi);
516    }
517  return f;
518  }
519
520fringe *check_hi(event **eq, double y, fringe *lo, fringe *f) {
521  if (f) {
522    f = (fringe*)splay_min((tree*)f);
523    fringe_intersect(eq, y, lo, f);
524    }
525  return f;
526  }
527
528double fringe_start_cut_x;
529double fringe_start_cut_y;
530
531int fringe_start_cut(fringe *f) {
532  double x = fringe_x(f, fringe_start_cut_y);
533  return fringe_start_cut_x == x ? 0 : fringe_start_cut_x < x ? -1 : 1;
534  }
535
536fringe *fringe_start(event **eq, fringe *f, double x, double y, fringe *lo, fringe *hi) {
537  double sx;
538
539  if (!f) {
540    circle_finish_event(eq, lo->c);
541    lo->l = 0;
542    lo->r = hi;
543    hi->l = hi->r = 0;
544    return lo;
545    }
546
547  fringe_start_cut_x = x;
548  fringe_start_cut_y = y;
549  f = (fringe*)splay((cut)fringe_start_cut, (tree*)f);
550
551  sx = fringe_x(f, y);
552  if (x == sx) {       /* time to cheat my way out of handling degeneracies */
553    tweak_circle(lo->c);
554    circle_start_event(eq, lo->c);
555    return f;
556    }
557  else if (x < sx) {
558    circle_finish_event(eq, lo->c);
559    f->l = check_lo(eq, y, f->l, lo);   
560    fringe_intersect(eq, y, hi, f);
561    lo->l = f->l;
562    lo->r = f;
563    f->l = hi;
564    hi->l = hi->r = 0;
565    return lo;
566    }
567  else {
568    circle_finish_event(eq, lo->c);
569    fringe_intersect(eq, y, f, lo);
570    f->r = check_hi(eq, y, hi, f->r);
571    hi->r = f->r;
572    hi->l = f;
573    f->r = lo;
574    lo->l = lo->r = 0;
575    return hi;
576    }
577  }
578
579double fringe_double_cut_x;
580double fringe_double_cut_y;
581fringe *fringe_double_cut_lo;
582fringe *fringe_double_cut_hi;
583
584int fringe_double_cut(fringe *f) {
585  double x;
586  if (f == fringe_double_cut_lo || f == fringe_double_cut_hi)
587    return 0;
588  x = fringe_x(f, fringe_double_cut_y);
589  return fringe_double_cut_x == x ? 0 : fringe_double_cut_x < x ? -1 : 1;
590  }
591
592int fringe_double_splay(fringe *f, double x, double y, fringe *lo, fringe *hi) {
593  fringe_double_cut_x = x;
594  fringe_double_cut_y = y;
595  fringe_double_cut_lo = lo;
596  fringe_double_cut_hi = hi;
597  f = (fringe*)splay((cut)fringe_double_cut, (tree*)f);
598
599  if (f == lo)
600    return (f->r = (fringe*)splay_min((tree*)f->r)) == hi;
601  else if (f == hi)
602    return (f->l = (fringe*)splay_max((tree*)f->l)) == lo;
603  else
604    return 0;
605  }
606
607fringe *fringe_cross(event **eq, fringe *f, double x, double y, fringe *lo, fringe *hi) {
608  fringe *l, *r;
609  if (!fringe_double_splay(f, x, y, lo, hi))
610    return PANIC;
611  l = check_lo(eq, y, lo->l, hi);
612  r = check_hi(eq, y, lo, hi->r);
613  lo->l = hi;
614  lo->r = r;
615  hi->l = l;
616  hi->r = 0;
617  return lo;
618  }
619
620fringe *fringe_finish(event **eq, fringe *f, double x, double y, fringe *lo, fringe *hi) {
621  if (!fringe_double_splay(f, x, y, lo, hi))
622    return PANIC;
623  else if (!lo->l)
624    return hi->r;
625  else if (!hi->r)
626    return lo->l;
627  else {
628    lo->l = (fringe*)splay_max((tree*)lo->l);
629    hi->r = (fringe*)splay_min((tree*)hi->r);
630    fringe_intersect(eq, y, lo->l, hi->r);
631    lo->l->r = hi->r;
632    hi->r->l = 0;
633    return lo->l;
634    }
635  }
636
637/******** plane sweep */
638
639void sweep(int n, circle *c) {
640  int i;
641  event *eq, *e;
642  fringe *f;
643
644  RESTART:
645  #define CHECK_PANIC()                 \
646    if (f == PANIC) {                   \
647      free(e);                          \
648      event_shred(eq);                  \
649      for (i=0;i<n;i++) {               \
650        tweak_circle(c+i);              \
651        c[i].lo->ni = c[i].hi->ni = 0;  \
652        }                               \
653      goto RESTART;                     \
654      }
655
656  eq = 0;
657  for (i=0;i<n;i++)
658    circle_start_event(&eq, c+i);
659  f = 0;
660
661  while ((e = event_next(&eq))) {
662    switch (e->kind) {
663      case START:
664        f = fringe_start(&eq, f, e->x, e->y, e->lo, e->hi);
665        break;
666      case CROSS:
667        f = fringe_cross(&eq, f, e->x, e->y, e->lo, e->hi);
668        CHECK_PANIC();
669        fringe_add_intersection(e->lo, e->x, e->y);
670        fringe_add_intersection(e->hi, e->x, e->y);
671        break;
672      case FINISH:
673        f = fringe_finish(&eq, f, e->x, e->y, e->lo, e->hi);
674        CHECK_PANIC();
675        break;
676      }
677    free(e);
678    }
679  }
680
681/******** circle drawing */
682
683void adjust_circle_visibility(circle *c) {
684  int i, j, n, a;
685  int *in;
686  n = c->lo->ni + c->hi->ni;
687  in = malloc(sizeof(int) * n);
688  for (i=0;i<c->hi->ni;i++)
689    in[i] = c->hi->i[i];
690  for (i=c->lo->ni-1;i>=0;i--)
691    in[n-i-1] = c->lo->i[i] > 0 ? c->lo->i[i] : c->lo->i[i] + 2 * X_PI;
692  c->lo->ni = c->hi->ni = 0;
693
694  i = j = 0;
695  a = 0;
696  while (i < n && j < c->ni)           /* whee */
697    a = (in[i] < c->i[j] ? in[i++] : c->i[j++]) - a;
698  while (i < n)
699    a = in[i++] - a;
700  while (j < c->ni)
701    a = c->i[j++] - a;
702
703  if (a > X_PI)
704    c->visible = !c->visible;
705  free(c->i); 
706  c->ni = n;
707  c->i = in;
708  }
709
710#define ARC_BUFFER_SIZE 256
711int arc_buffer_count = 0;
712XArc arc_buffer[ARC_BUFFER_SIZE];
713
714void flush_arc_buffer(Display *dpy, Drawable w, GC gc) {
715  if (arc_buffer_count) {
716    XDrawArcs(dpy, w, gc, arc_buffer, arc_buffer_count);
717    arc_buffer_count = 0;
718    }
719  }
720
721void draw_circle(Display *dpy, Drawable w, GC gc, circle *c) {
722  int i, xi, yi, di;
723  adjust_circle_visibility(c);
724
725  xi = rint(c->x - c->r);
726  yi = rint(c->y - c->r);
727  di = c->r << 1;
728
729  #define ARC(p, a1, a2) {                                \
730    if (((p) & 1) ^ c->visible) {                         \
731      arc_buffer[arc_buffer_count].x      = xi;           \
732      arc_buffer[arc_buffer_count].y      = yi;           \
733      arc_buffer[arc_buffer_count].width  = di;           \
734      arc_buffer[arc_buffer_count].height = di;           \
735      arc_buffer[arc_buffer_count].angle1 = -(a1);        \
736      arc_buffer[arc_buffer_count].angle2 = (a1) - (a2);  \
737      arc_buffer_count++;                                 \
738      if (arc_buffer_count == ARC_BUFFER_SIZE)            \
739        flush_arc_buffer(dpy, w, gc);                     \
740      }                                                   \
741    }
742
743  if (!c->ni)
744    ARC(0, 0, 2 * X_PI)
745  else
746    ARC(0, c->i[c->ni-1], c->i[0] + 2 * X_PI)
747  for (i=1;i<c->ni;i++)
748    ARC(i, c->i[i-1], c->i[i])
749  }
750
751/******** toplevel */
752
753char *progclass = "Piecewise";
754
755char *defaults [] = {
756  ".background:         black",
757  ".foreground:         white",
758  "*delay:              5000",
759  "*speed:              15",
760  "*ncolors:            256",
761  ".colorspeed:         10",
762
763  ".count:              32",
764  ".minradius:          0.05",
765  ".maxradius:          0.2",   
766
767  "*doubleBuffer:       True",
768#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
769  "*useDBE:             True",
770#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
771  0
772  };
773
774XrmOptionDescRec options [] = {
775  { "-delay",           ".delay",       XrmoptionSepArg, 0 },
776  { "-ncolors",         ".ncolors",     XrmoptionSepArg, 0 },
777  { "-speed",           ".speed",       XrmoptionSepArg, 0 },
778  { "-colorspeed",      ".colorspeed",  XrmoptionSepArg, 0 },
779
780  { "-count",           ".count",       XrmoptionSepArg, 0 },
781  { "-minradius",       ".minradius",   XrmoptionSepArg, 0 },
782  { "-maxradius",       ".maxradius",   XrmoptionSepArg, 0 },
783
784  { "-db",              ".doubleBuffer", XrmoptionNoArg,  "True" },
785  { "-no-db",           ".doubleBuffer", XrmoptionNoArg,  "False" },
786  { 0, 0, 0, 0 }
787  };
788
789void screenhack(Display *dpy, Window window) {
790  int i;
791  Bool dbuf;
792  XColor *colors;
793  XGCValues gcv;
794  GC erase_gc, draw_gc;
795  XWindowAttributes xgwa;
796  Pixmap b = 0, ba = 0, bb = 0;    /* double-buffering pixmap */
797
798#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
799  XdbeBackBuffer backb = 0;
800#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
801
802  int count, delay, ncolors, colorspeed, color_index, flags, iterations;
803  int color_iterations;
804  circle *circles;
805
806  count = get_integer_resource("count", "Integer");
807  delay = get_integer_resource("delay", "Integer");
808  ncolors = get_integer_resource("ncolors", "Integer");
809  colorspeed = get_integer_resource("colorspeed", "Integer");
810  dbuf = get_boolean_resource("doubleBuffer", "Boolean");
811
812  color_iterations = colorspeed ? 100 / colorspeed : 100000;
813  if (!color_iterations)
814    color_iterations = 1;
815
816  XGetWindowAttributes(dpy, window, &xgwa);
817  colors = calloc(sizeof(XColor), ncolors);
818
819  if (get_boolean_resource("mono", "Boolean")) { 
820    MONO:
821      ncolors = 1;
822      colors[0].pixel = get_pixel_resource("foreground", "Foreground", dpy, xgwa.colormap);
823    }
824  else {
825    make_color_loop(dpy, xgwa.colormap, 0, 1, 1, 120, 1, 1, 240, 1, 1, colors, &ncolors, True, False);
826    if (ncolors < 2)
827      goto MONO;
828    }
829
830  if (dbuf) {
831#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
832    b = backb = xdbe_get_backbuffer(dpy, window, XdbeUndefined);
833#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
834   
835    if (!b) {
836      ba = XCreatePixmap(dpy, window, xgwa.width, xgwa.height,xgwa.depth);
837      bb = XCreatePixmap(dpy, window, xgwa.width, xgwa.height,xgwa.depth);
838      b = ba;
839      }
840    }
841  else
842    b = window;
843
844  /* erasure gc */
845  gcv.foreground = get_pixel_resource("background", "Background", dpy, xgwa.colormap);
846  erase_gc = XCreateGC (dpy, b, GCForeground, &gcv);
847
848  /* drawing gc */
849  flags = GCForeground;
850  color_index = random() % ncolors;
851  gcv.foreground = colors[color_index].pixel;
852  draw_gc = XCreateGC(dpy, b, flags, &gcv);
853
854  /* initialize circles */
855  circles = init_circles(count, xgwa.width, xgwa.height);
856 
857  iterations = 0;
858  for (;;) {
859    XFillRectangle (dpy, b, erase_gc, 0, 0, xgwa.width, xgwa.height);
860
861    sweep(count, circles);
862    for (i=0;i<count;i++) {
863      draw_circle(dpy, b, draw_gc, circles+i);
864      move_circle(circles+i, xgwa.width, xgwa.height);
865      }
866    flush_arc_buffer(dpy, b, draw_gc);
867
868    if (++iterations % color_iterations == 0) {
869      color_index = (color_index + 1) % ncolors;
870      XSetForeground(dpy, draw_gc, colors[color_index].pixel);
871      }
872
873#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
874    if (backb) {
875      XdbeSwapInfo info[1];
876      info[0].swap_window = window;
877      info[0].swap_action = XdbeUndefined;
878      XdbeSwapBuffers (dpy, info, 1);
879      }
880    else
881#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
882    if (dbuf) {
883      XCopyArea (dpy, b, window, erase_gc, 0, 0, xgwa.width, xgwa.height, 0, 0);
884      b = (b == ba ? bb : ba);
885      }
886
887    XSync(dpy, False);
888    screenhack_handle_events(dpy);
889    if (delay)
890      usleep(delay);
891    }
892  }
Note: See TracBrowser for help on using the repository browser.