X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fmetaballs.c;h=b79dd95d94151550f4fd346a4753791a6e410008;hb=4ade52359b6eba3621566dac79793a33aa4c915f;hp=d814a80c29cd4ddabd5e44d2e90cea825ef740d3;hpb=96a411663168b0ba5432b407a83be55f3df0c802;p=xscreensaver diff --git a/hacks/metaballs.c b/hacks/metaballs.c index d814a80c..b79dd95d 100644 --- a/hacks/metaballs.c +++ b/hacks/metaballs.c @@ -17,97 +17,83 @@ #include #include "screenhack.h" -#include /*#define VERBOSE*/ -char *progclass = "Metaballs"; - -char *defaults [] = { - ".background: black", - ".foreground: white", - "*color: random", - "*count: 10", - "*cycles: 1000", - "*ncolors: 256", - "*delay: 5000", - "*radius: 100", - "*delta: 3", - 0 -}; - -XrmOptionDescRec options [] = { - { "-color", ".color", XrmoptionSepArg, 0 }, - { "-ncolors", ".ncolors", XrmoptionSepArg, 0 }, - { "-count", ".count", XrmoptionSepArg, 0 }, - { "-delay", ".delay", XrmoptionSepArg, 0 }, - { "-cycles", ".cycles", XrmoptionSepArg, 0 }, - { "-radius", ".radius", XrmoptionSepArg, 0 }, - { "-delta", ".delta", XrmoptionSepArg, 0 }, - { 0, 0, 0, 0 } -}; - -static unsigned short iWinWidth, iWinHeight; -static char *sColor; - /*blob structure*/ typedef struct { short xpos,ypos; } BLOB; -static unsigned int nBlobCount; -static unsigned char radius; -static unsigned char delta; -static unsigned char dradius; -static unsigned short sradius; -static unsigned char **blob; -static BLOB *blobs; -static unsigned char **blub; +struct state { + Display *dpy; + Window window; + + unsigned short iWinWidth, iWinHeight; + char *sColor; + + unsigned int nBlobCount; + unsigned char radius; + unsigned char delta; + unsigned char dradius; + unsigned short sradius; + unsigned char **blob; + BLOB *blobs; + unsigned char **blub; + + int delay, cycles; + signed short iColorCount; + unsigned long *aiColorVals; + XImage *pImage; + GC gc; + int draw_i; +}; + -static void init_blob(BLOB *blob) +#undef BELLRAND +#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3) + +static void init_blob(struct state *st, BLOB *blob) { - blob->xpos = (iWinWidth>> 1) - radius; - blob->ypos = (iWinHeight >> 1) - radius; + blob->xpos = st->iWinWidth/4 + BELLRAND(st->iWinWidth/2) - st->radius; + blob->ypos = st->iWinHeight/4 + BELLRAND(st->iWinHeight/2) - st->radius; } -static void Execute( Display *pDisplay, - Window MainWindow, - GC *pGC, XImage *pImage, - signed short iColorCount, unsigned long *aiColorVals ) +static void Execute( struct state *st ) { - unsigned int i, j, k; + int i, j, k; - /* clear blub array */ - for (i = 0; i < iWinHeight; ++i) - memset(blub[i], 0, iWinWidth * sizeof(unsigned char)); + /* clear st->blub array */ + for (i = 0; i < st->iWinHeight; ++i) + memset(st->blub[i], 0, st->iWinWidth * sizeof(unsigned char)); - /* move blobs */ - for (i = 0; i < nBlobCount; i++) + /* move st->blobs */ + for (i = 0; i < st->nBlobCount; i++) { - blobs[i].xpos += -delta + (int)((delta + .5f) * frand(2.0)); - blobs[i].ypos += -delta + (int)((delta + .5f) * frand(2.0)); + st->blobs[i].xpos += -st->delta + (int)((st->delta + .5f) * frand(2.0)); + st->blobs[i].ypos += -st->delta + (int)((st->delta + .5f) * frand(2.0)); } - /* draw blobs to blub array */ - for (k = 0; k < nBlobCount; ++k) + /* draw st->blobs to st->blub array */ + for (k = 0; k < st->nBlobCount; ++k) { - if (blobs[k].ypos > -dradius && blobs[k].xpos > -dradius && blobs[k].ypos < iWinHeight && blobs[k].xpos < iWinWidth) + if (st->blobs[k].ypos > -st->dradius && st->blobs[k].xpos > -st->dradius && st->blobs[k].ypos < st->iWinHeight && st->blobs[k].xpos < st->iWinWidth) { - for (i = 0; i < dradius; ++i) + for (i = 0; i < st->dradius; ++i) { - if (blobs[k].ypos + i >= 0 && blobs[k].ypos + i < iWinHeight) + if (st->blobs[k].ypos + i >= 0 && st->blobs[k].ypos + i < st->iWinHeight) { - for (j = 0; j < dradius; ++j) + for (j = 0; j < st->dradius; ++j) { - if (blobs[k].xpos + j >= 0 && blobs[k].xpos + j < iWinWidth) + if (st->blobs[k].xpos + j >= 0 && st->blobs[k].xpos + j < st->iWinWidth) { - if (blub[blobs[k].ypos + i][blobs[k].xpos + j] < iColorCount) + if (st->blub[st->blobs[k].ypos + i][st->blobs[k].xpos + j] < st->iColorCount-1) { - if (blub[blobs[k].ypos + i][blobs[k].xpos + j] + blob[i][j] > iColorCount) - blub[blobs[k].ypos + i][blobs[k].xpos + j] = iColorCount; + if (st->blub[st->blobs[k].ypos + i][st->blobs[k].xpos + j] + st->blob[i][j] > st->iColorCount-1) + st->blub[st->blobs[k].ypos + i][st->blobs[k].xpos + j] = st->iColorCount-1; else - blub[blobs[k].ypos + i][blobs[k].xpos + j] += blob[i][j]; + st->blub[st->blobs[k].ypos + i][st->blobs[k].xpos + j] += st->blob[i][j]; } } } @@ -115,59 +101,57 @@ static void Execute( Display *pDisplay, } } else - init_blob(blobs + k); + init_blob(st, st->blobs + k); } - memset( pImage->data, 0, pImage->bytes_per_line * pImage->height); + memset( st->pImage->data, 0, st->pImage->bytes_per_line * st->pImage->height); - /* draw blub array to screen */ - for (i = 0; i < iWinHeight; ++i) + /* draw st->blub array to screen */ + for (i = 0; i < st->iWinHeight; ++i) { - for (j = 0; j < iWinWidth; ++j) + for (j = 0; j < st->iWinWidth; ++j) { - if (aiColorVals[blub[i][j]] > 0) - XPutPixel( pImage, j, i, aiColorVals[blub[i][j]] ); + if (st->aiColorVals[st->blub[i][j]] > 0) + XPutPixel( st->pImage, j, i, st->aiColorVals[st->blub[i][j]] ); } } - XPutImage( pDisplay, MainWindow, *pGC, pImage, - 0, 0, 0, 0, iWinWidth, iWinHeight ); - XSync( pDisplay, False ); + XPutImage( st->dpy, st->window, st->gc, st->pImage, + 0, 0, 0, 0, st->iWinWidth, st->iWinHeight ); } -static unsigned long * SetPalette(Display *pDisplay, Window Win, char *sColor, signed short *piColorCount ) +static unsigned long * SetPalette(struct state *st ) { XWindowAttributes XWinAttribs; XColor Color, *aColors; - unsigned long *aiColorVals; signed short iColor; float nHalfColors; - XGetWindowAttributes( pDisplay, Win, &XWinAttribs ); + XGetWindowAttributes( st->dpy, st->window, &XWinAttribs ); Color.red = random() % 0xFFFF; Color.green = random() % 0xFFFF; Color.blue = random() % 0xFFFF; - if( strcasecmp( sColor, "random" ) && !XParseColor( pDisplay, XWinAttribs.colormap, sColor, &Color ) ) - fprintf( stderr, "%s: color %s not found in database. Choosing to random...\n", progname, sColor ); + if( strcasecmp( st->sColor, "random" ) && !XParseColor( st->dpy, XWinAttribs.colormap, st->sColor, &Color ) ) + fprintf( stderr, "%s: color %s not found in database. Choosing to random...\n", progname, st->sColor ); #ifdef VERBOSE - printf( "%s: Base color (RGB): <%d, %d, %d>\n", progclass, Color.red, Color.green, Color.blue ); + printf( "%s: Base color (RGB): <%d, %d, %d>\n", progname, Color.red, Color.green, Color.blue ); #endif /* VERBOSE */ - *piColorCount = get_integer_resource( "ncolors", "Integer" ); - if( *piColorCount < 2 ) *piColorCount = 2; - if( *piColorCount > 255 ) *piColorCount = 255; + st->iColorCount = get_integer_resource(st->dpy, "ncolors", "Integer" ); + if( st->iColorCount < 2 ) st->iColorCount = 2; + if( st->iColorCount > 255 ) st->iColorCount = 255; - aColors = calloc( *piColorCount, sizeof(XColor) ); - aiColorVals = calloc( *piColorCount, sizeof(unsigned long) ); + aColors = calloc( st->iColorCount, sizeof(XColor) ); + st->aiColorVals = calloc( st->iColorCount, sizeof(unsigned long) ); - for( iColor=0; iColor<*piColorCount; iColor++ ) + for( iColor=0; iColor < st->iColorCount; iColor++ ) { - nHalfColors = *piColorCount / 2.0F; + nHalfColors = st->iColorCount / 2.0F; /* Black -> Base Color */ - if( iColor < (*piColorCount/2) ) + if( iColor < (st->iColorCount/2) ) { aColors[ iColor ].red = ( Color.red / nHalfColors ) * iColor; aColors[ iColor ].green = ( Color.green / nHalfColors ) * iColor; @@ -181,52 +165,53 @@ static unsigned long * SetPalette(Display *pDisplay, Window Win, char *sColor, s aColors[ iColor ].blue = ( ( ( 0xFFFF - Color.blue ) / nHalfColors ) * ( iColor - nHalfColors ) ) + Color.blue; } - if( !XAllocColor( pDisplay, XWinAttribs.colormap, &aColors[ iColor ] ) ) + if( !XAllocColor( st->dpy, XWinAttribs.colormap, &aColors[ iColor ] ) ) { /* start all over with less colors */ - XFreeColors( pDisplay, XWinAttribs.colormap, aiColorVals, iColor, 0 ); + XFreeColors( st->dpy, XWinAttribs.colormap, st->aiColorVals, iColor, 0 ); free( aColors ); - free( aiColorVals ); - (*piColorCount)--; + free( st->aiColorVals ); + (st->iColorCount)--; - if (*piColorCount < 6) + if (st->iColorCount < 6) { fprintf (stderr, "%s: insufficient colors!\n", progname); exit (1); } - aColors = calloc( *piColorCount, sizeof(XColor) ); - aiColorVals = calloc( *piColorCount, sizeof(unsigned long) ); + aColors = calloc( st->iColorCount, sizeof(XColor) ); + st->aiColorVals = calloc( st->iColorCount, sizeof(unsigned long) ); iColor = -1; } else - aiColorVals[ iColor ] = aColors[ iColor ].pixel; + st->aiColorVals[ iColor ] = aColors[ iColor ].pixel; } free( aColors ); - XSetWindowBackground( pDisplay, Win, aiColorVals[ 0 ] ); + XSetWindowBackground( st->dpy, st->window, st->aiColorVals[ 0 ] ); - return aiColorVals; + return st->aiColorVals; } -static void Initialize( Display *pDisplay, Window Win, GC *pGC, XImage **ppImage ) +static void Initialize( struct state *st ) { XGCValues gcValues; XWindowAttributes XWinAttribs; - int iBitsPerPixel, i, j; + int /*iBitsPerPixel,*/ i, j; unsigned int distance_squared; float fraction; /* Create the Image for drawing */ - XGetWindowAttributes( pDisplay, Win, &XWinAttribs ); + XGetWindowAttributes( st->dpy, st->window, &XWinAttribs ); /* Find the preferred bits-per-pixel. (jwz) */ +#if 0 { int pfvc = 0; - XPixmapFormatValues *pfv = XListPixmapFormats( pDisplay, &pfvc ); + XPixmapFormatValues *pfv = XListPixmapFormats( st->dpy, &pfvc ); for( i=0; igc = XCreateGC( st->dpy, st->window, 0, &gcValues ); - *ppImage = XCreateImage( pDisplay, XWinAttribs.visual, XWinAttribs.depth, ZPixmap, 0, NULL, - XWinAttribs.width, XWinAttribs.height, BitmapPad( pDisplay ), 0 ); - (*ppImage)->data = calloc((*ppImage)->bytes_per_line, (*ppImage)->height); + st->pImage = XCreateImage( st->dpy, XWinAttribs.visual, XWinAttribs.depth, ZPixmap, 0, NULL, + XWinAttribs.width, XWinAttribs.height, BitmapPad( st->dpy ), 0 ); + (st->pImage)->data = calloc((st->pImage)->bytes_per_line, (st->pImage)->height); - iWinWidth = XWinAttribs.width; - iWinHeight = XWinAttribs.height; + st->iWinWidth = XWinAttribs.width; + st->iWinHeight = XWinAttribs.height; /* Get the base color. */ - sColor = get_string_resource( "color", "Color" ); - - /* Get the delta. */ - delta = get_integer_resource( "delta", "Integer" ); - if (delta < 1) - delta = 1; - else if (delta > 20) - delta = 20; + st->sColor = get_string_resource(st->dpy, "color", "Color" ); + + /* Get the st->delta. */ + st->delta = get_integer_resource(st->dpy, "delta", "Integer" ); + if (st->delta < 1) + st->delta = 1; + else if (st->delta > 20) + st->delta = 20; - /* Get the radius. */ - radius = get_integer_resource( "radius", "Integer" ); - if (radius < 2) - radius = 2; - if (radius > 100) - radius = 100; + /* Get the st->radius. */ + st->radius = get_integer_resource(st->dpy, "radius", "Integer" ); + if (st->radius < 2) + st->radius = 2; + if (st->radius > 100) + st->radius = 100; - radius = (radius / 100.0) * (iWinHeight >> 3); - if (radius >= 128) /* should use UCHAR_MAX? */ - radius = 127; /* dradius should fit in u_char */ + st->radius = (st->radius / 100.0) * (st->iWinHeight >> 3); + if (st->radius >= 128) /* should use UCHAR_MAX? */ + st->radius = 127; /* st->dradius should fit in u_char */ - dradius = radius * 2; - sradius = radius * radius; + st->dradius = st->radius * 2; + st->sradius = st->radius * st->radius; - /* create blob */ - blob = malloc ( dradius * sizeof(unsigned char*)); - for (i = 0; i < dradius; ++i) - blob[i] = malloc( dradius * sizeof(unsigned char)); + /* create st->blob */ + st->blob = malloc ( st->dradius * sizeof(unsigned char*)); + for (i = 0; i < st->dradius; ++i) + st->blob[i] = malloc( st->dradius * sizeof(unsigned char)); - /* create blub array */ - blub = malloc( iWinHeight * sizeof(unsigned char*)); - for (i = 0; i < iWinHeight; ++i) - blub[i] = malloc( iWinWidth * sizeof(unsigned char)); + /* create st->blub array */ + st->blub = malloc( st->iWinHeight * sizeof(unsigned char*)); + for (i = 0; i < st->iWinHeight; ++i) + st->blub[i] = malloc( st->iWinWidth * sizeof(unsigned char)); - /* create blob */ - for (i = -radius; i < radius; ++i) + /* create st->blob */ + for (i = -st->radius; i < st->radius; ++i) { - for (j = -radius; j < radius; ++j) + for (j = -st->radius; j < st->radius; ++j) { distance_squared = i * i + j * j; - if (distance_squared <= sradius) + if (distance_squared <= st->sradius) { /* compute density */ - fraction = (float)distance_squared / (float)sradius; - blob[i + radius][j + radius] = pow((1.0 - (fraction * fraction)),4.0) * 255.0; + fraction = (float)distance_squared / (float)st->sradius; + st->blob[i + st->radius][j + st->radius] = pow((1.0 - (fraction * fraction)),4.0) * 255.0; } else { - blob[i + radius][j + radius] = 0; + st->blob[i + st->radius][j + st->radius] = 0; } } } - for (i = 0; i < nBlobCount; i++) + for (i = 0; i < st->nBlobCount; i++) { - init_blob(blobs + i); + init_blob(st, st->blobs + i); } } -void screenhack(Display *pDisplay, Window Win ) +static void * +metaballs_init (Display *dpy, Window window) { - GC gc; - signed short iColorCount = 0; - unsigned long *aiColorVals = NULL; - XImage *pImage = NULL; + struct state *st = (struct state *) calloc (1, sizeof(*st)); #ifdef VERBOSE - time_t nTime = time( NULL ); - unsigned short iFrame = 0; + time_t nTime = time( NULL ); + unsigned short iFrame = 0; #endif /* VERBOSE */ - int delay, cycles, i; - nBlobCount = get_integer_resource( "count", "Integer" ); - if( nBlobCount > 255 ) nBlobCount = 255; - if( nBlobCount < 2 ) nBlobCount = 2; + st->dpy = dpy; + st->window = window; - if( ( blobs = calloc( nBlobCount, sizeof(BLOB) ) ) == NULL ) - { - fprintf( stderr, "%s: Could not allocate %d Blobs\n", progclass, nBlobCount ); - return; - } + st->nBlobCount = get_integer_resource(st->dpy, "count", "Integer" ); + if( st->nBlobCount > 255 ) st->nBlobCount = 255; + if( st->nBlobCount < 2 ) st->nBlobCount = 2; + + if( ( st->blobs = calloc( st->nBlobCount, sizeof(BLOB) ) ) == NULL ) + { + fprintf( stderr, "%s: Could not allocate %d Blobs\n", progname, st->nBlobCount ); + abort(); + } #ifdef VERBOSE - printf( "%s: Allocated %d Blobs\n", progclass, nBlobCount ); + printf( "%s: Allocated %d Blobs\n", progname, st->nBlobCount ); #endif /* VERBOSE */ - Initialize( pDisplay, Win, &gc, &pImage ); + Initialize( st ); - delay = get_integer_resource( "delay", "Integer" ); - cycles = get_integer_resource( "cycles", "Integer" ); - i = cycles; + st->delay = get_integer_resource(st->dpy, "delay", "Integer" ); + st->cycles = get_integer_resource(st->dpy, "cycles", "Integer" ); - while( 1 ) - { - screenhack_handle_events( pDisplay ); + st->draw_i = -1; + return st; +} - if( i++ >= cycles ) - { - XWindowAttributes XWinAttribs; - XGetWindowAttributes( pDisplay, Win, &XWinAttribs ); - - memset( pImage->data, 0, pImage->bytes_per_line * pImage->height ); - XFreeColors( pDisplay, XWinAttribs.colormap, aiColorVals, iColorCount, 0 ); - free( aiColorVals ); - aiColorVals = SetPalette( pDisplay, Win, sColor, &iColorCount ); - XClearWindow( pDisplay, Win ); - for (i = 0; i < nBlobCount; i++) - { - init_blob(blobs + i); - } - i = 0; - } - Execute( pDisplay, Win, &gc, pImage, iColorCount - 1, aiColorVals ); - if( delay && !(i % 4) ) - usleep(delay); +static unsigned long +metaballs_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + + if( st->draw_i < 0 || st->draw_i++ >= st->cycles ) + { + int i; + XWindowAttributes XWinAttribs; + XGetWindowAttributes( st->dpy, st->window, &XWinAttribs ); + + memset( st->pImage->data, 0, st->pImage->bytes_per_line * st->pImage->height ); + XFreeColors( st->dpy, XWinAttribs.colormap, st->aiColorVals, st->iColorCount, 0 ); + free( st->aiColorVals ); + st->aiColorVals = SetPalette( st ); + XClearWindow( st->dpy, st->window ); + for (i = 0; i < st->nBlobCount; i++) + { + init_blob(st, st->blobs + i); + } + st->draw_i = 0; + } + + Execute( st ); #ifdef VERBOSE - iFrame++; - if( nTime - time( NULL ) ) - { - printf( "%s: %d FPS\n", progclass, iFrame ); - nTime = time( NULL ); - iFrame = 0; - } + iFrame++; + if( nTime - time( NULL ) ) + { + printf( "%s: %d FPS\n", progname, iFrame ); + nTime = time( NULL ); + iFrame = 0; + } #endif /* VERBOSE */ - } - free( pImage->data ); - XDestroyImage( pImage ); - free( aiColorVals ); - free( blobs ); - for (i = 0; i < iWinHeight; ++i) - free( blub[i] ); - free( blub ); - for (i = 0; i < dradius; ++i) - free( blob[i] ); - free( blob ); + return st->delay; +} + + +static void +metaballs_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +metaballs_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; } +static void +metaballs_free (Display *dpy, Window window, void *closure) +{ +#if 0 + struct state *st = (struct state *) closure; + free( st->pImage->data ); + XDestroyImage( st->pImage ); + free( st->aiColorVals ); + free( st->blobs ); + for (i = 0; i < st->iWinHeight; ++i) + free( st->blub[i] ); + free( st->blub ); + for (i = 0; i < st->dradius; ++i) + free( st->blob[i] ); + free( st->blob ); +#endif +} + + +static const char *metaballs_defaults [] = { + ".background: black", + ".foreground: white", + "*color: random", + "*count: 10", + "*cycles: 1000", + "*ncolors: 256", + "*delay: 10000", + "*radius: 100", + "*delta: 3", +#ifdef USE_IPHONE + "*ignoreRotation: True", +#endif + 0 +}; + +static XrmOptionDescRec metaballs_options [] = { + { "-color", ".color", XrmoptionSepArg, 0 }, + { "-ncolors", ".ncolors", XrmoptionSepArg, 0 }, + { "-count", ".count", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-cycles", ".cycles", XrmoptionSepArg, 0 }, + { "-radius", ".radius", XrmoptionSepArg, 0 }, + { "-delta", ".delta", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("MetaBalls", metaballs) /* End of Module - "metaballs.c" */