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

Revision 20148, 7.4 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/* forest.c (aka xtree.c), Copyright (c) 1999
2 *  Peter Baumung <unn6@rz.uni-karlsruhe.de>
3 *
4 * Most code taken from
5 *  xscreensaver, Copyright (c) 1992, 1995, 1997
6 *  Jamie Zawinski <jwz@netscape.com>
7 *
8 * Permission to use, copy, modify, distribute, and sell this software and its
9 * documentation for any purpose is hereby granted without fee, provided that
10 * the above copyright notice appear in all copies and that both that
11 * copyright notice and this permission notice appear in supporting
12 * documentation.  No representations are made about the suitability of this
13 * software for any purpose.  It is provided "as is" without express or
14 * implied warranty.
15 */
16
17#include "config.h"
18
19/* ******************************   NOTE   ******************************
20
21     This is not the xlockmore version of forest, but a much better
22     looking rewrite.  Be careful not to delete it in a merging frenzy...
23
24   **********************************************************************
25 */
26
27#ifdef STANDALONE
28# define PROGCLASS          "Forest" /*"XTree"*/
29# define HACK_INIT          init_trees
30# define HACK_DRAW          draw_trees
31# define trees_opts         xlockmore_opts
32# define DEFAULTS   "*delay:            500000 \n"  \
33                    "*ncolors:          20     \n"  \
34                    "*eraseSpeed:       400    \n"  \
35                    "*eraseMode:        -1     \n"  \
36                    "*installColormap   False"
37# include "xlockmore.h"     /* from the xscreensaver distribution */
38#else  /* !STANDALONE */
39# include "xlock.h"                                     /* from the xlockmore distribution */
40#endif /* !STANDALONE */
41
42ModeSpecOpt trees_opts = {0, NULL, 0, NULL, NULL};
43
44typedef struct {
45  int     x;
46  int     y;
47  int     thick;
48  double  size;
49  long    color;
50  int     toDo;
51  int     season;
52} treestruct;
53
54static treestruct *trees = NULL;
55
56XColor colors[20];
57int color;
58
59static long colorM[12] = {0xff0000, 0xff8000, 0xffff00, 0x80ff00,
60                          0x00ff00, 0x00ff80, 0x00ffff, 0x0080ff,
61                          0x0000ff, 0x8000ff, 0xff00ff, 0xff0080};
62
63static long colorV[12] = {0x0a0000, 0x0a0500, 0x0a0a00, 0x050a00,
64                          0x000a00, 0x000a05, 0x000a0a, 0x00050a,
65                          0x00000a, 0x05000a, 0x0a000a, 0x0a0005};
66
67void init_trees(ModeInfo * mi) {
68        unsigned long                   pixels[20];
69  treestruct       *tree;
70  Display          *display = MI_DISPLAY(mi);
71  GC                gc = MI_GC(mi);
72  int               i;
73
74  if (trees == NULL) {
75    trees = (treestruct *) calloc(MI_NUM_SCREENS(mi), sizeof (treestruct));
76    if (trees == NULL) {
77      return;
78    }
79               
80    if (mi->npixels > 20) {
81                        printf("%d colors selected. Setting limit to 20...\n", mi->npixels);
82                        mi->npixels = 20;
83                }
84                       
85                if (mi->npixels < 4) {
86      for (i = 0; i < mi->npixels; i++) {
87        colors[i].red   = 65535 * (i & 1);
88        colors[i].green = 65535 * (i & 1);
89        colors[i].blue  = 65535 * (i & 1);
90        colors[i].flags = DoRed | DoGreen | DoBlue;
91      }
92    } else {
93      if (mi->npixels < 8) {
94        for (i = 0; i < mi->npixels; i++) {
95          colors[i].red   = 32768 + 4096 * (i % 4);
96          colors[i].green = 32768 + 4096 * (i % 4);
97          colors[i].blue  = 32768 + 4096 * (i % 4);
98          colors[i].flags = DoRed | DoGreen | DoBlue;
99        }
100      } else {
101        for (i = 0; i < mi->npixels; i++) {
102          colors[i].red   = 24576 + 4096 * (i % 4);
103          colors[i].green = 10240 + 2048 * (i % 4);
104          colors[i].blue  =  0;
105          colors[i].flags = DoRed | DoGreen | DoBlue;
106        }
107      }
108    }
109
110    for (i = 0; i < mi->npixels; i++)
111      if (!XAllocColor(display, mi->xgwa.colormap, &colors[i])) break;
112    color = i;
113
114    XSetForeground(display, gc, colors[1].pixel);
115  }
116
117  XClearWindow(display, MI_WINDOW(mi));
118  XSetLineAttributes(display, gc, 2, LineSolid, CapButt, JoinMiter);
119  tree = &trees[MI_SCREEN(mi)];
120  tree->toDo   = 25;
121        tree->season = NRAND(12);
122
123  for (i = 4; i < mi->npixels; i++) {
124    int sIndex = (tree->season + (i-4) / 4) % 12;
125    long color = colorM[sIndex] - 2 * colorV[sIndex] * (i % 4);
126    colors[i].red = (color & 0xff0000) / 256;
127    colors[i].green = (color & 0x00ff00);
128    colors[i].blue = (color & 0x0000ff) * 256;
129    colors[i].flags = DoRed | DoGreen | DoBlue;
130  }
131
132        for (i = 0; i < color; i++)
133                pixels[i] = colors[i].pixel;
134                       
135  XFreeColors(display, mi->xgwa.colormap, pixels, mi->npixels, 0L);
136
137        for (i = 0; i < mi->npixels; i++)
138    if (!XAllocColor(display, mi->xgwa.colormap, &colors[i])) break;
139
140  color = i;
141}
142
143double rRand(double a, double b) {
144  return (a+(b-a)*NRAND(10001)/10000.0);
145}
146
147void draw_line(ModeInfo * mi,
148               int x1, int y1, int x2, int y2,
149               double angle, int widths, int widthe) {
150
151  Display    *display = MI_DISPLAY(mi);
152  GC          gc = MI_GC(mi);
153  double      sns = 0.5*widths*sin(angle + M_PI_2);
154  double      css = 0.5*widths*cos(angle + M_PI_2);
155  double      sne = 0.5*widthe*sin(angle + M_PI_2);
156  double      cse = 0.5*widthe*cos(angle + M_PI_2);
157
158  int         xs1 = (int) (x1-sns);
159  int         xs2 = (int) (x1+sns);
160  int         ys1 = (int) (y1-css);
161  int         ys2 = (int) (y1+css);
162  int         xe1 = (int) (x2-sne);
163  int         xe2 = (int) (x2+sne);
164  int         ye1 = (int) (y2-cse);
165  int         ye2 = (int) (y2+cse);
166  int         i;
167
168  for (i = 0; i < widths; i++) {
169    if (color >= 4)
170      XSetForeground(display, gc, colors[i*4/widths].pixel);
171    XDrawLine(display, MI_WINDOW(mi), gc,
172      xs1+(xs2-xs1)*i/widths, ys1+(ys2-ys1)*i/widths,
173      xe1+(xe2-xe1)*i/widths, ye1+(ye2-ye1)*i/widths);
174  }
175}
176
177void draw_tree_rec(ModeInfo * mi, double thick, int x, int y, double angle) {
178  treestruct *tree = &trees[MI_SCREEN(mi)];
179  Display    *display = MI_DISPLAY(mi);
180  GC          gc = MI_GC(mi);
181  int         length = (24+NRAND(12))*tree->size;
182  int         a = (int) (x - length*sin(angle));
183  int         b = (int) (y - length*cos(angle));
184  int         i;
185
186  draw_line(mi, x, y, a, b, angle, thick*tree->size, 0.68*thick*tree->size);
187
188  if (thick > 2) {
189    draw_tree_rec(mi, 0.68*thick, a, b, 0.8*angle+rRand(-0.2, 0.2));
190    if (thick < tree->thick-1) {
191      draw_tree_rec(mi, 0.68*thick, a, b, angle+rRand(0.2, 0.9));
192      draw_tree_rec(mi, 0.68*thick, (a+x)/2, (b+y)/2, angle-rRand(0.2, 0.9));
193    }
194  }
195
196  if (thick < 0.5*tree->thick) {
197        int     nleaf = 12 + NRAND(4);
198          XArc    leaf[16];
199    for (i = 0; i < nleaf; i++) {
200      leaf[i].x = a + (int) (tree->size * rRand(-12, 12));
201      leaf[i].y = b + (int) (tree->size * rRand(-12, 12));
202      leaf[i].width = (int) (tree->size * rRand(2, 6));
203      leaf[i].height = leaf[i].width;
204      leaf[i].angle1 = 0;
205      leaf[i].angle2 = 360 * 64;
206    }
207    if (mi->npixels >= 4)
208      XSetForeground(display, gc, colors[tree->color+NRAND(4)].pixel);
209    XFillArcs(display, MI_WINDOW(mi), gc, leaf, nleaf);
210  }
211}
212
213void draw_trees(ModeInfo * mi) {
214  treestruct *tree = &trees[MI_SCREEN(mi)];
215        int                                     width = MI_WIN_WIDTH(mi);
216        int                                     height = MI_WIN_HEIGHT(mi);
217
218  if (--(tree->toDo) == 0) {
219    usleep(3000000);
220    init_trees(mi);
221  }
222
223  tree->x        = NRAND(width);
224  tree->y        = (int) (1.25 * height * (1 - tree->toDo / 23.0));
225  tree->thick    = rRand(7, 12);
226  tree->size     = height / 480.0;
227  if (color < 8) {
228    tree->color = 0;
229  } else {
230    tree->color    = 4 * (1 + NRAND(color / 4 - 1));
231  }
232
233  draw_tree_rec(mi, tree->thick, tree->x, tree->y, rRand(-0.1, 0.1));
234}
235
236void release_trees(ModeInfo * mi) {
237  if (trees != NULL) {
238    (void) free((void *) trees);
239    trees = NULL;
240  }
241}
Note: See TracBrowser for help on using the repository browser.