http://ftp.x.org/contrib/applications/xscreensaver-3.19.tar.gz
[xscreensaver] / hacks / shadebobs.c
index fc89ceeecbaaacb86175bbd47d6573e4ac6ca9d0..422bc1b2abbd3b0ab55067d886fdfef0f49e64f5 100644 (file)
@@ -28,6 +28,9 @@
  *                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 :).
  */
 
 #include <math.h>
 char *progclass = "ShadeBobs";
 
 char *defaults [] = {
-  "*degrees:  512",
+  "*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",
   0
@@ -63,6 +66,8 @@ static unsigned short nMaxExtentX, nMaxExtentY;
 static unsigned short nMinExtentX, nMinExtentY;
 static unsigned short nHalfWidth, nHalfHeight;
 static char *sColor;
+static unsigned char nBobRadius, nBobDiameter; 
+static float nExtentDelta; 
 
 #define RANDOM() ((int) (random() & 0X7FFFFFFFL))
 
@@ -70,14 +75,12 @@ static char *sColor;
 /* Ahem. Chocolate is a flavor; not a food. Thank you */
 
 
-#define MAPSIZE 32
-
 typedef struct
 {
-  char anDeltaMap[ MAPSIZE * MAPSIZE ];  /* 32 x 32 Delta Map */
+  signed char *anDeltaMap;
   double nVelocityX, nVelocityY;
   double nAngleX, nAngleY;
-  short nExtentX, nExtentY;
+  float nExtentX, nExtentY;
 } SShadeBob;
 
 
@@ -94,19 +97,25 @@ static void ResetShadeBob( SShadeBob *pShadeBob )
 static void InitShadeBob( SShadeBob *pShadeBob, Bool bDark )
 {
   double nDelta;
-  char iWidth, iHeight;
+  int iWidth, iHeight;
 
-  for( iHeight=-16; iHeight<16; iHeight++ )
-    for( iWidth=-16; iWidth<16; iWidth++ )
+  if( ( pShadeBob->anDeltaMap = calloc( nBobDiameter * nBobDiameter, sizeof(char) ) ) == NULL )
+  {
+    fprintf( stderr, "Could not allocate Delta Map!\n" );
+    return;
+  }
+
+  for( iHeight=-nBobRadius; iHeight<nBobRadius; iHeight++ )
+    for( iWidth=-nBobRadius; iWidth<nBobRadius; iWidth++ )
     {
-      nDelta = 9 - (sqrt( pow( iWidth+0.5, 2 ) + pow( iHeight+0.5, 2 ) ) / 2 );
+      nDelta = 9 - ( ( sqrt( pow( iWidth+0.5, 2 ) + pow( iHeight+0.5, 2 ) ) / nBobRadius ) * 8 );
       if( nDelta < 0 )  nDelta = 0;
       if( bDark ) nDelta = -nDelta;
-      pShadeBob->anDeltaMap[ (iWidth+(MAPSIZE/2))*MAPSIZE
-                           + iHeight+(MAPSIZE/2) ] = (char)nDelta;
+      pShadeBob->anDeltaMap[ ( iWidth + nBobRadius ) * nBobDiameter
+                           + iHeight + nBobRadius ] = (char)nDelta;
     }
-
-       ResetShadeBob( pShadeBob );
+  
+  ResetShadeBob( pShadeBob );
 }
 
 
@@ -131,15 +140,13 @@ static void Execute( SShadeBob *pShadeBob, Display *pDisplay,
   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;
+  if( pShadeBob->nAngleX >= nDegreeCount ) pShadeBob->nAngleX -= nDegreeCount;
+  if( pShadeBob->nAngleY >= nDegreeCount ) pShadeBob->nAngleY -= nDegreeCount;
 
-  pShadeBob->nExtentX += ( RANDOM() % 5 ) - 2;
+  pShadeBob->nExtentX += ( ( ( RANDOM() % 5 ) - 2 ) / 2.0F ) * nExtentDelta;
   if( pShadeBob->nExtentX > nMaxExtentX ) pShadeBob->nExtentX = nMaxExtentX;
   if( pShadeBob->nExtentX < nMinExtentX ) pShadeBob->nExtentX = nMinExtentX;
-  pShadeBob->nExtentY += ( RANDOM() % 5 ) - 2;
+  pShadeBob->nExtentY += ( ( ( RANDOM() % 5 ) - 2 ) / 2.0F ) * nExtentDelta;
   if( pShadeBob->nExtentY > nMaxExtentY ) pShadeBob->nExtentY = nMaxExtentY;
   if( pShadeBob->nExtentY < nMinExtentY ) pShadeBob->nExtentY = nMinExtentY;
 
@@ -149,9 +156,9 @@ static void Execute( SShadeBob *pShadeBob, Display *pDisplay,
   nYPos = (unsigned int)(( anSinTable[ (int)pShadeBob->nAngleY ] * pShadeBob->nExtentY )
                          + nHalfHeight);
 
-  for( iHeight=0; iHeight < MAPSIZE; iHeight++ )
+  for( iHeight=0; iHeight<nBobDiameter; iHeight++ )
   {
-    for( iWidth=0; iWidth < MAPSIZE; iWidth++ )
+    for( iWidth=0; iWidth<nBobDiameter; iWidth++ )
     {
       nColor = XGetPixel( pXImage, nXPos + iWidth, nYPos + iHeight );
 
@@ -160,7 +167,7 @@ static void Execute( SShadeBob *pShadeBob, Display *pDisplay,
         if( aXColors[ nIndex ].pixel == nColor )
           break;
 
-      nIndex += pShadeBob->anDeltaMap[ iWidth * MAPSIZE + iHeight ];
+      nIndex += pShadeBob->anDeltaMap[ iWidth * nBobDiameter + iHeight ];
       if( nIndex >= ncolors ) nIndex = ncolors-1;
       if( nIndex < 0 )  nIndex = 0;
 
@@ -168,9 +175,9 @@ static void Execute( SShadeBob *pShadeBob, Display *pDisplay,
                  aXColors[ nIndex ].pixel );
     }
   }
-  /* Place graphics in window */
+
   XPutImage( pDisplay, MainWindow, *pGC, pXImage,
-             nXPos, nYPos, nXPos, nYPos, MAPSIZE, MAPSIZE );
+             nXPos, nYPos, nXPos, nYPos, nBobDiameter, nBobDiameter );
   XSync (pDisplay, False);
 }
 
@@ -242,11 +249,13 @@ static void SetPalette(Display *pDisplay, Window Win, char *sColor,
                      False, True, False );
     *ncolorsP = n1 + n2;
   }
+
+  XSetWindowBackground( pDisplay, Win, aXColors[ 0 ].pixel );
 }
 
 
 static void Initialize( Display *pDisplay, Window Win,
-                        GC *pGC, XImage *pXImage,
+                        GC *pGC, XImage **pXImage,
                         int *ncolorsP, XColor *aXColors )
 {
   XGCValues gcValues;
@@ -273,36 +282,39 @@ static void Initialize( Display *pDisplay, Window Win,
   /*  Create the GC. */
   *pGC = XCreateGC( pDisplay, Win, 0, &gcValues );
 
-  memset (pXImage, 0, sizeof(*pXImage));
-  pXImage->width = XWinAttribs.width;                   /* Width of image */
-  pXImage->height = XWinAttribs.height;                 /* Height of image */
-  pXImage->format = ZPixmap;                /* XYBitmap, XYPixmap, ZPixmap */
-
-  /* Pointer to image data */
-  pXImage->byte_order = ImageByteOrder(pDisplay);
-  pXImage->bitmap_unit = BitmapUnit(pDisplay);
-  pXImage->bitmap_bit_order = BitmapBitOrder(pDisplay);
-  pXImage->bitmap_pad = BitmapPad(pDisplay);
-  pXImage->depth = XWinAttribs.depth;
-  pXImage->bytes_per_line = 0;                /* Accelerator to next line */
-  pXImage->bits_per_pixel = bpp;
-  XInitImage( pXImage );
-  pXImage->data = calloc(pXImage->bytes_per_line, pXImage->height);
+  *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;
+  nBobDiameter = XWinAttribs.width / 25;
+  nBobRadius = nBobDiameter / 2;
+  nExtentDelta = nBobRadius / 5.0F;
+#ifdef VERBOSE
+  printf( "Bob Diameter = %d\n", nBobDiameter );
+#endif
+
+  nHalfWidth = ( XWinAttribs.width / 2 ) - nBobRadius;
+  nHalfHeight = ( XWinAttribs.height / 2 ) - nBobRadius;
+  nMaxExtentX = nHalfWidth - nBobRadius;
+  nMaxExtentY = nHalfHeight - nBobRadius;
   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;
+  if(      nDegreeCount == 0   ) nDegreeCount = ( XWinAttribs.width / 6 ) + 400;
+  else if( nDegreeCount < 90   ) nDegreeCount = 90;
+  else if( nDegreeCount > 5400 ) nDegreeCount = 5400;
   CreateTables( nDegreeCount );
-
+#ifdef VERBOSE
+  printf( "Using a %d degree circle.\n", nDegreeCount );
+#endif /* VERBOSE */
+  
   /*  Get the colors. */
   sColor = get_string_resource( "color", "Color" );
   if( sColor == NULL)
@@ -317,7 +329,7 @@ void screenhack(Display *pDisplay, Window Win )
   GC gc;
   int ncolors = 0;
   XColor aXColors[ 256 ];
-  XImage Image;
+  XImage *pImage;
   unsigned char nShadeBobCount, iShadeBob;
   SShadeBob *aShadeBobs;
 #ifdef VERBOSE
@@ -339,24 +351,24 @@ void screenhack(Display *pDisplay, Window Win )
   printf( "Allocated %d ShadeBobs\n", nShadeBobCount );
 #endif  /*  VERBOSE */
 
-  Initialize( pDisplay, Win, &gc, &Image, &ncolors, aXColors );
+  Initialize( pDisplay, Win, &gc, &pImage, &ncolors, aXColors );
 
   for( iShadeBob=0; iShadeBob<nShadeBobCount; iShadeBob++ )
     InitShadeBob( &aShadeBobs[ iShadeBob ], iShadeBob % 2 );
 
   delay = get_integer_resource( "delay", "Integer" );
-  cycles = get_integer_resource( "cycles", "Integer" ) * (nDegreeCount / 3);
+  cycles = get_integer_resource( "cycles", "Integer" ) * nDegreeCount;
   i = cycles;
 
-  while (1)
+  while( 1 )
   {
     screenhack_handle_events( pDisplay );
 
     if (i++ >= cycles)
     {
       i = 0;
-      XClearWindow (pDisplay, Win);
-      memset (Image.data, 0, Image.bytes_per_line * Image.height);
+      XClearWindow( pDisplay, Win );
+      memset( pImage->data, 0, pImage->bytes_per_line * pImage->height );
       for( iShadeBob=0; iShadeBob<nShadeBobCount; iShadeBob++ )
         ResetShadeBob( &aShadeBobs[ iShadeBob ] );
       SetPalette( pDisplay, Win, sColor, &ncolors, aXColors );
@@ -364,7 +376,7 @@ void screenhack(Display *pDisplay, Window Win )
 
     for( iShadeBob=0; iShadeBob<nShadeBobCount; iShadeBob++ )
       Execute( &aShadeBobs[ iShadeBob ], pDisplay, Win, &gc,
-               &Image, ncolors, aXColors );
+               pImage, ncolors, aXColors );
 
     if( delay && !(i % 4) )
                usleep(delay);
@@ -381,8 +393,10 @@ void screenhack(Display *pDisplay, Window Win )
   }
 
   free( anSinTable );
-  free( Image.data );
-  XDestroyImage( &Image );
+  free( pImage->data );
+  XDestroyImage( pImage );
+  for( iShadeBob=0; iShadeBob<nShadeBobCount; iShadeBob++ )
+    free( aShadeBobs[ iShadeBob ].anDeltaMap );
   free( aShadeBobs );
 }