X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fshadebobs.c;h=39040ea377c66067619ea4bdc19932c23226d90a;hb=f0261d8acab611f3433160e4f07367b870439739;hp=34965dfc465303ffdec3764ef6c43d7d3d6b332e;hpb=af290bcdf2d1c61efc8aaaff653745c900cbe98c;p=xscreensaver diff --git a/hacks/shadebobs.c b/hacks/shadebobs.c index 34965dfc..39040ea3 100644 --- a/hacks/shadebobs.c +++ b/hacks/shadebobs.c @@ -28,355 +28,436 @@ * on cycle, and the extents of the sinus pattern change in * real-time. * [06/22/99] - Shane Smit: Fixed delay to be fast and use little CPU :). + * [09/17/99] - Shane Smit: Made all calculations based on the size of the + * window. Thus, it'll look the same at 100x100 as it does at + * 1600x1200 ( Only smaller :). + * [04/24/00] - Shane Smit: Revamped entire source code: + * Shade Bob movement is calculated very differently. + * Base color can be any color now. */ + #include #include "screenhack.h" -#include /* #define VERBOSE */ -char *progclass = "ShadeBobs"; - -char *defaults [] = { - "*degrees: 512", +static const char *shadebobs_defaults [] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*degrees: 0", /* default: Automatic degree calculation */ "*color: random", - "*count: 2", - "*cycles: 50", + "*count: 4", + "*cycles: 10", "*ncolors: 64", /* changing this doesn't work particularly well */ - "*delay: 5000", + "*delay: 10000", 0 }; -XrmOptionDescRec options [] = { +static XrmOptionDescRec shadebobs_options [] = { { "-degrees", ".degrees", XrmoptionSepArg, 0 }, { "-color", ".color", XrmoptionSepArg, 0 }, + { "-ncolors", ".ncolors", XrmoptionSepArg, 0 }, { "-count", ".count", XrmoptionSepArg, 0 }, { "-delay", ".delay", XrmoptionSepArg, 0 }, { "-cycles", ".cycles", XrmoptionSepArg, 0 }, { 0, 0, 0, 0 } }; -static unsigned short nDegreeCount; -static double *anSinTable; -static unsigned short nMaxExtentX, nMaxExtentY; -static unsigned short nMinExtentX, nMinExtentY; -static unsigned short nHalfWidth, nHalfHeight; -static char *sColor; - -#define RANDOM() ((int) (random() & 0X7FFFFFFFL)) - - /* Ahem. Chocolate is a flavor; not a food. Thank you */ -#define MAPSIZE 32 - typedef struct { - char anDeltaMap[ MAPSIZE * MAPSIZE ]; /* 32 x 32 Delta Map */ - double nVelocityX, nVelocityY; - double nAngleX, nAngleY; - short nExtentX, nExtentY; + signed char *anDeltaMap; + double nAngle, nAngleDelta, nAngleInc; + double nPosX, nPosY; } SShadeBob; +struct state { + Display *dpy; + Window window; + unsigned short iDegreeCount; + double *anSinTable, *anCosTable; + unsigned short iWinWidth, iWinHeight; + unsigned short iWinCenterX, iWinCenterY; + char *sColor; + unsigned char iBobRadius, iBobDiameter; + unsigned char iVelocity; + + unsigned long *aiColorVals; + signed short iColorCount; + int cycles; + XImage *pImage; + unsigned char nShadeBobCount, iShadeBob; + SShadeBob *aShadeBobs; + GC gc; + int delay; + int draw_i; +}; -static void ResetShadeBob( SShadeBob *pShadeBob ) -{ - pShadeBob->nAngleX = RANDOM() % nDegreeCount; - pShadeBob->nAngleY = RANDOM() % nDegreeCount; +#define RANDOM() ((int) (random() & 0X7FFFFFFFL)) - pShadeBob->nExtentX = (RANDOM() % (nMaxExtentX - nMinExtentX)) + nMinExtentX; - pShadeBob->nExtentY = (RANDOM() % (nMaxExtentY - nMinExtentY)) + nMinExtentY; -} -static void InitShadeBob( SShadeBob *pShadeBob, Bool bDark ) +static void ResetShadeBob( struct state *st, SShadeBob *pShadeBob ) { - double nDelta; - char iWidth, iHeight; + pShadeBob->nPosX = RANDOM() % st->iWinWidth; + pShadeBob->nPosY = RANDOM() % st->iWinHeight; + pShadeBob->nAngle = RANDOM() % st->iDegreeCount; + pShadeBob->nAngleDelta = ( RANDOM() % st->iDegreeCount ) - ( st->iDegreeCount / 2.0F ); + pShadeBob->nAngleInc = pShadeBob->nAngleDelta / 50.0F; + if( pShadeBob->nAngleInc == 0.0F ) + pShadeBob->nAngleInc = ( pShadeBob->nAngleDelta > 0.0F ) ? 0.0001F : -0.0001F; +} - for( iHeight=-16; iHeight<16; iHeight++ ) - for( iWidth=-16; iWidth<16; iWidth++ ) - { - nDelta = 9 - (sqrt( pow( iWidth+0.5, 2 ) + pow( iHeight+0.5, 2 ) ) / 2 ); - if( nDelta < 0 ) nDelta = 0; - if( bDark ) nDelta = -nDelta; - pShadeBob->anDeltaMap[ (iWidth+(MAPSIZE/2))*MAPSIZE - + iHeight+(MAPSIZE/2) ] = (char)nDelta; - } - ResetShadeBob( pShadeBob ); +static void InitShadeBob( struct state *st, SShadeBob *pShadeBob, Bool bDark ) +{ + double nDelta; + int iWidth, iHeight; + + if( ( pShadeBob->anDeltaMap = calloc( st->iBobDiameter * st->iBobDiameter, sizeof(char) ) ) == NULL ) + { + fprintf( stderr, "%s: Could not allocate Delta Map!\n", progname ); + return; + } + + for( iHeight=-st->iBobRadius; iHeightiBobRadius; iHeight++ ) + for( iWidth=-st->iBobRadius; iWidthiBobRadius; iWidth++ ) + { + nDelta = 9 - ( ( sqrt( pow( iWidth+0.5, 2 ) + pow( iHeight+0.5, 2 ) ) / st->iBobRadius ) * 8 ); + if( nDelta < 0 ) nDelta = 0; + if( bDark ) nDelta = -nDelta; + pShadeBob->anDeltaMap[ ( iWidth + st->iBobRadius ) * st->iBobDiameter + iHeight + st->iBobRadius ] = (char)nDelta; + } + + ResetShadeBob( st, pShadeBob ); } -static void Execute( SShadeBob *pShadeBob, Display *pDisplay, - Window MainWindow, - GC *pGC, XImage *pXImage, - int ncolors, XColor *aXColors ) +/* A delta is calculated, and the shadebob turns at an increment. When the delta + * falls to 0, a new delta and increment are calculated. */ +static void MoveShadeBob( struct state *st, SShadeBob *pShadeBob ) { - long nColor; - short nIndex; - unsigned int nXPos, nYPos; - unsigned int iWidth, iHeight; - - pShadeBob->nVelocityX += ( ( RANDOM() % 200 ) - 100 ) / 1000.0F; - pShadeBob->nVelocityY += ( ( RANDOM() % 200 ) - 100 ) / 1000.0F; - - if( pShadeBob->nVelocityX > 4 ) pShadeBob->nVelocityX = 4; - else if( pShadeBob->nVelocityX < 3 ) pShadeBob->nVelocityX = 3; - if( pShadeBob->nVelocityY > 4 ) pShadeBob->nVelocityY = 4; - else if( pShadeBob->nVelocityY < 3 ) pShadeBob->nVelocityY = 3; - - pShadeBob->nAngleX += pShadeBob->nVelocityX; - pShadeBob->nAngleY += pShadeBob->nVelocityY; - - if( pShadeBob->nAngleX >= nDegreeCount ) pShadeBob->nAngleX -= nDegreeCount; - else if( pShadeBob->nAngleX < 0 ) pShadeBob->nAngleX += nDegreeCount; - if( pShadeBob->nAngleY >= nDegreeCount ) pShadeBob->nAngleY -= nDegreeCount; - else if( pShadeBob->nAngleY < 0 ) pShadeBob->nAngleY += nDegreeCount; - - pShadeBob->nExtentX += ( RANDOM() % 5 ) - 2; - if( pShadeBob->nExtentX > nMaxExtentX ) pShadeBob->nExtentX = nMaxExtentX; - if( pShadeBob->nExtentX < nMinExtentX ) pShadeBob->nExtentX = nMinExtentX; - pShadeBob->nExtentY += ( RANDOM() % 5 ) - 2; - if( pShadeBob->nExtentY > nMaxExtentY ) pShadeBob->nExtentY = nMaxExtentY; - if( pShadeBob->nExtentY < nMinExtentY ) pShadeBob->nExtentY = nMinExtentY; - - /* Trig is your friend :) */ - nXPos = (unsigned int)(( anSinTable[ (int)pShadeBob->nAngleX ] * pShadeBob->nExtentX ) - + nHalfWidth); - nYPos = (unsigned int)(( anSinTable[ (int)pShadeBob->nAngleY ] * pShadeBob->nExtentY ) - + nHalfHeight); - - for( iHeight=0; iHeight < MAPSIZE; iHeight++ ) - { - for( iWidth=0; iWidth < MAPSIZE; iWidth++ ) - { - nColor = XGetPixel( pXImage, nXPos + iWidth, nYPos + iHeight ); - - /* FIXME: Here is a loop I'd love to take out. */ - for( nIndex=0; nIndex < ncolors; nIndex++ ) - if( aXColors[ nIndex ].pixel == nColor ) - break; + pShadeBob->nAngle += pShadeBob->nAngleInc; + pShadeBob->nAngleDelta -= pShadeBob->nAngleInc; + + if( pShadeBob->nAngle >= st->iDegreeCount ) pShadeBob->nAngle -= st->iDegreeCount; + else if( pShadeBob->nAngle < 0 ) pShadeBob->nAngle += st->iDegreeCount; + + if( ( pShadeBob->nAngleInc>0.0F && pShadeBob->nAngleDeltanAngleInc ) || + ( pShadeBob->nAngleInc<=0.0F && pShadeBob->nAngleDelta>pShadeBob->nAngleInc ) ) + { + pShadeBob->nAngleDelta = ( RANDOM() % st->iDegreeCount ) - ( st->iDegreeCount / 2.0F ); + pShadeBob->nAngleInc = pShadeBob->nAngleDelta / 50.0F; + if( pShadeBob->nAngleInc == 0.0F ) + pShadeBob->nAngleInc = ( pShadeBob->nAngleDelta > 0.0F ) ? 0.0001F : -0.0001F; + } + + pShadeBob->nPosX = ( st->anSinTable[ (int)pShadeBob->nAngle ] * st->iVelocity ) + pShadeBob->nPosX; + pShadeBob->nPosY = ( st->anCosTable[ (int)pShadeBob->nAngle ] * st->iVelocity ) + pShadeBob->nPosY; + + /* This wraps it around the screen. */ + if( pShadeBob->nPosX >= st->iWinWidth ) pShadeBob->nPosX -= st->iWinWidth; + else if( pShadeBob->nPosX < 0 ) pShadeBob->nPosX += st->iWinWidth; + + if( pShadeBob->nPosY >= st->iWinHeight ) pShadeBob->nPosY -= st->iWinHeight; + else if( pShadeBob->nPosY < 0 ) pShadeBob->nPosY += st->iWinHeight; +} - nIndex += pShadeBob->anDeltaMap[ iWidth * MAPSIZE + iHeight ]; - if( nIndex >= ncolors ) nIndex = ncolors-1; - if( nIndex < 0 ) nIndex = 0; - XPutPixel( pXImage, nXPos + iWidth, nYPos + iHeight, - aXColors[ nIndex ].pixel ); - } - } - /* Place graphics in window */ - XPutImage( pDisplay, MainWindow, *pGC, pXImage, - nXPos, nYPos, nXPos, nYPos, MAPSIZE, MAPSIZE ); - XSync (pDisplay, False); +static void Execute( struct state *st, SShadeBob *pShadeBob ) +{ + unsigned long iColor; + short iColorVal; + int iPixelX, iPixelY; + unsigned int iWidth, iHeight; + + MoveShadeBob( st, pShadeBob ); + + for( iHeight=0; iHeightiBobDiameter; iHeight++ ) + { + iPixelY = pShadeBob->nPosY + iHeight; + if( iPixelY >= st->iWinHeight ) iPixelY -= st->iWinHeight; + + for( iWidth=0; iWidthiBobDiameter; iWidth++ ) + { + iPixelX = pShadeBob->nPosX + iWidth; + if( iPixelX >= st->iWinWidth ) iPixelX -= st->iWinWidth; + + iColor = XGetPixel( st->pImage, iPixelX, iPixelY ); + + /* FIXME: Here is a loop I'd love to take out. */ + for( iColorVal=0; iColorValiColorCount; iColorVal++ ) + if( st->aiColorVals[ iColorVal ] == iColor ) + break; + + iColorVal += pShadeBob->anDeltaMap[ iWidth * st->iBobDiameter + iHeight ]; + if( iColorVal >= st->iColorCount ) iColorVal = st->iColorCount - 1; + if( iColorVal < 0 ) iColorVal = 0; + + XPutPixel( st->pImage, iPixelX, iPixelY, st->aiColorVals[ iColorVal ] ); + } + } + + /* FIXME: if it's next to the top or left sides of screen this will break. However, it's not noticable. */ + XPutImage( st->dpy, st->window, st->gc, st->pImage, + pShadeBob->nPosX, pShadeBob->nPosY, pShadeBob->nPosX, pShadeBob->nPosY, st->iBobDiameter, st->iBobDiameter ); } -static void CreateTables( unsigned int nDegrees ) +static void CreateTables( struct state *st, unsigned int nDegrees ) { - double nRadian; - unsigned int iDegree; - anSinTable = calloc( nDegrees, sizeof(double) ); - - for( iDegree=0; iDegreeanSinTable = calloc( nDegrees, sizeof(double) ); + st->anCosTable = calloc( nDegrees, sizeof(double) ); + + for( iDegree=0; iDegreeanSinTable[ iDegree ] = sin( nRadian ); + st->anCosTable[ iDegree ] = cos( nRadian ); + } } -static void SetPalette(Display *pDisplay, Window Win, char *sColor, - int *ncolorsP, XColor *aXColors ) +static unsigned long * SetPalette(struct state *st ) { - XWindowAttributes XWinAttrib; - Colormap CMap; - XColor Color; - int nHue; - double nSat, nVal; - - XGetWindowAttributes( pDisplay, Win, &XWinAttrib ); - CMap = XWinAttrib.colormap; - - Color.red = ( RANDOM() % 3 ) * 0x7FFF; /* Either full, half or none. */ - Color.green = ( RANDOM() % 3 ) * 0x7FFF; - Color.blue = ( RANDOM() % 3 ) * 0x7FFF; - - /* If Color is black, grey, or white, then make SURE its a color */ - if( Color.red == Color.green && Color.green == Color.blue ) - { Color.red = 0xFFFF; - Color.green = ( RANDOM() % 3 ) * 0x7FFF; - Color.blue = 0; } - - if( strcasecmp( sColor, "random" ) && - !XParseColor( pDisplay, CMap, sColor, &Color ) ) - fprintf( stderr, - "%s: color %s not found in database. Choosing to random...\n", - progname, sColor ); - - rgb_to_hsv( Color.red, Color.green, Color.blue, &nHue, &nSat, &nVal ); + XWindowAttributes XWinAttribs; + XColor Color, *aColors; + signed short iColor; + float nHalfColors; + + XGetWindowAttributes( st->dpy, st->window, &XWinAttribs ); + + Color.red = RANDOM() % 0xFFFF; + Color.green = RANDOM() % 0xFFFF; + Color.blue = RANDOM() % 0xFFFF; + + 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( "RGB (%d, %d, %d) = HSV (%d, %g, %g)\n", - Color.red, Color.green, Color.blue, nHue, nSat, nVal ); + printf( "%s: Base color (RGB): <%d, %d, %d>\n", progname, Color.red, Color.green, Color.blue ); #endif /* VERBOSE */ - if (*ncolorsP != 0) - free_colors (pDisplay, CMap, aXColors, *ncolorsP); - - *ncolorsP = get_integer_resource ("ncolors", "Integer"); - if (*ncolorsP <= 0) *ncolorsP = 64; - - /* allocate two color ramps, black -> color -> white. */ - { - int n1, n2; - n1 = *ncolorsP / 2; - make_color_ramp( pDisplay, CMap, 0, 0, 0, nHue, nSat, nVal, - aXColors, &n1, - False, True, False ); - n2 = *ncolorsP - n1; - make_color_ramp( pDisplay, CMap, nHue, nSat, nVal, 0, 0, 1, - aXColors + n1, &n2, - False, True, False ); - *ncolorsP = n1 + n2; - } + 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( st->iColorCount, sizeof(XColor) ); + st->aiColorVals = calloc( st->iColorCount, sizeof(unsigned long) ); + + for( iColor=0; iColoriColorCount; iColor++ ) + { + nHalfColors = st->iColorCount / 2.0F; + /* Black -> Base Color */ + if( iColor < (st->iColorCount/2) ) + { + aColors[ iColor ].red = ( Color.red / nHalfColors ) * iColor; + aColors[ iColor ].green = ( Color.green / nHalfColors ) * iColor; + aColors[ iColor ].blue = ( Color.blue / nHalfColors ) * iColor; + } + /* Base Color -> White */ + else + { + aColors[ iColor ].red = ( ( ( 0xFFFF - Color.red ) / nHalfColors ) * ( iColor - nHalfColors ) ) + Color.red; + aColors[ iColor ].green = ( ( ( 0xFFFF - Color.green ) / nHalfColors ) * ( iColor - nHalfColors ) ) + Color.green; + aColors[ iColor ].blue = ( ( ( 0xFFFF - Color.blue ) / nHalfColors ) * ( iColor - nHalfColors ) ) + Color.blue; + } + + if( !XAllocColor( st->dpy, XWinAttribs.colormap, &aColors[ iColor ] ) ) + { + /* start all over with less colors */ + XFreeColors( st->dpy, XWinAttribs.colormap, st->aiColorVals, iColor, 0 ); + free( aColors ); + free( st->aiColorVals ); + st->iColorCount--; + aColors = calloc( st->iColorCount, sizeof(XColor) ); + st->aiColorVals = calloc( st->iColorCount, sizeof(unsigned long) ); + iColor = -1; + } + else + st->aiColorVals[ iColor ] = aColors[ iColor ].pixel; + } + + free( aColors ); + + XSetWindowBackground( st->dpy, st->window, st->aiColorVals[ 0 ] ); + + return st->aiColorVals; } -static void Initialize( Display *pDisplay, Window Win, - GC *pGC, XImage **pXImage, - int *ncolorsP, XColor *aXColors ) +static void Initialize( struct state *st ) { - XGCValues gcValues; - XWindowAttributes XWinAttribs; - int bpp; - - /* Create the Image for drawing */ - XGetWindowAttributes( pDisplay, Win, &XWinAttribs ); - - /* Find the preferred bits-per-pixel. */ - { - int i, pfvc = 0; - XPixmapFormatValues *pfv = XListPixmapFormats (pDisplay, &pfvc); - for (i = 0; i < pfvc; i++) - if (pfv[i].depth == XWinAttribs.depth) - { - bpp = pfv[i].bits_per_pixel; - break; - } - if (pfv) - XFree (pfv); - } - - /* Create the GC. */ - *pGC = XCreateGC( pDisplay, Win, 0, &gcValues ); - - *pXImage = XCreateImage(pDisplay, XWinAttribs.visual, - XWinAttribs.depth, - ZPixmap, 0, NULL, - XWinAttribs.width, XWinAttribs.height, - BitmapPad(pDisplay), 0); - (*pXImage)->data = calloc((*pXImage)->bytes_per_line, - (*pXImage)->height); - - /* These are precalculations used in Execute(). */ - nMaxExtentX = ( XWinAttribs.width / 2 ) - 20; - nMaxExtentY = ( XWinAttribs.height / 2 ) - 20; - nMinExtentX = nMaxExtentX / 3; - nMinExtentY = nMaxExtentY / 3; - nHalfWidth = ( XWinAttribs.width / 2 ) - 16; - nHalfHeight = ( XWinAttribs.height / 2 ) - 16; - - /* Create the Sin and Cosine lookup tables. */ - nDegreeCount = get_integer_resource( "degrees", "Integer" ); - if( nDegreeCount < 90 ) nDegreeCount = 90; - if( nDegreeCount > 5400 ) nDegreeCount = 5400; - CreateTables( nDegreeCount ); - - /* Get the colors. */ - sColor = get_string_resource( "color", "Color" ); - if( sColor == NULL) - SetPalette( pDisplay, Win, "random", ncolorsP, aXColors ); - else - SetPalette( pDisplay, Win, sColor, ncolorsP, aXColors ); + XGCValues gcValues; + XWindowAttributes XWinAttribs; + int iBitsPerPixel; + + /* Create the Image for drawing */ + XGetWindowAttributes( st->dpy, st->window, &XWinAttribs ); + + /* Find the preferred bits-per-pixel. (jwz) */ + { + int i, pfvc = 0; + XPixmapFormatValues *pfv = XListPixmapFormats( st->dpy, &pfvc ); + for( i=0; igc = XCreateGC( st->dpy, st->window, 0, &gcValues ); + + st->pImage = XCreateImage( st->dpy, XWinAttribs.visual, XWinAttribs.depth, ZPixmap, 0, NULL, + XWinAttribs.width, XWinAttribs.height, 8 /*BitmapPad( st->dpy )*/, 0 ); + st->pImage->data = calloc((st->pImage)->bytes_per_line, (st->pImage)->height); + + st->iWinWidth = XWinAttribs.width; + st->iWinHeight = XWinAttribs.height; + + /* These are precalculations used in Execute(). */ + st->iBobDiameter = ( ( st->iWinWidth < st->iWinHeight ) ? st->iWinWidth : st->iWinHeight ) / 25; + st->iBobRadius = st->iBobDiameter / 2; +#ifdef VERBOSE + printf( "%s: Bob Diameter = %d\n", progname, st->iBobDiameter ); +#endif + + st->iWinCenterX = ( XWinAttribs.width / 2 ) - st->iBobRadius; + st->iWinCenterY = ( XWinAttribs.height / 2 ) - st->iBobRadius; + + st->iVelocity = ( ( st->iWinWidth < st->iWinHeight ) ? st->iWinWidth : st->iWinHeight ) / 150; + + /* Create the Sin and Cosine lookup tables. */ + st->iDegreeCount = get_integer_resource(st->dpy, "degrees", "Integer" ); + if( st->iDegreeCount == 0 ) st->iDegreeCount = ( XWinAttribs.width / 6 ) + 400; + else if( st->iDegreeCount < 90 ) st->iDegreeCount = 90; + else if( st->iDegreeCount > 5400 ) st->iDegreeCount = 5400; + CreateTables( st, st->iDegreeCount ); +#ifdef VERBOSE + printf( "%s: Using a %d degree circle.\n", progname, st->iDegreeCount ); +#endif /* VERBOSE */ + + /* Get the base color. */ + st->sColor = get_string_resource(st->dpy, "color", "Color" ); } -void screenhack(Display *pDisplay, Window Win ) +static void * +shadebobs_init (Display *dpy, Window window) { - GC gc; - int ncolors = 0; - XColor aXColors[ 256 ]; - XImage *pImage; - unsigned char nShadeBobCount, iShadeBob; - SShadeBob *aShadeBobs; + 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; - nShadeBobCount = get_integer_resource( "count", "Integer" ); - if( nShadeBobCount > 64 ) nShadeBobCount = 64; - if( nShadeBobCount < 1 ) nShadeBobCount = 1; + st->dpy = dpy; + st->window = window; - if( ( aShadeBobs = calloc( nShadeBobCount, sizeof(SShadeBob) ) ) == NULL ) - { - fprintf( stderr, "Could not allocate %d ShadeBobs\n", nShadeBobCount ); - return; - } + st->nShadeBobCount = get_integer_resource(st->dpy, "count", "Integer" ); + if( st->nShadeBobCount > 64 ) st->nShadeBobCount = 64; + if( st->nShadeBobCount < 1 ) st->nShadeBobCount = 1; + + if( ( st->aShadeBobs = calloc( st->nShadeBobCount, sizeof(SShadeBob) ) ) == NULL ) + { + fprintf( stderr, "%s: Could not allocate %d ShadeBobs\n", progname, st->nShadeBobCount ); + abort(); + } #ifdef VERBOSE - printf( "Allocated %d ShadeBobs\n", nShadeBobCount ); + printf( "%s: Allocated %d ShadeBobs\n", progname, st->nShadeBobCount ); #endif /* VERBOSE */ - Initialize( pDisplay, Win, &gc, &pImage, &ncolors, aXColors ); + Initialize( st ); + + for( st->iShadeBob=0; st->iShadeBobnShadeBobCount; st->iShadeBob++ ) + InitShadeBob( st, &st->aShadeBobs[ st->iShadeBob ], st->iShadeBob % 2 ); - for( iShadeBob=0; iShadeBobdelay = get_integer_resource(st->dpy, "delay", "Integer" ); + st->cycles = get_integer_resource(st->dpy, "cycles", "Integer" ) * st->iDegreeCount; - delay = get_integer_resource( "delay", "Integer" ); - cycles = get_integer_resource( "cycles", "Integer" ) * (nDegreeCount / 3); - i = cycles; + st->draw_i = 99999999; + return st; +} - while (1) - { - screenhack_handle_events( pDisplay ); +static unsigned long +shadebobs_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; - if (i++ >= cycles) + if( st->draw_i++ >= st->cycles ) { - i = 0; - XClearWindow (pDisplay, Win); - memset (pImage->data, 0, pImage->bytes_per_line * pImage->height); - for( iShadeBob=0; iShadeBobdpy, st->window, &XWinAttribs ); + + st->draw_i = 0; +#if 0 + memset( st->pImage->data, 0, st->pImage->bytes_per_line * st->pImage->height ); +#else + { + /* fill the image with the actual value of the black pixel, not 0. */ + unsigned long black = BlackPixelOfScreen (XWinAttribs.screen); + int x, y; + for (y = 0; y < XWinAttribs.height; y++) + for (x = 0; x < XWinAttribs.width; x++) + XPutPixel (st->pImage, x, y, black); + } +#endif + + for( st->iShadeBob=0; st->iShadeBobnShadeBobCount; st->iShadeBob++ ) + ResetShadeBob( st, &st->aShadeBobs[ st->iShadeBob ] ); + XFreeColors( st->dpy, XWinAttribs.colormap, st->aiColorVals, st->iColorCount, 0 ); + free( st->aiColorVals ); + st->aiColorVals = SetPalette( st ); + XClearWindow( st->dpy, st->window ); } - for( iShadeBob=0; iShadeBobiShadeBob=0; st->iShadeBobnShadeBobCount; st->iShadeBob++ ) + Execute( st, &st->aShadeBobs[ st->iShadeBob ] ); - if( delay && !(i % 4) ) - usleep(delay); + return st->delay; +} -#ifdef VERBOSE - iFrame++; - if( nTime - time( NULL ) ) - { - printf( "FPS: %d\n", iFrame ); - nTime = time( NULL ); - iFrame = 0; - } -#endif /* VERBOSE */ - } +static void +shadebobs_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +shadebobs_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} - free( anSinTable ); - free( pImage->data ); - XDestroyImage( pImage ); - free( aShadeBobs ); +static void +shadebobs_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free( st->anSinTable ); + free( st->anCosTable ); + /* free( st->pImage->data ); */ + XDestroyImage( st->pImage ); + for( st->iShadeBob=0; st->iShadeBobnShadeBobCount; st->iShadeBob++ ) + free( st->aShadeBobs[ st->iShadeBob ].anDeltaMap ); + free( st->aShadeBobs ); + free( st->aiColorVals ); } +XSCREENSAVER_MODULE ("ShadeBobs", shadebobs) + /* End of Module - "shadebobs.c" */ + +/* vim: ts=4 + */