~ubuntu-branches/ubuntu/breezy/xscreensaver/breezy

« back to all changes in this revision

Viewing changes to hacks/metaballs.c

  • Committer: Bazaar Package Importer
  • Author(s): Oliver Grawert
  • Date: 2005-10-11 21:00:42 UTC
  • mfrom: (2.1.1 sarge)
  • Revision ID: james.westby@ubuntu.com-20051011210042-u7q6zslgevdxspr3
Tags: 4.21-4ubuntu17
updated pt_BR again, fixed to UTF-8 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* MetaBalls, Copyright (c) 2002-2003 W.P. van Paassen <peter@paassen.tmfweb.nl>
 
2
 *
 
3
 * Permission to use, copy, modify, distribute, and sell this software and its
 
4
 * documentation for any purpose is hereby granted without fee, provided that
 
5
 * the above copyright notice appear in all copies and that both that
 
6
 * copyright notice and this permission notice appear in supporting
 
7
 * documentation.  No representations are made about the suitability of this
 
8
 * software for any purpose.  It is provided "as is" without express or
 
9
 * implied warranty.
 
10
 *
 
11
 * Module - "metaballs.c"
 
12
 *
 
13
 * [01/24/03] - W.P. van Paassen: Additional features
 
14
 * [12/29/02] - W.P. van Paassen: Port to X for use with XScreenSaver, the shadebob hack by Shane Smit was used as a template
 
