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

Revision 20148, 38.0 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/* -*- Mode: C; tab-width: 4 -*-
2 * swirl --- swirly color-cycling patterns.
3 */
4#if 0
5static const char sccsid[] = "@(#)swirl.c       4.00 97/01/01 xlockmore";
6#endif
7
8/* Copyright (c) 1994 M.Dobie <mrd@ecs.soton.ac.uk>
9 *
10 * Permission to use, copy, modify, and distribute this software and its
11 * documentation for any purpose and without fee is hereby granted,
12 * provided that the above copyright notice appear in all copies and that
13 * both that copyright notice and this permission notice appear in
14 * supporting documentation.
15 *
16 * This file is provided AS IS with no warranties of any kind.  The author
17 * shall have no liability with respect to the infringement of copyrights,
18 * trade secrets or any patents by this file or any part thereof.  In no
19 * event will the author be liable for any lost revenue or profits or
20 * other special, indirect and consequential damages.
21 *
22 * 13-May-97: jwz@jwz.org: turned into a standalone program.
23 * 21-Apr-95: improved startup time for TrueColour displays
24 *            (limited to 16bpp to save memory) S.Early <sde1000@cam.ac.uk>
25 * 09-Jan-95: fixed colour maps (more colourful) and the image now spirals
26 *            outwards from the centre with a fixed number of points drawn
27 *            every iteration. Thanks to M.Dobie <mrd@ecs.soton.ac.uk>.
28 * 1994:      written.   Copyright (c) 1994 M.Dobie <mrd@ecs.soton.ac.uk>
29 *            based on original code by R.Taylor
30 */
31
32#ifdef STANDALONE
33# define PROGCLASS                                      "Swirl"
34# define HACK_INIT                                      init_swirl
35# define HACK_DRAW                                      draw_swirl
36# define swirl_opts                                     xlockmore_opts
37# define DEFAULTS       "*count:                5       \n"                     \
38                                        "*delay:                10000   \n"                     \
39                                        "*ncolors:              200     \n"                     \
40                                        "*useSHM:               True    \n"
41# define SMOOTH_COLORS
42# define WRITABLE_COLORS
43# include "xlockmore.h"                         /* from the xscreensaver distribution */
44# include <X11/Xutil.h>
45# ifdef HAVE_XSHM_EXTENSION
46#  include "xshm.h"
47# endif /* HAVE_XSHM_EXTENSION */
48#else  /* !STANDALONE */
49# include "xlock.h"                                     /* from the xlockmore distribution */
50# undef HAVE_XSHM_EXTENSION
51#endif /* !STANDALONE */
52
53ModeSpecOpt swirl_opts = {
54  0, NULL, 0, NULL, NULL };
55
56#include <time.h>
57
58/****************************************************************/
59
60#define MASS            4       /* maximum mass of a knot */
61#define MIN_RES         5       /* minimim resolution (>= MIN_RES) */
62#define MAX_RES         1       /* maximum resolution (>0) */
63#define TWO_PLANE_PCNT  30      /* probability for two plane mode (0-100) */
64#define RESTART         2500    /* number of cycles before restart */
65#define BATCH_DRAW      100     /* points to draw per iteration */
66
67/* knot types */
68typedef enum {
69        NONE = 0,
70        ORBIT = (1 << 0),
71        WHEEL = (1 << 1),
72        PICASSO = (1 << 2),
73        RAY = (1 << 3),
74        HOOK = (1 << 4),
75        ALL = (1 << 5)
76} KNOT_T;
77
78/* a knot */
79typedef struct Knot {
80        int         x, y;       /* position */
81        int         m;          /* mass */
82        KNOT_T      t;          /* type in the first (or only) plane */
83        KNOT_T      T;          /* type in second plane if there is one */
84        int         M;          /* mass in second plane if there is one */
85} KNOT     , *KNOT_P;
86
87/* a colour specification */
88typedef struct Colour {
89        unsigned short r, g, b;
90} COLOUR   , *COLOUR_P;
91
92/* drawing direction */
93typedef enum {
94        DRAW_RIGHT, DRAW_DOWN, DRAW_LEFT, DRAW_UP
95} DIR_T;
96
97/****************************************************************/
98
99/* data associated with a swirl window */
100typedef struct swirl_data {
101        /* window paramaters */
102        Window      win;        /* the window */
103        int         width, height;      /* window size */
104        int         depth;      /* depth */
105        int         rdepth;     /* real depth (for XImage) */
106        Visual     *visual;     /* visual */
107
108        /* swirl drawing parameters */
109        int         n_knots;    /* number of knots */
110        KNOT_P      knots;      /* knot details */
111        KNOT_T      knot_type;  /* general type of knots */
112        int         resolution; /* drawing resolution, 1..5 */
113        int         max_resolution;     /* maximum resolution, MAX_RES */
114        int         r;          /* pixel step */
115        Bool        two_plane;  /* two plane mode? */
116        Bool        first_plane;        /* doing first plane? */
117        int         start_again;        /* when to restart */
118
119        /* spiral drawing parameters */
120        int         x, y;       /* current point */
121        DIR_T       direction;  /* current direction */
122        int         dir_todo, dir_done;         /* how many points in current direction? */
123        int         batch_todo, batch_done;     /* how many points in this batch */
124        Bool        started, drawing;   /* are we drawing? */
125
126        /* image stuff */
127        unsigned char *image;   /* image data */
128        XImage     *ximage;
129
130        /* colours stuff */
131        int         colours;    /* how many colours possible */
132        int         dcolours;   /* how many colours for shading */
133#ifndef STANDALONE
134        Bool        fixed_colourmap;    /* fixed colourmap? */
135#endif /* !STANDALONE */
136        Bool        monochrome; /* monochrome? */
137        Colormap    cmap;       /* colour map for the window */
138        XColor     *rgb_values; /* colour definitions array */
139#ifndef STANDALONE
140        int         current_map;        /* current colour map, 0..dcolours-1 */
141        unsigned long fg, bg, white, black;     /* black and white pixel values */
142        int         shift;      /* colourmap shift */
143        int         dshift;     /* colourmap shift while drawing */
144        XColor      fgcol, bgcol;       /* foreground and background colour specs */
145#endif /* !STANDALONE */
146        Bool       off_screen;
147} SWIRL    , *SWIRL_P;
148
149#define SWIRLCOLOURS 13
150
151#ifndef STANDALONE
152/* basic colours */
153static COLOUR basic_colours[SWIRLCOLOURS];
154#endif /* !STANDALONE */
155
156/* an array of swirls for each screen */
157static SWIRL_P swirls = NULL;
158
159/*
160   random_no
161
162   Return a random integer between 0 and n inclusive
163
164   -      n is the maximum number
165
166   Returns a random integer */
167
168static int
169random_no(unsigned int n)
170{
171        return ((int) ((n + 1) * (double) LRAND() / MAXRAND));
172}
173
174/****************************************************************/
175
176/*
177   initialise_swirl
178
179   Initialise all the swirl data
180
181   -      swirl is the swirl data */
182
183static void
184initialise_swirl(ModeInfo * mi, SWIRL_P swirl)
185{
186#ifndef STANDALONE
187        Display    *display = MI_DISPLAY(mi);
188#endif /* !STANDALONE */
189
190        swirl->width = 0;       /* width and height of window */
191        swirl->height = 0;
192        swirl->depth = 1;
193        swirl->rdepth = 1;
194        swirl->visual = NULL;
195        swirl->resolution = MIN_RES + 1;        /* current resolution */
196        swirl->max_resolution = MAX_RES;        /* maximum resolution */
197        swirl->n_knots = 0;     /* number of knots */
198        swirl->knot_type = ALL; /* general type of knots */
199        swirl->two_plane = False;       /* two plane mode? */
200        swirl->first_plane = False;     /* doing first plane? */
201        swirl->start_again = -1;        /* restart counter */
202
203        /* drawing parameters */
204        swirl->x = 0;
205        swirl->y = 0;
206        swirl->started = False;
207        swirl->drawing = False;
208
209        /* image stuff */
210        swirl->image = NULL;    /* image data */
211        swirl->ximage = NULL;
212
213        /* colours stuff */
214        swirl->colours = 0;     /* how many colours possible */
215        swirl->dcolours = 0;    /* how many colours for shading */
216        swirl->cmap = (Colormap) NULL;
217        swirl->rgb_values = NULL;       /* colour definitions array */
218#ifndef STANDALONE
219        swirl->current_map = 0; /* current colour map, 0..dcolours-1 */
220
221        /* set up fg fb colour specs */
222        swirl->white = MI_WIN_WHITE_PIXEL(mi);
223        swirl->black = MI_WIN_BLACK_PIXEL(mi);
224#endif /* !STANDALONE */
225
226
227#ifndef STANDALONE
228        swirl->fg = MI_FG_COLOR(mi);
229        swirl->bg = MI_BG_COLOR(mi);
230        swirl->fgcol.pixel = swirl->fg;
231        swirl->bgcol.pixel = swirl->bg;
232        XQueryColor(display, MI_COLORMAP(mi), &(swirl->fgcol));
233        XQueryColor(display, MI_COLORMAP(mi), &(swirl->bgcol));
234#endif /* !STANDALONE */
235}
236
237/****************************************************************/
238
239/*
240 * initialise_image
241 *
242 * Initialise the image for drawing to
243 *
244 * -      swirl is the swirl data
245 */
246static void
247initialise_image(ModeInfo * mi, SWIRL_P swirl)
248{
249  Display *dpy = MI_DISPLAY(mi);
250
251  if (swirl->ximage != NULL)
252        XDestroyImage(swirl->ximage);
253
254  swirl->ximage = 0;
255#ifdef HAVE_XSHM_EXTENSION
256  if (mi->use_shm)
257        {
258          swirl->ximage = create_xshm_image(dpy, swirl->visual, swirl->rdepth,
259                                                                                ZPixmap, 0, &mi->shm_info,
260                                                                                swirl->width, swirl->height);
261          if (!swirl->ximage)
262                mi->use_shm = False;
263        }
264#endif /* HAVE_XSHM_EXTENSION */
265
266  if (!swirl->ximage)
267        {
268          swirl->ximage = XCreateImage(dpy, swirl->visual, swirl->rdepth, ZPixmap,
269                                                                   0, 0, swirl->width, swirl->height,
270                                                                   8, 0);
271          swirl->image = (unsigned char *)
272        calloc(swirl->height, swirl->ximage->bytes_per_line);
273      swirl->ximage->data = (char *) swirl->image;
274        }
275}
276
277/****************************************************************/
278
279#ifndef STANDALONE
280/*
281 * initialise_colours
282 *
283 * Initialise the list of colours from which the colourmaps are derived
284 *
285 * -      colours is the array to initialise
286 * -      saturation is the saturation value to use 0->grey,
287 *            1.0->full saturation
288 */
289static void
290initialise_colours(COLOUR * colours, float saturate)
291{
292        int         i;
293
294        /* start off fully saturated, medium and bright colours */
295        colours[0].r = 0xA000;
296        colours[0].g = 0x0000;
297        colours[0].b = 0x0000;
298        colours[1].r = 0xD000;
299        colours[1].g = 0x0000;
300        colours[1].b = 0x0000;
301        colours[2].r = 0x0000;
302        colours[2].g = 0x6000;
303        colours[2].b = 0x0000;
304        colours[3].r = 0x0000;
305        colours[3].g = 0x9000;
306        colours[3].b = 0x0000;
307        colours[4].r = 0x0000;
308        colours[4].g = 0x0000;
309        colours[4].b = 0xC000;
310        colours[5].r = 0x0000;
311        colours[5].g = 0x0000;
312        colours[5].b = 0xF000;
313        colours[6].r = 0xA000;
314        colours[6].g = 0x6000;
315        colours[6].b = 0x0000;
316        colours[7].r = 0xD000;
317        colours[7].g = 0x9000;
318        colours[7].b = 0x0000;
319        colours[8].r = 0xA000;
320        colours[8].g = 0x0000;
321        colours[8].b = 0xC000;
322        colours[9].r = 0xD000;
323        colours[9].g = 0x0000;
324        colours[9].b = 0xF000;
325        colours[10].r = 0x0000;
326        colours[10].g = 0x6000;
327        colours[10].b = 0xC000;
328        colours[11].r = 0x0000;
329        colours[11].g = 0x9000;
330        colours[11].b = 0xF000;
331        colours[12].r = 0xA000;
332        colours[12].g = 0xA000;
333        colours[12].b = 0xA000;
334
335        /* add white for low saturation */
336        for (i = 0; i < SWIRLCOLOURS - 1; i++) {
337                unsigned short max_rg, max;
338
339                /* what is the max intensity for this colour? */
340                max_rg = (colours[i].r > colours[i].g) ? colours[i].r : colours[i].g;
341                max = (max_rg > colours[i].b) ? max_rg : colours[i].b;
342
343                /* bring elements up to max as saturation approaches 0.0 */
344                colours[i].r += (unsigned short) ((float) (1.0 - saturate) *
345                                               ((float) max - colours[i].r));
346                colours[i].g += (unsigned short) ((float) (1.0 - saturate) *
347                                               ((float) max - colours[i].g));
348                colours[i].b += (unsigned short) ((float) (1.0 - saturate) *
349                                               ((float) max - colours[i].b));
350        }
351}
352#endif /* !STANDALONE */
353
354/****************************************************************/
355
356#ifndef STANDALONE
357/*
358 * set_black_and_white
359 *
360 * Set the entries for foreground & background pixels and
361 * WhitePixel & BlackPixel in an array of colour specifications.
362 *
363 * -      swirl is the swirl data
364 * -      values is the array of specifications
365 */
366static void
367set_black_and_white(SWIRL_P swirl, XColor * values)
368{
369        unsigned long white, black;
370
371        /* where is black and white? */
372        white = swirl->white;
373        black = swirl->black;
374
375        /* set black and white up */
376        values[white].flags = DoRed | DoGreen | DoBlue;
377        values[white].pixel = white;
378        values[white].red = 0xFFFF;
379        values[white].green = 0xFFFF;
380        values[white].blue = 0xFFFF;
381        values[black].flags = DoRed | DoGreen | DoBlue;
382        values[black].pixel = black;
383        values[black].red = 0;
384        values[black].green = 0;
385        values[black].blue = 0;
386
387        /* copy the colour specs from the original entries */
388        values[swirl->fg] = swirl->fgcol;
389        values[swirl->bg] = swirl->bgcol;
390}
391
392/****************************************************************/
393
394/*
395 * set_colour
396 *
397 * Set an entry in an array of XColor specifications. The given entry will be
398 * set to the given colour. If the entry corresponds to the foreground,
399 * background, WhitePixel, or BlackPixel it is ignored and the given colour
400 * is is put in the next entry.
401 *
402 * Therefore, the given colour may be placed up to four places after the
403 * specified entry in the array, if foreground, background, white, or black
404 * intervene.
405 *
406 * -      swirl is the swirl data
407 * -      value points to a pointer to the array entry. It gets updated to
408 *            point to the next free entry.
409 * -      pixel points to the current pixel number. It gets updated.
410 * -      c points to the colour to add
411 */
412static void
413set_colour(SWIRL_P swirl, XColor ** value, unsigned long *pixel, COLOUR_P c)
414{
415        Bool        done;
416        unsigned long fg, bg, white, black;
417
418        /* where are foreground, background, white, and black? */
419        fg = swirl->fg;
420        bg = swirl->bg;
421        white = swirl->white;
422        black = swirl->black;
423
424        /* haven't set it yet */
425        done = False;
426
427        /* try and set the colour */
428        while (!done) {
429                (**value).flags = DoRed | DoGreen | DoBlue;
430                (**value).pixel = *pixel;
431
432                /* white, black, fg, bg, or a colour? */
433                if ((*pixel != fg) && (*pixel != bg) &&
434                    (*pixel != white) && (*pixel != black)) {
435                        (**value).red = c->r;
436                        (**value).green = c->g;
437                        (**value).blue = c->b;
438
439                        /* now we've done it */
440                        done = True;
441                }
442                /* next pixel */
443                (*value)++;
444                (*pixel)++;
445        }
446}
447
448/****************************************************************/
449
450/*
451 * get_colour
452 *
453 * Get an entry from an array of XColor specifications. The next colour from
454 * the array will be returned. Foreground, background, WhitePixel, or
455 * BlackPixel will be ignored.
456 *
457 * -      swirl is the swirl data
458 * -      value points the array entry. It is updated to point to the entry
459 *            following the one returned.
460 * -      c is set to the colour found
461 */
462static void
463get_colour(SWIRL_P swirl, XColor ** value, COLOUR_P c)
464{
465        Bool        done;
466        unsigned long fg, bg, white, black;
467
468        /* where is white and black? */
469        fg = swirl->fg;
470        bg = swirl->bg;
471        white = swirl->white;
472        black = swirl->black;
473
474        /* haven't set it yet */
475        done = False;
476
477        /* try and set the colour */
478        while (!done) {
479                /* black, white or a colour? */
480                if (((*value)->pixel != fg) && ((*value)->pixel != bg) &&
481                  ((*value)->pixel != white) && ((*value)->pixel != black)) {
482                        c->r = (*value)->red;
483                        c->g = (*value)->green;
484                        c->b = (*value)->blue;
485
486                        /* now we've done it */
487                        done = True;
488                }
489                /* next value */
490                (*value)++;
491        }
492}
493#endif /* !STANDALONE */
494
495/****************************************************************/
496
497#ifndef STANDALONE
498/*
499 *  interpolate
500 *
501 * Generate n colours between c1 and c2.  n XColors at *value are set up with
502 * ascending pixel values.
503 *
504 * If the pixel range includes BlackPixel or WhitePixel they are set to black
505 * and white respectively but otherwise ignored. Therefore, up to n+2 colours
506 * may actually be set by this function.
507 *
508 * -      swirl is the swirl data
509 * -      values points a pointer to an array of XColors to update
510 * -      pixel points to the pixel number to start at
511 * -      k n is the number of colours to generate
512 * -      c1, c2 are the colours to interpolate between
513 */
514static void
515interpolate(SWIRL_P swirl, XColor ** values, unsigned long *pixel, int n, COLOUR_P c1, COLOUR_P c2)
516{
517        int         i, r, g, b;
518        COLOUR      c;
519        unsigned short maxv;
520
521        /* maximum value */
522        maxv = (255 << 8);
523
524        for (i = 0; i < n / 2 && (int) *pixel < swirl->colours; i++) {
525                /* work out the colour */
526                r = c1->r + 2 * i * ((int) c2->r) / n;
527                c.r = (r > (int) maxv) ? maxv : r;
528                g = c1->g + 2 * i * ((int) c2->g) / n;
529                c.g = (g > (int) maxv) ? maxv : g;
530                b = c1->b + 2 * i * ((int) c2->b) / n;
531                c.b = (b > (int) maxv) ? maxv : b;
532
533                /* set it up */
534                set_colour(swirl, values, pixel, &c);
535        }
536        for (i = n / 2; i >= 0 && (int) *pixel < swirl->colours; i--) {
537                r = c2->r + 2 * i * ((int) c1->r) / n;
538                c.r = (r > (int) maxv) ? maxv : r;
539                g = c2->g + 2 * i * ((int) c1->g) / n;
540                c.g = (g > (int) maxv) ? maxv : g;
541                b = c2->b + 2 * i * ((int) c1->b) / n;
542                c.b = (b > (int) maxv) ? maxv : b;
543
544                /* set it up */
545                set_colour(swirl, values, pixel, &c);
546        }
547}
548
549/****************************************************************/
550
551/*
552 * basic_map
553 *
554 * Generate a `random' closed loop colourmap that occupies the whole colour
555 * map.
556 *
557 * -      swirl is the swirl data
558 * -      values is the array of colour definitions to set up
559 */
560static void
561basic_map(SWIRL_P swirl, XColor * values)
562{
563        COLOUR      c[3];
564        int         i;
565        unsigned short r1, g1, b1, r2, g2, b2, r3, g3, b3;
566        int         L1, L2, L3, L;
567        unsigned long pixel;
568        XColor     *value;
569
570        /* start at the beginning of the colour map */
571        pixel = 0;
572        value = values;
573
574        /* choose 3 different basic colours at random */
575        for (i = 0; i < 3;) {
576                int         j;
577                Bool        same;
578
579                /* choose colour i */
580                c[i] = basic_colours[random_no(SWIRLCOLOURS - 1)];
581
582                /* assume different */
583                same = False;
584
585                /* different from the rest? */
586                for (j = 0; j < i; j++)
587                        if ((c[i].r == c[j].r) &&
588                            (c[i].g == c[j].g) &&
589                            (c[i].b == c[j].b))
590                                same = True;
591
592                /* ready for the next colour? */
593                if (!same)
594                        i++;
595        }
596
597        /* extract components into variables */
598        r1 = c[0].r;
599        g1 = c[0].g;
600        b1 = c[0].b;
601        r2 = c[1].r;
602        g2 = c[1].g;
603        b2 = c[1].b;
604        r3 = c[2].r;
605        g3 = c[2].g;
606        b3 = c[2].b;
607
608        /* work out the lengths of each side of the triangle */
609        L1 = (int) sqrt((((double) r1 - r2) * ((double) r1 - r2) +
610                         ((double) g1 - g2) * ((double) g1 - g2) +
611                         ((double) b1 - b2) * ((double) b1 - b2)));
612
613        L2 = (int) sqrt((((double) r3 - r2) * ((double) r3 - r2) +
614                         ((double) g3 - g2) * ((double) g3 - g2) +
615                         ((double) b3 - b2) * ((double) b3 - b2)));
616
617        L3 = (int) sqrt((((double) r1 - r3) * ((double) r1 - r3) +
618                         ((double) g1 - g3) * ((double) g1 - g3) +
619                         ((double) b1 - b3) * ((double) b1 - b3)));
620
621        L = L1 + L2 + L3;
622
623        /* allocate colours in proportion to the lengths of the sides */
624        interpolate(swirl, &value, &pixel,
625                    (int) ((double) swirl->dcolours * ((double) L1 / (double) L)) + 1, c, c + 1);
626        interpolate(swirl, &value, &pixel,
627                    (int) ((double) swirl->dcolours * ((double) L2 / (double) L)) + 1, c + 1, c + 2);
628        interpolate(swirl, &value, &pixel,
629                    (int) ((double) swirl->dcolours * ((double) L3 / (double) L)) + 1, c + 2, c);
630
631        /* fill up any remaining slots (due to rounding) */
632        while ((int) pixel < swirl->colours) {
633                /* repeat the last colour */
634                set_colour(swirl, &value, &pixel, c);
635        }
636
637        /* ensure black and white are correct */
638        if (!swirl->fixed_colourmap)
639                set_black_and_white(swirl, values);
640}
641
642/****************************************************************/
643
644/*
645 * pre_rotate
646 *
647 * Generate pre-rotated versions of the colour specifications
648 *
649 * -      swirl is the swirl data
650 * -      values is an array of colour specifications
651 */
652static void
653pre_rotate(SWIRL_P swirl, XColor * values)
654{
655        int         i, j;
656        XColor     *src, *dest;
657        int         dcolours;
658        unsigned long pixel;
659
660        /* how many colours to display? */
661        dcolours = swirl->dcolours;
662
663        /* start at the first map */
664        src = values;
665        dest = values + swirl->colours;
666
667        /* generate dcolours-1 rotated maps */
668        for (i = 0; i < dcolours - 1; i++) {
669                COLOUR      first;
670
671                /* start at the first pixel */
672                pixel = 0;
673
674                /* remember the first one and skip it */
675                get_colour(swirl, &src, &first);
676
677                /* put a rotated version of src at dest */
678                for (j = 0; j < dcolours - 1; j++) {
679                        COLOUR      c;
680
681                        /* get the source colour */
682                        get_colour(swirl, &src, &c);
683
684                        /* set the colour */
685                        set_colour(swirl, &dest, &pixel, &c);
686                }
687
688                /* put the first one at the end */
689                set_colour(swirl, &dest, &pixel, &first);
690
691                /* NB: src and dest should now be ready for the next table */
692
693                /* ensure black and white are properly set */
694                set_black_and_white(swirl, src);
695        }
696}
697
698/****************************************************************/
699
700/*
701 * create_colourmap
702 *
703 * Create a read/write colourmap to use
704 *
705 * -      swirl is the swirl data
706 */
707
708static void
709create_colourmap(ModeInfo * mi, SWIRL_P swirl)
710{
711        Display    *display = MI_DISPLAY(mi);
712        int         preserve;
713        int         n_rotations;
714        int         i;
715        Bool        truecolor;
716  unsigned long redmask, greenmask, bluemask;
717
718        swirl->fixed_colourmap = !setupColormap(mi, &(swirl->colours),
719    &truecolor, &redmask, &greenmask, &bluemask);
720        preserve = preserveColors(swirl->fg, swirl->bg, swirl->white, swirl->black);
721
722        /* how many colours should we animate? */
723        swirl->dcolours = (swirl->colours > preserve + 1) ?
724                swirl->colours - preserve : swirl->colours;
725
726        if (MI_NPIXELS(mi) < 2)
727                return;
728
729        /* how fast to shift the colourmap? */
730        swirl->shift = (swirl->colours > 64) ? swirl->colours / 64 : 1;
731        swirl->dshift = (swirl->shift > 1) ? swirl->shift * 2 : 1;
732
733        /* how may colour map rotations are there? */
734        n_rotations = (swirl->fixed_colourmap) ? 1 : swirl->dcolours;
735
736        /* allocate space for colour definitions (if not already there) */
737        if (swirl->rgb_values == NULL) {
738                swirl->rgb_values = (XColor *) calloc((swirl->colours + 3) * n_rotations,
739                                                      sizeof (XColor));
740
741                /* create a colour map */
742                if (!swirl->fixed_colourmap)
743                        swirl->cmap =
744                                XCreateColormap(display, swirl->win, swirl->visual, AllocAll);
745        }
746        /* select a set of colours for the colour map */
747        basic_map(swirl, swirl->rgb_values);
748
749        /* are we rotating them? */
750        if (!swirl->fixed_colourmap) {
751                /* generate rotations of the colour maps */
752                pre_rotate(swirl, swirl->rgb_values);
753
754                /* store the colours in the colour map */
755                XStoreColors(display, swirl->cmap, swirl->rgb_values, swirl->colours);
756        } else {
757                if (truecolor) {
758                        int         rsh, gsh, bsh;
759                        unsigned long int t;
760
761                        t = redmask;
762                        for (i = 0; (int) t > 0; i++, t >>= 1);
763                        rsh = 16 - i;
764                        t = greenmask;
765                        for (i = 0; (int) t > 0; i++, t >>= 1);
766                        gsh = 16 - i;
767                        t = bluemask;
768                        for (i = 0; (int) t > 0; i++, t >>= 1);
769                        bsh = 16 - i;
770                        for (i = 0; i < swirl->colours; i++)
771                                swirl->rgb_values[i].pixel =
772                                        ((rsh > 0 ? (swirl->rgb_values[i].red) >> rsh :
773                                          (swirl->rgb_values[i].red) << (-rsh)) & redmask) |
774                                        ((gsh > 0 ? (swirl->rgb_values[i].green) >> gsh :
775                                          (swirl->rgb_values[i].green) << (-gsh)) & greenmask) |
776                                        ((bsh > 0 ? (swirl->rgb_values[i].blue) >> bsh :
777                                          (swirl->rgb_values[i].blue) << (-bsh)) & bluemask);
778                } else {
779                        /* lookup the colours in the fixed colour map */
780                        for (i = 0; i < swirl->colours; i++)
781                                (void) XAllocColor(display, MI_COLORMAP(mi),
782                                                   &(swirl->rgb_values[i]));
783                }
784        }
785}
786
787/****************************************************************/
788
789/*
790 * install_map
791 *
792 * Install a new set of colours into the colour map
793 *
794 * -      dpy is the display
795 * -      swirl is the swirl data
796 * -      shift is the amount to rotate the colour map by
797 */
798static void
799install_map(Display * dpy, SWIRL_P swirl, int shift)
800{
801        if (!swirl->fixed_colourmap) {
802                /* shift the colour map */
803                swirl->current_map = (swirl->current_map + shift) %
804                        swirl->dcolours;
805
806                /* store it */
807                XStoreColors(dpy, swirl->cmap,
808                             swirl->rgb_values +
809                             swirl->current_map * swirl->colours,
810                             swirl->colours);
811        }
812}
813#endif /* !STANDALONE */
814
815/****************************************************************/
816
817/*
818 * create_knots
819 *
820 * Initialise the array of knot
821 *
822 * swirl is the swirl data
823 */
824static void
825create_knots(SWIRL_P swirl)
826{
827        int         k;
828        Bool        orbit, wheel, picasso, ray, hook;
829        KNOT_P      knot;
830
831        /* create array for knots */
832        if (swirl->knots)
833                (void) free((void *) swirl->knots);
834        swirl->knots = (KNOT_P) calloc(swirl->n_knots, sizeof (KNOT));
835
836        /* no knots yet */
837        orbit = wheel = picasso = ray = hook = False;
838
839        /* what types do we have? */
840        if ((int) swirl->knot_type & (int) ALL) {
841                orbit = wheel = ray = hook = True;
842        } else {
843                if ((int) swirl->knot_type & (int) ORBIT)
844                        orbit = True;
845                if ((int) swirl->knot_type & (int) WHEEL)
846                        wheel = True;
847                if ((int) swirl->knot_type & (int) PICASSO)
848                        picasso = True;
849                if ((int) swirl->knot_type & (int) RAY)
850                        ray = True;
851                if ((int) swirl->knot_type & (int) HOOK)
852                        hook = True;
853        }
854
855        /* initialise each knot */
856        knot = swirl->knots;
857        for (k = 0; k < swirl->n_knots; k++) {
858                /* position */
859                knot->x = random_no((unsigned int) swirl->width);
860                knot->y = random_no((unsigned int) swirl->height);
861
862                /* mass */
863                knot->m = random_no(MASS) + 1;
864
865                /* can be negative */
866                if (random_no(100) > 50)
867                        knot->m *= -1;
868
869                /* type */
870                knot->t = NONE;
871                while (knot->t == NONE) {
872                        /* choose a random one from the types available */
873                        switch (random_no(4)) {
874                                case 0:
875                                        if (orbit)
876                                                knot->t = ORBIT;
877                                        break;
878                                case 1:
879                                        if (wheel)
880                                                knot->t = WHEEL;
881                                        break;
882                                case 2:
883                                        if (picasso)
884                                                knot->t = PICASSO;
885                                        break;
886                                case 3:
887                                        if (ray)
888                                                knot->t = RAY;
889                                        break;
890                                case 4:
891                                        if (hook)
892                                                knot->t = HOOK;
893                                        break;
894                        }
895                }
896
897                /* if two planes, do same for second plane */
898                if (swirl->two_plane) {
899                        knot->T = NONE;
900                        while (knot->T == NONE || knot->T == knot->t) {
901                                /* choose a different type */
902                                switch (random_no(4)) {
903                                        case 0:
904                                                if (orbit)
905                                                        knot->T = ORBIT;
906                                                break;
907                                        case 1:
908                                                if (wheel)
909                                                        knot->T = WHEEL;
910                                                break;
911                                        case 2:
912                                                if (picasso)
913                                                        knot->T = PICASSO;
914                                                break;
915                                        case 3:
916                                                if (ray)
917                                                        knot->T = RAY;
918                                                break;
919                                        case 4:
920                                                if (hook)
921                                                        knot->T = HOOK;
922                                                break;
923                                }
924                        }
925                }
926                /* next knot */
927                knot++;
928        }
929}
930
931/****************************************************************/
932
933/*
934 * do_point
935 *
936 * Work out the pixel value at i, j. Ensure it does not clash with BlackPixel
937 * or WhitePixel.
938 *
939 * -      swirl is the swirl data
940 * -      i, j is the point to calculate
941 *
942 * Returns the value of the point
943 */
944static unsigned long
945do_point(SWIRL_P swirl, int i, int j)
946{
947        int         tT, k, value, add;
948        double      dx, dy, theta, dist;
949        int         dcolours, qcolours;
950        double      rads;
951        KNOT_P      knot;
952
953        /* how many colours? */
954        dcolours = swirl->dcolours;
955        qcolours = dcolours / 4;
956
957        /* colour step round a circle */
958        rads = (double) dcolours / (2.0 * M_PI);
959
960        /* start at zero */
961        value = 0;
962
963        /* go through all the knots */
964        knot = swirl->knots;
965        for (k = 0; k < swirl->n_knots; k++) {
966                dx = i - knot->x;
967                dy = j - knot->y;
968
969                /* in two_plane mode get the appropriate knot type */
970                if (swirl->two_plane)
971                        tT = (int) ((swirl->first_plane) ? knot->t : knot->T);
972                else
973                        tT = (int) knot->t;
974
975                /* distance from knot */
976                dist = sqrt(dx * dx + dy * dy);
977
978                /* nothing to add at first */
979                add = 0;
980
981                /* work out the contribution (if close enough) */
982                if (dist > 0.1)
983                        switch (tT) {
984                                case ORBIT:
985                                        add = (int) (dcolours / (1.0 + 0.01 * abs(knot->m) * dist));
986                                        break;
987                                case WHEEL:
988                                        /* Avoid atan2: DOMAIN error message */
989                                        if (dy == 0.0 && dx == 0.0)
990                                                theta = 1.0;
991                                        else
992                                                theta = (atan2(dy, dx) + M_PI) / M_PI;
993                                        if (theta < 1.0)
994                                                add = (int) (dcolours * theta +
995                                                  sin(0.1 * knot->m * dist) *
996                                                qcolours * exp(-0.01 * dist));
997                                        else
998                                                add = (int) (dcolours * (theta - 1.0) +
999                                                  sin(0.1 * knot->m * dist) *
1000                                                qcolours * exp(-0.01 * dist));
1001                                        break;
1002                                case PICASSO:
1003                                        add = (int) (dcolours *
1004                                          fabs(cos(0.002 * knot->m * dist)));
1005                                        break;
1006                                case RAY:
1007                                        /* Avoid atan2: DOMAIN error message */
1008                                        if (dy == 0.0 && dx == 0.0)
1009                                                add = 0;
1010                                        else
1011                                                add = (int) (dcolours * fabs(sin(2.0 * atan2(dy, dx))));
1012
1013                                        break;
1014                                case HOOK:
1015                                        /* Avoid atan2: DOMAIN error message */
1016                                        if (dy == 0.0 && dx == 0.0)
1017                                                add = (int) (0.05 * (abs(knot->m) - 1) * dist);
1018                                        else
1019                                                add = (int) (rads * atan2(dy, dx) +
1020                                                             0.05 * (abs(knot->m) - 1) * dist);
1021                                        break;
1022                        }
1023                /* for a +ve mass add on the contribution else take it off */
1024                if (knot->m > 0)
1025                        value += add;
1026                else
1027                        value -= add;
1028
1029                /* next knot */
1030                knot++;
1031        }
1032
1033        /* toggle plane */
1034        swirl->first_plane = (!swirl->first_plane);
1035
1036        /* make sure we handle -ve values properly */
1037        if (value >= 0)
1038                value = (value % dcolours) + 2;
1039        else
1040                value = dcolours - (abs(value) % (dcolours - 1));
1041
1042#ifndef STANDALONE
1043        /* if fg and bg are 1 and 0 we should be OK, but just in case */
1044        while ((dcolours > 2) &&
1045               (((value % swirl->colours) == (int) swirl->fg) ||
1046                ((value % swirl->colours) == (int) swirl->bg) ||
1047                ((value % swirl->colours) == (int) swirl->white) ||
1048                ((value % swirl->colours) == (int) swirl->black))) {
1049                value++;
1050        }
1051#endif /* !STANDALONE */
1052
1053        /* definitely make sure it is in range */
1054        value = value % swirl->colours;
1055
1056        /* lookup the pixel value if necessary */
1057#ifndef STANDALONE
1058        if (swirl->fixed_colourmap && swirl->dcolours > 2)
1059#endif
1060                value = swirl->rgb_values[value].pixel;
1061
1062        /* return it */
1063        return ((unsigned long) value);
1064}
1065
1066/****************************************************************/
1067
1068/*
1069 * draw_block
1070 *
1071 * Draw a square block of points with the same value.
1072 *
1073 * -      ximage is the XImage to draw on.
1074 * -      x, y is the top left corner
1075 * -      s is the length of each side
1076 * -      v is the value
1077 */
1078static void
1079draw_block(XImage * ximage, int x, int y, int s, unsigned long v)
1080{
1081        int         a, b;
1082
1083        for (a = 0; a < s; a++)
1084                for (b = 0; b < s; b++) {
1085                        XPutPixel(ximage, x + b, y + a, v);
1086                }
1087}
1088
1089/****************************************************************/
1090
1091/*
1092 * draw_point  Draw the current point in a swirl pattern onto the XImage
1093 *
1094 * -    swirl is the swirl
1095 * -    win is the window to update
1096 */
1097static void
1098draw_point(ModeInfo * mi, SWIRL_P swirl)
1099{
1100        int         r;
1101        int         x, y;
1102
1103        /* get current point coordinates and resolution */
1104        x = swirl->x;
1105        y = swirl->y;
1106        r = swirl->r;
1107
1108        /* check we are within the window */
1109        if ((x < 0) || (x > swirl->width - r) || (y < 0) || (y > swirl->height - r))
1110                return;
1111
1112        /* what style are we drawing? */
1113        if (swirl->two_plane) {
1114                int         r2;
1115
1116                /* halve the block size */
1117                r2 = r / 2;
1118
1119                /* interleave blocks at half r */
1120                draw_block(swirl->ximage, x, y, r2, do_point(swirl, x, y));
1121                draw_block(swirl->ximage, x + r2, y, r2, do_point(swirl, x + r2, y));
1122                draw_block(swirl->ximage, x + r2, y + r2, r2, do_point(swirl,
1123                        x + r2, y + r2));
1124                draw_block(swirl->ximage, x, y + r2, r2, do_point(swirl, x, y + r2));
1125        } else
1126                draw_block(swirl->ximage, x, y, r, do_point(swirl, x, y));
1127
1128        /* update the screen */
1129
1130#ifdef HAVE_XSHM_EXTENSION
1131        if (mi->use_shm)
1132          XShmPutImage(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), swirl->ximage,
1133                                   x, y, x, y, r, r, False);
1134        else
1135#endif /* !HAVE_XSHM_EXTENSION */
1136          /* PURIFY 4.0.1 on SunOS4 and on Solaris 2 reports a 256 byte memory
1137                 leak on the next line. */
1138          XPutImage(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), swirl->ximage,
1139                                x, y, x, y, r, r);
1140}
1141
1142/****************************************************************/
1143
1144/*
1145 * next_point  Move to the next point in the spiral pattern
1146 *  -    swirl is the swirl
1147 *  -    win is the window to update
1148 */
1149static void
1150next_point(SWIRL_P swirl)
1151{
1152        /* more to do in this direction? */
1153        if (swirl->dir_done < swirl->dir_todo) {
1154                /* move in the current direction */
1155                switch (swirl->direction) {
1156                        case DRAW_RIGHT:
1157                                swirl->x += swirl->r;
1158                                break;
1159                        case DRAW_DOWN:
1160                                swirl->y += swirl->r;
1161                                break;
1162                        case DRAW_LEFT:
1163                                swirl->x -= swirl->r;
1164                                break;
1165                        case DRAW_UP:
1166                                swirl->y -= swirl->r;
1167                                break;
1168                }
1169
1170                /* done another point */
1171                swirl->dir_done++;
1172        } else {
1173                /* none drawn yet */
1174                swirl->dir_done = 0;
1175
1176                /* change direction - check and record if off screen */
1177                switch (swirl->direction) {
1178                        case DRAW_RIGHT:
1179                                swirl->direction = DRAW_DOWN;
1180                                if (swirl->x > swirl->width - swirl->r) {
1181                                        /* skip these points */
1182                                        swirl->dir_done = swirl->dir_todo;
1183                                        swirl->y += (swirl->dir_todo * swirl->r);
1184
1185                                        /* check for finish */
1186                                        if (swirl->off_screen)
1187                                                swirl->drawing = False;
1188                                        swirl->off_screen = True;
1189                                } else
1190                                        swirl->off_screen = False;
1191                                break;
1192                        case DRAW_DOWN:
1193                                swirl->direction = DRAW_LEFT;
1194                                swirl->dir_todo++;
1195                                if (swirl->y > swirl->height - swirl->r) {
1196                                        /* skip these points */
1197                                        swirl->dir_done = swirl->dir_todo;
1198                                        swirl->x -= (swirl->dir_todo * swirl->r);
1199
1200                                        /* check for finish */
1201                                        if (swirl->off_screen)
1202                                                swirl->drawing = False;
1203                                        swirl->off_screen = True;
1204                                } else
1205                                        swirl->off_screen = False;
1206                                break;
1207                        case DRAW_LEFT:
1208                                swirl->direction = DRAW_UP;
1209                                if (swirl->x < 0) {
1210                                        /* skip these points */
1211                                        swirl->dir_done = swirl->dir_todo;
1212                                        swirl->y -= (swirl->dir_todo * swirl->r);
1213
1214                                        /* check for finish */
1215                                        if (swirl->off_screen)
1216                                                swirl->drawing = False;
1217                                        swirl->off_screen = True;
1218                                } else
1219                                        swirl->off_screen = False;
1220                                break;
1221                        case DRAW_UP:
1222                                swirl->direction = DRAW_RIGHT;
1223                                swirl->dir_todo++;
1224                                if (swirl->y < 0) {
1225                                        /* skip these points */
1226                                        swirl->dir_done = swirl->dir_todo;
1227                                        swirl->x += (swirl->dir_todo * swirl->r);
1228
1229                                        /* check for finish */
1230                                        if (swirl->off_screen)
1231                                                swirl->drawing = False;
1232                                        swirl->off_screen = True;
1233                                } else
1234                                        swirl->off_screen = False;
1235                                break;
1236                }
1237        }
1238}
1239
1240/****************************************************************/
1241
1242/*
1243 * init_swirl
1244 *
1245 * Initialise things for swirling
1246 *
1247 * -      win is the window to draw in
1248 */
1249void
1250init_swirl(ModeInfo * mi)
1251{
1252        Display    *display = MI_DISPLAY(mi);
1253        Window      window = MI_WINDOW(mi);
1254        SWIRL_P     swirl;
1255
1256        /* does the swirls array exist? */
1257        if (swirls == NULL) {
1258                int         i;
1259
1260                /* allocate an array, one entry for each screen */
1261                swirls = (SWIRL_P) calloc(ScreenCount(display), sizeof (SWIRL));
1262
1263                /* initialise them all */
1264                for (i = 0; i < ScreenCount(display); i++)
1265                        initialise_swirl(mi, &swirls[i]);
1266        }
1267        /* get a pointer to this swirl */
1268        swirl = &(swirls[MI_SCREEN(mi)]);
1269
1270        /* get window parameters */
1271        swirl->win = window;
1272        swirl->width = MI_WIN_WIDTH(mi);
1273        swirl->height = MI_WIN_HEIGHT(mi);
1274        swirl->depth = MI_WIN_DEPTH(mi);
1275        swirl->rdepth = swirl->depth;
1276        swirl->visual = MI_VISUAL(mi);
1277
1278        if (swirl->depth > 16)
1279                swirl->depth = 16;
1280
1281        /* initialise image for speeding up drawing */
1282        initialise_image(mi, swirl);
1283
1284        /* clear the window (before setting the colourmap) */
1285        XClearWindow(display, MI_WINDOW(mi));
1286
1287#ifdef STANDALONE
1288
1289        swirl->rgb_values = mi->colors;
1290        swirl->colours = mi->npixels;
1291        swirl->dcolours = swirl->colours;
1292/*      swirl->fixed_colourmap = !mi->writable_p;*/
1293
1294#else /* !STANDALONE */
1295
1296        /* initialise the colours from which the colourmap is derived */
1297        initialise_colours(basic_colours, MI_SATURATION(mi));
1298
1299        /* set up the colour map */
1300        create_colourmap(mi, swirl);
1301
1302        /* attach the colour map to the window (if we have one) */
1303        if (!swirl->fixed_colourmap) {
1304#if 1
1305                setColormap(display, window, swirl->cmap, MI_WIN_IS_INWINDOW(mi));
1306#else
1307                XSetWindowColormap(display, window, swirl->cmap);
1308                (void) XSetWMColormapWindows(display, window, &window, 1);
1309                XInstallColormap(display, swirl->cmap);
1310#endif
1311        }
1312#endif /* STANDALONE */
1313
1314        /* resolution starts off chunky */
1315        swirl->resolution = MIN_RES + 1;
1316
1317        /* calculate the pixel step for this resulution */
1318        swirl->r = (1 << (swirl->resolution - 1));
1319
1320        /* how many knots? */
1321        swirl->n_knots = random_no((unsigned int) MI_BATCHCOUNT(mi) / 2) +
1322                MI_BATCHCOUNT(mi) + 1;
1323
1324        /* what type of knots? */
1325        swirl->knot_type = ALL; /* for now */
1326
1327        /* use two_plane mode occaisionally */
1328        if (random_no(100) <= TWO_PLANE_PCNT) {
1329                swirl->two_plane = swirl->first_plane = True;
1330                swirl->max_resolution = 2;
1331        } else
1332                swirl->two_plane = False;
1333
1334        /* fix the knot values */
1335        create_knots(swirl);
1336
1337        /* we are off */
1338        swirl->started = True;
1339        swirl->drawing = False;
1340}
1341
1342/****************************************************************/
1343
1344/*
1345 * draw_swirl
1346 *
1347 * Draw one iteration of swirling
1348 *
1349 * -      win is the window to draw in
1350 */
1351void
1352draw_swirl(ModeInfo * mi)
1353{
1354        SWIRL_P     swirl = &(swirls[MI_SCREEN(mi)]);
1355
1356        /* are we going? */
1357        if (swirl->started) {
1358                /* in the middle of drawing? */
1359                if (swirl->drawing) {
1360#ifdef STANDALONE
1361                  if (mi->writable_p)
1362                        rotate_colors(MI_DISPLAY(mi), MI_COLORMAP(mi),
1363                                                  swirl->rgb_values, swirl->colours, 1);
1364#else  /* !STANDALONE */
1365                        /* rotate the colours */
1366                        install_map(MI_DISPLAY(mi), swirl, swirl->dshift);
1367#endif /* !STANDALONE */
1368
1369                        /* draw a batch of points */
1370                        swirl->batch_todo = BATCH_DRAW;
1371                        while ((swirl->batch_todo > 0) && swirl->drawing) {
1372                                /* draw a point */
1373                                draw_point(mi, swirl);
1374
1375                                /* move to the next point */
1376                                next_point(swirl);
1377
1378                                /* done a point */
1379                                swirl->batch_todo--;
1380                        }
1381                } else {
1382#ifdef STANDALONE
1383                  if (mi->writable_p)
1384                        rotate_colors(MI_DISPLAY(mi), MI_COLORMAP(mi),
1385                                                  swirl->rgb_values, swirl->colours, 1);
1386#else  /* !STANDALONE */
1387                        /* rotate the colours */
1388                        install_map(MI_DISPLAY(mi), swirl, swirl->shift);
1389#endif /* !STANDALONE */
1390
1391                        /* time for a higher resolution? */
1392                        if (swirl->resolution > swirl->max_resolution) {
1393                                /* move to higher resolution */
1394                                swirl->resolution--;
1395
1396                                /* calculate the pixel step for this resulution */
1397                                swirl->r = (1 << (swirl->resolution - 1));
1398
1399                                /* start drawing again */
1400                                swirl->drawing = True;
1401
1402                                /* start in the middle of the screen */
1403                                swirl->x = (swirl->width - swirl->r) / 2;
1404                                swirl->y = (swirl->height - swirl->r) / 2;
1405
1406                                /* initialise spiral drawing parameters */
1407                                swirl->direction = DRAW_RIGHT;
1408                                swirl->dir_todo = 1;
1409                                swirl->dir_done = 0;
1410                        } else {
1411                                /* all done, decide when to restart */
1412                                if (swirl->start_again == -1) {
1413                                        /* start the counter */
1414                                        swirl->start_again = RESTART;
1415                                } else if (swirl->start_again == 0) {
1416                                        /* reset the counter */
1417                                        swirl->start_again = -1;
1418
1419#ifdef STANDALONE
1420                                        /* Pick a new colormap! */
1421                                        XClearWindow (MI_DISPLAY(mi), MI_WINDOW(mi));
1422                                        free_colors (MI_DISPLAY(mi), MI_COLORMAP(mi),
1423                                                                 mi->colors, mi->npixels);
1424                                        make_smooth_colormap (MI_DISPLAY(mi),
1425                                                                                  MI_VISUAL(mi),
1426                                                                                  MI_COLORMAP(mi),
1427                                                                                  mi->colors, &mi->npixels, True,
1428                                                                                  &mi->writable_p, True);
1429                                        swirl->colours = mi->npixels;
1430#endif /* STANDALONE */
1431
1432                                        /* start again */
1433                                        init_swirl(mi);
1434                                } else
1435                                        /* decrement the counter */
1436                                        swirl->start_again--;
1437                        }
1438                }
1439        }
1440}
1441
1442/****************************************************************/
1443
1444void
1445release_swirl(ModeInfo * mi)
1446{
1447        /* does the swirls array exist? */
1448        if (swirls != NULL) {
1449                int         i;
1450
1451                /* free them all */
1452                for (i = 0; i < MI_NUM_SCREENS(mi); i++) {
1453                        SWIRL_P     swirl = &(swirls[i]);
1454
1455                        if (swirl->cmap != (Colormap) NULL)
1456                                XFreeColormap(MI_DISPLAY(mi), swirl->cmap);
1457                        if (swirl->rgb_values != NULL)
1458                                XFree((void *) swirl->rgb_values);
1459                        if (swirl->ximage != NULL)
1460                                XDestroyImage(swirl->ximage);
1461                        if (swirl->knots)
1462                                (void) free((void *) swirl->knots);
1463                }
1464                /* deallocate an array, one entry for each screen */
1465                (void) free((void *) swirls);
1466                swirls = NULL;
1467        }
1468}
1469
1470/****************************************************************/
1471
1472void
1473refresh_swirl(ModeInfo * mi)
1474{
1475        SWIRL_P     swirl = &(swirls[MI_SCREEN(mi)]);
1476
1477        if (swirl->started) {
1478                if (swirl->drawing)
1479                        swirl->resolution = swirl->resolution + 1;
1480                swirl->drawing = False;
1481        }
1482}
Note: See TracBrowser for help on using the repository browser.