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

Revision 20148, 7.7 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/* slip --- lots of slipping blits */
3
4#if 0
5static const char sccsid[] = "@(#)slip.c        5.00 2000/11/01 xlockmore";
6#endif
7
8/*-
9 * Copyright (c) 1992 by Scott Draves <spot@cs.cmu.edu>
10 *
11 * Permission to use, copy, modify, and distribute this software and its
12 * documentation for any purpose and without fee is hereby granted,
13 * provided that the above copyright notice appear in all copies and that
14 * both that copyright notice and this permission notice appear in
15 * supporting documentation.
16 *
17 * This file is provided AS IS with no warranties of any kind.  The author
18 * shall have no liability with respect to the infringement of copyrights,
19 * trade secrets or any patents by this file or any part thereof.  In no
20 * event will the author be liable for any lost revenue or profits or
21 * other special, indirect and consequential damages.
22 *
23 * 01-Nov-2000: Allocation checks
24 * 10-May-1997: Jamie Zawinski <jwz@jwz.org> compatible with xscreensaver
25 * 01-Dec-1995: Patched for VMS <joukj@hrem.stm.tudelft.nl>
26 */
27
28#ifdef STANDALONE
29#define MODE_slip
30#define PROGCLASS "Slip"
31#define HACK_INIT init_slip
32#define HACK_DRAW draw_slip
33#define slip_opts xlockmore_opts
34#define DEFAULTS "*delay: 50000 \n" \
35 "*count: 35 \n" \
36 "*cycles: 50 \n" \
37 "*ncolors: 200 \n"
38#include "xlockmore.h"          /* in xscreensaver distribution */
39#else /* STANDALONE */
40#include "xlock.h"              /* in xlockmore distribution */
41#endif /* STANDALONE */
42
43#ifdef MODE_slip
44
45ModeSpecOpt slip_opts =
46{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
47
48#ifdef USE_MODULES
49ModStruct   slip_description =
50{"slip", "init_slip", "draw_slip", "release_slip",
51 "init_slip", "init_slip", (char *) NULL, &slip_opts,
52 50000, 35, 50, 1, 64, 1.0, "",
53 "Shows slipping blits", 0, NULL};
54
55#endif
56
57typedef struct {
58        int         width, height;
59        int         nblits_remaining;
60        int         blit_width, blit_height;
61        int         mode;
62        int         first_time;
63        int         backwards;
64        short       lasthalf;
65        int         stage;
66        unsigned long r;
67} slipstruct;
68static slipstruct *slips = (slipstruct *) NULL;
69
70static short
71halfrandom(slipstruct *sp, int mv)
72{
73        unsigned long r;
74
75        if (sp->lasthalf) {
76                r = sp->lasthalf;
77                sp->lasthalf = 0;
78        } else {
79                r = LRAND();
80                sp->lasthalf = (short) (r >> 16);
81        }
82        return r % mv;
83}
84
85static int
86erandom(slipstruct *sp, int mv)
87{
88        int         res;
89
90        if (0 == sp->stage) {
91                sp->r = LRAND();
92                sp->stage = 7;
93        }
94        res = (int) (sp->r & 0xf);
95        sp->r = sp->r >> 4;
96        sp->stage--;
97        if (res & 8)
98                return res & mv;
99        else
100                return -(res & mv);
101}
102
103static void
104prepare_screen(ModeInfo * mi, slipstruct * sp)
105{
106
107        Display    *display = MI_DISPLAY(mi);
108        GC          gc = MI_GC(mi);
109        int         i, n, w = sp->width / 20;
110        int         not_solid = halfrandom(sp, 10);
111
112#ifdef STANDALONE                         /* jwz -- sometimes hack the desktop image! */
113        if (halfrandom(sp, 2) == 0) {
114      load_random_image (DefaultScreenOfDisplay(display),
115                                  MI_WINDOW(mi), MI_WINDOW(mi), NULL);
116        }
117#endif
118
119        sp->backwards = (int) (LRAND() & 1);    /* jwz: go the other way sometimes */
120
121        if (sp->first_time || !halfrandom(sp, 10)) {
122                MI_CLEARWINDOW(mi);
123                n = 300;
124        } else {
125                if (halfrandom(sp, 5))
126                        return;
127                if (halfrandom(sp, 5))
128                        n = 100;
129                else
130                        n = 2000;
131        }
132
133        if (MI_NPIXELS(mi) > 2)
134                XSetForeground(display, gc, MI_PIXEL(mi, halfrandom(sp, MI_NPIXELS(mi))));
135        else if (halfrandom(sp, 2))
136                XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
137        else
138                XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
139
140        for (i = 0; i < n; i++) {
141                int         ww = ((w / 2) + halfrandom(sp, MAX(w, 1)));
142
143                if (not_solid) {
144                        if (MI_NPIXELS(mi) > 2)
145                                XSetForeground(display, gc, MI_PIXEL(mi, halfrandom(sp, MI_NPIXELS(mi))));
146                        else if (halfrandom(sp, 2))
147                                XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
148                        else
149                                XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
150                }
151                XFillRectangle(display, MI_WINDOW(mi), gc,
152                               halfrandom(sp, MAX(sp->width - ww, 1)),
153                               halfrandom(sp, MAX(sp->height - ww, 1)),
154                               ww, ww);
155        }
156        sp->first_time = 0;
157}
158
159static int
160quantize(double d)
161{
162        int         i = (int) floor(d);
163        double      f = d - i;
164
165        if ((LRAND() & 0xff) < f * 0xff)
166                i++;
167        return i;
168}
169
170void
171init_slip(ModeInfo * mi)
172{
173        slipstruct *sp;
174
175        if (slips == NULL) {
176                if ((slips = (slipstruct *) calloc(MI_NUM_SCREENS(mi),
177                                               sizeof (slipstruct))) == NULL)
178                        return;
179        }
180        sp = &slips[MI_SCREEN(mi)];
181
182        sp->width = MI_WIDTH(mi);
183        sp->height = MI_HEIGHT(mi);
184
185        sp->blit_width = sp->width / 25;
186        sp->blit_height = sp->height / 25;
187        sp->nblits_remaining = 0;
188        sp->mode = 0;
189        sp->first_time = 1;
190
191        /* no "NoExpose" events from XCopyArea wanted */
192        XSetGraphicsExposures(MI_DISPLAY(mi), MI_GC(mi), False);
193}
194
195void
196draw_slip(ModeInfo * mi)
197{
198        Display    *display = MI_DISPLAY(mi);
199        Window      window = MI_WINDOW(mi);
200        GC          gc = MI_GC(mi);
201        int         timer;
202        slipstruct *sp;
203
204        if (slips == NULL)
205                return;
206        sp = &slips[MI_SCREEN(mi)];
207
208        timer = MI_COUNT(mi) * MI_CYCLES(mi);
209
210        MI_IS_DRAWN(mi) = True;
211
212        while (timer--) {
213                int         xi = halfrandom(sp, MAX(sp->width - sp->blit_width, 1));
214                int         yi = halfrandom(sp, MAX(sp->height - sp->blit_height, 1));
215                double      x, y, dx = 0, dy = 0, t, s1, s2;
216
217                if (0 == sp->nblits_remaining--) {
218                        static int  lut[] =
219                        {0, 0, 0, 1, 1, 1, 2};
220
221                        prepare_screen(mi, sp);
222                        sp->nblits_remaining = MI_COUNT(mi) *
223                                (2000 + halfrandom(sp, 1000) + halfrandom(sp, 1000));
224                        if (sp->mode == 2)
225                                sp->mode = halfrandom(sp, 2);
226                        else
227                                sp->mode = lut[halfrandom(sp, 7)];
228                }
229                x = (2 * xi + sp->blit_width) / (double) sp->width - 1;
230                y = (2 * yi + sp->blit_height) / (double) sp->height - 1;
231
232                /* (x,y) is in biunit square */
233                switch (sp->mode) {
234                        case 0: /* rotor */
235                                dx = x;
236                                dy = y;
237
238                                if (dy < 0) {
239                                        dy += 0.04;
240                                        if (dy > 0)
241                                                dy = 0.00;
242                                }
243                                if (dy > 0) {
244                                        dy -= 0.04;
245                                        if (dy < 0)
246                                                dy = 0.00;
247                                }
248                                t = dx * dx + dy * dy + 1e-10;
249                                s1 = 2 * dx * dx / t - 1;
250                                s2 = 2 * dx * dy / t;
251                                dx = s1 * 5;
252                                dy = s2 * 5;
253
254                                if (sp->backwards) {    /* jwz: go the other way sometimes */
255                                        dx = -dx;
256                                        dy = -dy;
257                                }
258                                break;
259                        case 1: /* shuffle */
260                                dx = erandom(sp, 3);
261                                dy = erandom(sp, 3);
262                                break;
263                        case 2: /* explode */
264                                dx = x * 3;
265                                dy = y * 3;
266                                break;
267                }
268                {
269                        int         qx = xi + quantize(dx), qy = yi + quantize(dy);
270                        int         wrap;
271
272                        if (qx < 0 || qy < 0 ||
273                            qx >= sp->width - sp->blit_width ||
274                            qy >= sp->height - sp->blit_height)
275                                continue;
276
277/*-
278Seems to cause problems using Exceed
279with PseudoColor
280X Error of failed request:  BadGC (invalid GC parameter)
281with TrueColor
282X Error of failed request:  BadDrawable (invalid Pixmap or Window parameter)
283  Major opcode of failed request:  62 (X_CopyArea)
284 */
285                        XCopyArea(display, window, window, gc, xi, yi,
286                                  sp->blit_width, sp->blit_height,
287                                  qx, qy);
288                        switch (sp->mode) {
289                                case 0:
290                                        /* wrap */
291                                        wrap = sp->width - (2 * sp->blit_width);
292                                        if (qx > wrap ) {
293                                                XCopyArea(display, window, window, gc, qx, qy,
294                                                sp->blit_width, sp->blit_height,
295                                                          qx - wrap, qy);
296                                        }
297                                        if (qx < 2 * sp->blit_width) {
298                                                XCopyArea(display, window, window, gc, qx, qy,
299                                                sp->blit_width, sp->blit_height,
300                                                          qx + wrap, qy);
301                                        }
302                                        wrap = sp->height - (2 * sp->blit_height);
303                                        if (qy > wrap) {
304                                                XCopyArea(display, window, window, gc, qx, qy,
305                                                sp->blit_width, sp->blit_height,
306                                                          qx, qy - wrap);
307                                        }
308                                        if (qy < 2 * sp->blit_height) {
309                                                XCopyArea(display, window, window, gc, qx, qy,
310                                                sp->blit_width, sp->blit_height,
311                                                          qx, qy + wrap);
312                                        }
313                                        break;
314                                case 1:
315                                case 2:
316                                        break;
317                        }
318                }
319        }
320}
321
322void
323release_slip(ModeInfo * mi)
324{
325        if (slips != NULL) {
326                (void) free((void *) slips);
327                slips = (slipstruct *) NULL;
328        }
329}
330
331#endif /* MODE_slip */
Note: See TracBrowser for help on using the repository browser.