15
 * [12/26/02] - W.P. van Paassen: Creation for the Demo Effects Collection (http://demo-effects.sourceforge.net)
 
16
 */
 
17
 
 
18
#include <math.h>
 
19
#include "screenhack.h"
 
20
#include <X11/Xutil.h>
 
21
 
 
22
/*#define VERBOSE*/ 
 
23
 
 
24
char *progclass = "Metaballs";
 
25
 
 
26
char *defaults [] = {
 
27
  ".background: black",
 
28
  ".foreground: white",
 
29
  "*color:    random",
 
30
  "*count:    10",
 
31
  "*cycles:   1000",
 
32
  "*ncolors:  256",
 
33
  "*delay:    5000",
 
34
  "*radius:   100",
 
35
  "*delta:   3",
 
36
  0
 
37
};
 
38
 
 
39
XrmOptionDescRec options [] = {
 
40
  { "-color",   ".color",   XrmoptionSepArg, 0 },
 
41
  { "-ncolors", ".ncolors", XrmoptionSepArg, 0 },
 
42
  { "-count",   ".count",   XrmoptionSepArg, 0 },
 
43
  { "-delay",   ".delay",   XrmoptionSepArg, 0 },
 
44
  { "-cycles",  ".cycles",  XrmoptionSepArg, 0 },
 
45
  { "-radius",  ".radius",  XrmoptionSepArg, 0 },
 
46
  { "-delta",  ".delta",  XrmoptionSepArg, 0 },
 
47
  { 0, 0, 0, 0 }
 
48
};
 
49
 
 
50
static unsigned short iWinWidth, iWinHeight;
 
51
static char *sColor;
 
52
 
 
53
/*blob structure*/
 
54
typedef struct 
 
55
{
 
56
  short xpos,ypos;
 
57
} BLOB;
 
58
 
 
59
static unsigned int nBlobCount;
 
60
static unsigned char radius;
 
61
static unsigned char delta;
 
62
static unsigned char dradius;
 
63
static unsigned short sradius;
 
64
static unsigned char **blob;
 
65
static BLOB *blobs;
 
66
static unsigned char **blub;
 
67
 
 
68
#undef BELLRAND
 
69
#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3)
 
70
 
 
71
static void init_blob(BLOB *blob)
 
72
{
 
73
  blob->xpos = iWinWidth/4  + BELLRAND(iWinWidth/2)  - radius;
 
74
  blob->ypos = iWinHeight/4 + BELLRAND(iWinHeight/2) - radius;
 
75
}
 
76
 
 
77
static void Execute( Display *pDisplay,
 
78
                     Window MainWindow,
 
79
                     GC *pGC, XImage *pImage,
 
80
                     signed short iColorCount, unsigned long *aiColorVals )
 
81
{
 
82
        unsigned int i, j, k;
 
83
 
 
84
        /* clear blub array */
 
85
        for (i = 0; i < iWinHeight; ++i)
 
86
          memset(blub[i], 0, iWinWidth * sizeof(unsigned char));
 
87
 
 
88
        /* move blobs */
 
89
        for (i = 0; i < nBlobCount; i++)
 
90
        {
 
91
          blobs[i].xpos += -delta + (int)((delta + .5f) * frand(2.0));
 
92
          blobs[i].ypos += -delta + (int)((delta + .5f) * frand(2.0));
 
93
        }
 
94
 
 
95
        /* draw blobs to blub array */
 
96
        for (k = 0; k < nBlobCount; ++k)
 
97
          { 
 
98
            if (blobs[k].ypos > -dradius && blobs[k].xpos > -dradius && blobs[k].ypos < iWinHeight && blobs[k].xpos < iWinWidth)
 
99
              {
 
100
                for (i = 0; i < dradius; ++i)
 
101
                  {
 
102
                    if (blobs[k].ypos + i >= 0 && blobs[k].ypos + i < iWinHeight)
 
103
                      {
 
104
                        for (j = 0; j < dradius; ++j)
 
105
                          {
 
106
                            if (blobs[k].xpos + j >= 0 && blobs[k].xpos + j < iWinWidth)
 
107
                              {
 
108
                                if (blub[blobs[k].ypos + i][blobs[k].xpos + j] < iColorCount)
 
109
                                  {
 
110
                                    if (blub[blobs[k].ypos + i][blobs[k].xpos + j] + blob[i][j] > iColorCount)
 
111
                                      blub[blobs[k].ypos + i][blobs[k].xpos + j] = iColorCount;
 
112
                                    else 
 
113
                                      blub[blobs[k].ypos + i][blobs[k].xpos + j] += blob[i][j];     
 
114
                                  }
 
115
                              }
 
116
                          }
 
117
                      }
 
118
                  }
 
119
              }
 
120
            else
 
121
              init_blob(blobs + k);
 
122
          }
 
123
 
 
124
        memset( pImage->data, 0, pImage->bytes_per_line * pImage->height);
 
125
 
 
126
        /* draw blub array to screen */
 
127
        for (i = 0; i < iWinHeight; ++i)
 
128
          {
 
129
            for (j = 0; j < iWinWidth; ++j)
 
130
              {
 
131
                if (aiColorVals[blub[i][j]] > 0)
 
132
                  XPutPixel( pImage, j, i, aiColorVals[blub[i][j]] );
 
133
              }
 
134
          }
 
135
 
 
136
        XPutImage( pDisplay, MainWindow, *pGC, pImage,
 
137
                   0, 0, 0, 0, iWinWidth, iWinHeight );
 
138
        XSync( pDisplay, False );
 
139
}
 
140
 
 
141
static unsigned long * SetPalette(Display *pDisplay, Window Win, char *sColor, signed short *piColorCount )
 
142
{
 
143
        XWindowAttributes XWinAttribs;
 
144
        XColor Color, *aColors;
 
145
        unsigned long *aiColorVals;
 
146
        signed short iColor;
 
147
        float nHalfColors;
 
148
        
 
149
        XGetWindowAttributes( pDisplay, Win, &XWinAttribs );
 
150
        
 
151
        Color.red =   random() % 0xFFFF;
 
152
        Color.green = random() % 0xFFFF;
 
153
        Color.blue =  random() % 0xFFFF;
 
154
 
 
155
        if( strcasecmp( sColor, "random" ) && !XParseColor( pDisplay, XWinAttribs.colormap, sColor, &Color ) )
 
156
                fprintf( stderr, "%s: color %s not found in database. Choosing to random...\n", progname, sColor );
 
157
 
 
158
#ifdef VERBOSE
 
159
        printf( "%s: Base color (RGB): <%d, %d, %d>\n", progclass, Color.red, Color.green, Color.blue );
 
160
#endif  /*  VERBOSE */
 
161
 
 
162
        *piColorCount = get_integer_resource( "ncolors", "Integer" );
 
163
        if( *piColorCount <   2 )       *piColorCount = 2;
 
164
        if( *piColorCount > 255 )       *piColorCount = 255;
 
165
 
 
166
        aColors    = calloc( *piColorCount, sizeof(XColor) );
 
167
        aiColorVals = calloc( *piColorCount, sizeof(unsigned long) );
 
168
        
 
169
        for( iColor=0; iColor<*piColorCount; iColor++ )
 
170
        {
 
171
                nHalfColors = *piColorCount / 2.0F;
 
172
                /* Black -> Base Color */
 
173
                if( iColor < (*piColorCount/2) )
 
174
                {
 
175
                        aColors[ iColor ].red   = ( Color.red   / nHalfColors ) * iColor;
 
176
                        aColors[ iColor ].green = ( Color.green / nHalfColors ) * iColor;
 
177
                        aColors[ iColor ].blue  = ( Color.blue  / nHalfColors ) * iColor;
 
178
                }
 
179
                /* Base Color -> White */
 
180
                else
 
181
                {
 
182
                        aColors[ iColor ].red   = ( ( ( 0xFFFF - Color.red )   / nHalfColors ) * ( iColor - nHalfColors ) ) + Color.red;
 
183
                        aColors[ iColor ].green = ( ( ( 0xFFFF - Color.green ) / nHalfColors ) * ( iColor - nHalfColors ) ) + Color.green;
 
184
                        aColors[ iColor ].blue  = ( ( ( 0xFFFF - Color.blue )  / nHalfColors ) * ( iColor - nHalfColors ) ) + Color.blue;
 
185
                }
 
186
 
 
187
                if( !XAllocColor( pDisplay, XWinAttribs.colormap, &aColors[ iColor ] ) )
 
188
                {
 
189
                        /* start all over with less colors */   
 
190
                        XFreeColors( pDisplay, XWinAttribs.colormap, aiColorVals, iColor, 0 );
 
191
                        free( aColors );
 
192
                        free( aiColorVals );
 
193
                        (*piColorCount)--;
 
194
 
 
195
                        if (*piColorCount < 6)
 
196
                          {
 
197
                            fprintf (stderr, "%s: insufficient colors!\n",
 
198
                                     progname);
 
199
                            exit (1);
 
200
                          }
 
201
 
 
202
                        aColors     = calloc( *piColorCount, sizeof(XColor) );
 
203
                        aiColorVals = calloc( *piColorCount, sizeof(unsigned long) );
 
204
                        iColor = -1;
 
205
                }
 
206
                else
 
207
                        aiColorVals[ iColor ] = aColors[ iColor ].pixel;
 
208
        }
 
209
 
 
210
        free( aColors );
 
211
 
 
212
        XSetWindowBackground( pDisplay, Win, aiColorVals[ 0 ] );
 
213
 
 
214
        return aiColorVals;
 
215
}
 
216
 
 
217
 
 
218
static void Initialize( Display *pDisplay, Window Win, GC *pGC, XImage **ppImage )
 
219
{
 
220
        XGCValues gcValues;
 
221
        XWindowAttributes XWinAttribs;
 
222
        int iBitsPerPixel, i, j;
 
223
        unsigned int distance_squared;
 
224
        float fraction;
 
225
 
 
226
        /* Create the Image for drawing */
 
227
        XGetWindowAttributes( pDisplay, Win, &XWinAttribs );
 
228
 
 
229
        /* Find the preferred bits-per-pixel. (jwz) */
 
230
        {
 
231
                int pfvc = 0;
 
232
                XPixmapFormatValues *pfv = XListPixmapFormats( pDisplay, &pfvc );
 
233
                for( i=0; i<pfvc; i++ )
 
234
                        if( pfv[ i ].depth == XWinAttribs.depth )
 
235
                        {
 
236
                                iBitsPerPixel = pfv[ i ].bits_per_pixel;
 
237
                                break;
 
238
                        }
 
239
                if( pfv )
 
240
                        XFree (pfv);
 
241
        }
 
242
 
 
243
        /*  Create the GC. */
 
244
        *pGC = XCreateGC( pDisplay, Win, 0, &gcValues );
 
245
 
 
246
        *ppImage = XCreateImage( pDisplay, XWinAttribs.visual, XWinAttribs.depth, ZPixmap, 0, NULL,
 
247
                                                          XWinAttribs.width, XWinAttribs.height, BitmapPad( pDisplay ), 0 );
 
248
        (*ppImage)->data = calloc((*ppImage)->bytes_per_line, (*ppImage)->height);
 
249
 
 
250
        iWinWidth = XWinAttribs.width;
 
251
        iWinHeight = XWinAttribs.height;
 
252
 
 
253
        /*  Get the base color. */
 
254
        sColor = get_string_resource( "color", "Color" );
 
255
 
 
256
        /*  Get the delta. */
 
257
        delta = get_integer_resource( "delta", "Integer" );
 
258
        if (delta < 1)
 
259
          delta = 1;
 
260
        else if (delta > 20)
 
261
          delta = 20;
 
262
        
 
263
        /*  Get the radius. */
 
264
        radius = get_integer_resource( "radius", "Integer" );
 
265
        if (radius < 2)
 
266
          radius = 2;
 
267
        if (radius > 100)
 
268
          radius = 100;
 
269
        
 
270
        radius = (radius / 100.0) * (iWinHeight >> 3);
 
271
        if (radius >= 128) /* should use UCHAR_MAX? */
 
272
          radius = 127; /* dradius should fit in u_char */
 
273
 
 
274
        dradius = radius * 2;
 
275
        sradius = radius * radius;
 
276
 
 
277
        /* create blob */
 
278
        blob = malloc ( dradius * sizeof(unsigned char*));
 
279
        for (i = 0; i < dradius; ++i)
 
280
          blob[i] = malloc( dradius * sizeof(unsigned char));
 
281
 
 
282
        /* create blub array */
 
283
        blub = malloc( iWinHeight * sizeof(unsigned char*));
 
284
        for (i = 0; i < iWinHeight; ++i)
 
285
          blub[i] = malloc( iWinWidth * sizeof(unsigned char));
 
286
 
 
287
        /* create blob */
 
288
        for (i = -radius; i < radius; ++i)
 
289
          {
 
290
            for (j = -radius; j < radius; ++j)
 
291
              {
 
292
                distance_squared = i * i + j * j;
 
293
                if (distance_squared <= sradius)
 
294
                  {
 
295
                    /* compute density */     
 
296
                    fraction = (float)distance_squared / (float)sradius;
 
297
                    blob[i + radius][j + radius] = pow((1.0 - (fraction * fraction)),4.0) * 255.0;
 
298
                  }
 
299
                else
 
300
                  {
 
301
                    blob[i + radius][j + radius] = 0;
 
302
                  }
 
303
              }    
 
304
          }
 
305
        
 
306
        for (i = 0; i < nBlobCount; i++)
 
307
          {
 
308
            init_blob(blobs + i);
 
309
          }
 
310
}
 
311
 
 
312
void screenhack(Display *pDisplay, Window Win )
 
313
{
 
314
        GC gc;
 
315
        signed short iColorCount = 0;
 
316
        unsigned long *aiColorVals = NULL;
 
317
        XImage *pImage = NULL;
 
318
#ifdef VERBOSE
 
319
        time_t nTime = time( NULL );
 
320
        unsigned short iFrame = 0;
 
321
#endif  /*  VERBOSE */
 
322
        int delay, cycles, i;
 
323
 
 
324
        nBlobCount = get_integer_resource( "count", "Integer" );
 
325
        if( nBlobCount > 255 ) nBlobCount = 255;
 
326
        if( nBlobCount <  2 ) nBlobCount = 2;
 
327
 
 
328
        if( ( blobs = calloc( nBlobCount, sizeof(BLOB) ) ) == NULL )
 
329
        {
 
330
                fprintf( stderr, "%s: Could not allocate %d Blobs\n", progclass, nBlobCount );
 
331
                return;
 
332
        }
 
333
#ifdef VERBOSE 
 
334
        printf( "%s: Allocated %d Blobs\n", progclass, nBlobCount );
 
335
#endif  /*  VERBOSE */
 
336
 
 
337
        Initialize( pDisplay, Win, &gc, &pImage );
 
338
 
 
339
        delay = get_integer_resource( "delay", "Integer" );
 
340
        cycles = get_integer_resource( "cycles", "Integer" );
 
341
        i = cycles;
 
342
 
 
343
        while( 1 )
 
344
        {
 
345
                screenhack_handle_events( pDisplay );
 
346
 
 
347
                if( i++ >= cycles )
 
348
                {
 
349
                        XWindowAttributes XWinAttribs;
 
350
                        XGetWindowAttributes( pDisplay, Win, &XWinAttribs );
 
351
 
 
352
                        memset( pImage->data, 0, pImage->bytes_per_line * pImage->height );
 
353
                        XFreeColors( pDisplay, XWinAttribs.colormap, aiColorVals, iColorCount, 0 );
 
354
                        free( aiColorVals );
 
355
                        aiColorVals = SetPalette( pDisplay, Win, sColor, &iColorCount );
 
356
                        XClearWindow( pDisplay, Win );
 
357
                        for (i = 0; i < nBlobCount; i++)
 
358
                          {
 
359
                            init_blob(blobs + i);
 
360
                          }
 
361
                        i = 0;
 
362
                }
 
363
 
 
364
                Execute( pDisplay, Win, &gc, pImage, iColorCount - 1, aiColorVals );
 
365
 
 
366
                if( delay && !(i % 4) )
 
367
                        usleep(delay);
 
368
 
 
369
#ifdef VERBOSE
 
370
                iFrame++;
 
371
                if( nTime - time( NULL ) )
 
372
                {
 
373
                        printf( "%s: %d FPS\n", progclass, iFrame );
 
374
                        nTime = time( NULL );
 
375
                        iFrame = 0;
 
376
                }
 
377
#endif  /*  VERBOSE */
 
378
        }
 
379
 
 
380
        free( pImage->data );
 
381
        XDestroyImage( pImage );
 
382
        free( aiColorVals );
 
383
        free( blobs );
 
384
        for (i = 0; i < iWinHeight; ++i)
 
385
          free( blub[i] );
 
386
        free( blub );
 
387
        for (i = 0; i < dradius; ++i)
 
388
          free( blob[i] );
 
389
        free( blob );
 
390
}
 
391
 
 
392
 
 
393
/* End of Module - "metaballs.c" */
 
394