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

Revision 20148, 8.2 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/* xscreensaver, Copyright (c) 1992, 1993, 1994, 1996, 1997
2 * Jamie Zawinski <jwz@jwz.org>
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/* decayscreen
14 *
15 * Based on slidescreen program from the xscreensaver application and the
16 * decay program for Sun framebuffers.  This is the comment from the decay.c
17 * file:
18
19 * decay.c
20 *   find the screen bitmap for the console and make it "decay" by
21 *   randomly shifting random rectangles by one pixelwidth at a time.
22 *
23 *   by David Wald, 1988
24 *        rewritten by Natuerlich!
25 *   based on a similar "utility" on the Apollo ring at Yale.
26
27 * X version by
28 *
29 *  Vivek Khera <khera@cs.duke.edu>
30 *  5-AUG-1993
31 *
32 *  Hacked by jwz, 28-Nov-97 (sped up and added new motion directions)
33 
34 *  R. Schultz
35 *  Added "melt" & "stretch" modes 28-Mar-1999
36 *
37 */
38
39#include "screenhack.h"
40
41static int sizex, sizey;
42static int delay;
43static GC gc;
44static int mode;
45static int iterations=100;
46
47#define SHUFFLE 0
48#define UP 1
49#define LEFT 2
50#define RIGHT 3
51#define DOWN 4
52#define UPLEFT 5
53#define DOWNLEFT 6
54#define UPRIGHT 7
55#define DOWNRIGHT 8
56#define IN 9
57#define OUT 10
58#define MELT 11
59#define STRETCH 12
60#define FUZZ 13
61
62static void
63init_decay (Display *dpy, Window window)
64{
65  XGCValues gcv;
66  XWindowAttributes xgwa;
67  long gcflags;
68  unsigned long bg;
69
70  char *s = get_string_resource("mode", "Mode");
71  if      (s && !strcmp(s, "shuffle")) mode = SHUFFLE;
72  else if (s && !strcmp(s, "up")) mode = UP;
73  else if (s && !strcmp(s, "left")) mode = LEFT;
74  else if (s && !strcmp(s, "right")) mode = RIGHT;
75  else if (s && !strcmp(s, "down")) mode = DOWN;
76  else if (s && !strcmp(s, "upleft")) mode = UPLEFT;
77  else if (s && !strcmp(s, "downleft")) mode = DOWNLEFT;
78  else if (s && !strcmp(s, "upright")) mode = UPRIGHT;
79  else if (s && !strcmp(s, "downright")) mode = DOWNRIGHT;
80  else if (s && !strcmp(s, "in")) mode = IN;
81  else if (s && !strcmp(s, "out")) mode = OUT;
82  else if (s && !strcmp(s, "melt")) mode = MELT;
83  else if (s && !strcmp(s, "stretch")) mode = STRETCH;
84  else if (s && !strcmp(s, "fuzz")) mode = FUZZ;
85  else {
86    if (s && *s && !!strcmp(s, "random"))
87      fprintf(stderr, "%s: unknown mode %s\n", progname, s);
88    mode = random() % (FUZZ+1);
89  }
90
91  delay = get_integer_resource ("delay", "Integer");
92
93  if (delay < 0) delay = 0;
94
95  XGetWindowAttributes (dpy, window, &xgwa);
96
97  gcv.function = GXcopy;
98  gcv.subwindow_mode = IncludeInferiors;
99
100  if (mode == MELT || mode == STRETCH) {
101    bg = get_pixel_resource ("background", "Background", dpy, xgwa.colormap);
102    gcv.foreground = bg;
103  }
104
105  gcflags = GCForeground |GCFunction;
106  if (use_subwindow_mode_p(xgwa.screen, window)) /* see grabscreen.c */
107    gcflags |= GCSubwindowMode;
108  gc = XCreateGC (dpy, window, gcflags, &gcv);
109
110  sizex = xgwa.width;
111  sizey = xgwa.height;
112
113  load_random_image (xgwa.screen, window, window, NULL);
114 
115  if (mode == MELT || mode == STRETCH) {
116    /* make sure screen eventually turns background color */
117    XDrawLine(dpy, window, gc, 0, 0, sizex, 0);
118
119    /* slow down for smoother melting*/
120    iterations = 1;
121  }
122
123}
124
125
126/*
127 * perform one iteration of decay
128 */
129static void
130decay1 (Display *dpy, Window window)
131{
132    int left, top, width, height, toleft, totop;
133
134#define L 101
135#define R 102
136#define U 103
137#define D 104
138    static int no_bias[]        = { L,L,L,L, R,R,R,R, U,U,U,U, D,D,D,D };
139    static int up_bias[]        = { L,L,L,L, R,R,R,R, U,U,U,U, U,U,D,D };
140    static int down_bias[]      = { L,L,L,L, R,R,R,R, U,U,D,D, D,D,D,D };
141    static int left_bias[]      = { L,L,L,L, L,L,R,R, U,U,U,U, D,D,D,D };
142    static int right_bias[]     = { L,L,R,R, R,R,R,R, U,U,U,U, D,D,D,D };
143
144    static int upleft_bias[]    = { L,L,L,L, L,R,R,R, U,U,U,U, U,D,D,D };
145    static int downleft_bias[]  = { L,L,L,L, L,R,R,R, U,U,U,D, D,D,D,D };
146    static int upright_bias[]   = { L,L,L,R, R,R,R,R, U,U,U,U, U,D,D,D };
147    static int downright_bias[] = { L,L,L,R, R,R,R,R, U,U,U,D, D,D,D,D };
148    static int *bias;
149
150    switch (mode) {
151      case SHUFFLE:     bias = no_bias; break;
152      case UP:          bias = up_bias; break;
153      case LEFT:        bias = left_bias; break;
154      case RIGHT:       bias = right_bias; break;
155      case DOWN:        bias = down_bias; break;
156      case UPLEFT:      bias = upleft_bias; break;
157      case DOWNLEFT:    bias = downleft_bias; break;
158      case UPRIGHT:     bias = upright_bias; break;
159      case DOWNRIGHT:   bias = downright_bias; break;
160      case IN:          bias = no_bias; break;
161      case OUT:         bias = no_bias; break;
162      case MELT:        bias = no_bias; break;
163      case STRETCH:     bias = no_bias; break;
164      case FUZZ:        bias = no_bias; break;
165     default: abort();
166    }
167
168#define nrnd(x) (random() % (x))
169
170    if (mode == MELT || mode == STRETCH) {
171      left = nrnd(sizex/2);
172      top = nrnd(sizey);
173      width = nrnd( sizex/2 ) + sizex/2 - left;
174      height = nrnd(sizey - top);
175      toleft = left;
176      totop = top+1;
177
178    } else if (mode == FUZZ) {  /* By Vince Levey <vincel@vincel.org>;
179                                   inspired by the "melt" mode of the
180                                   "scrhack" IrisGL program by Paul Haeberli
181                                   circa 1991. */
182      static int toggle = 0;
183
184      left = nrnd(sizex - 1);
185      top  = nrnd(sizey - 1);
186      toggle = !toggle;
187      if (toggle)
188        {
189          totop = top;
190          height = 1;
191          toleft = nrnd(sizex - 1);
192          if (toleft > left)
193            {
194              width = toleft-left;
195              toleft = left;
196              left++;
197            }
198          else
199            {
200              width = left-toleft;
201              left = toleft;
202              toleft++;
203            }
204        }
205      else
206        {
207          toleft = left;
208          width = 1;
209          totop  = nrnd(sizey - 1);
210          if (totop > top)
211            {
212              height = totop-top;
213              totop = top;
214              top++;
215            }
216          else
217            {
218              height = top-totop;
219              top = totop;
220              totop++;
221            }
222        }
223
224    } else {
225
226      left = nrnd(sizex - 1);
227      top = nrnd(sizey);
228      width = nrnd(sizex - left);
229      height = nrnd(sizey - top);
230     
231      toleft = left;
232      totop = top;
233      if (mode == IN || mode == OUT) {
234        int x = left+(width/2);
235        int y = top+(height/2);
236        int cx = sizex/2;
237        int cy = sizey/2;
238        if (mode == IN) {
239          if      (x > cx && y > cy)   bias = upleft_bias;
240          else if (x < cx && y > cy)   bias = upright_bias;
241          else if (x < cx && y < cy)   bias = downright_bias;
242          else /* (x > cx && y < cy)*/ bias = downleft_bias;
243        } else {
244          if      (x > cx && y > cy)   bias = downright_bias;
245          else if (x < cx && y > cy)   bias = downleft_bias;
246          else if (x < cx && y < cy)   bias = upleft_bias;
247          else /* (x > cx && y < cy)*/ bias = upright_bias;
248        }
249      }
250     
251      switch (bias[random() % (sizeof(no_bias)/sizeof(*no_bias))]) {
252      case L: toleft = left-1; break;
253      case R: toleft = left+1; break;
254      case U: totop = top-1; break;
255      case D: totop = top+1; break;
256      default: abort(); break;
257      }
258    }
259   
260    if (mode == STRETCH) {
261      XCopyArea (dpy, window, window, gc, 0, sizey-top-2, sizex, top+1,
262                 0, sizey-top-1);
263    } else {
264      XCopyArea (dpy, window, window, gc, left, top, width, height,
265                 toleft, totop);
266    }
267
268#undef nrnd
269}
270
271
272char *progclass = "DecayScreen";
273
274char *defaults [] = {
275  "*dontClearRoot:              True",
276
277#ifdef __sgi    /* really, HAVE_READ_DISPLAY_EXTENSION */
278  "*visualID:                   Best",
279#endif
280
281  "*delay:                      10000",
282  "*mode:                       random",
283  0
284};
285
286XrmOptionDescRec options [] = {
287  { "-delay",           ".delay",               XrmoptionSepArg, 0 },
288  { "-mode",            ".mode",                XrmoptionSepArg, 0 },
289  { 0, 0, 0, 0 }
290};
291
292void
293screenhack (Display *dpy, Window window)
294{
295    init_decay (dpy, window);
296    while (1) {
297      int i;
298      for (i = 0; i < iterations; i++)
299        decay1 (dpy, window);
300      XSync(dpy, False);
301      screenhack_handle_events (dpy);
302      if (delay) usleep (delay);
303    }
304}
Note: See TracBrowser for help on using the repository browser.