From http://www.jwz.org/xscreensaver/xscreensaver-5.35.tar.gz
[xscreensaver] / hacks / goop.c
index b7670e7cf3fbcb7176b20998f52b342eeabf7e63..0f5c139e34968bbf89536ffa4b3ed067332b4c65 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1997, 2006 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1997-2008 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -47,7 +47,6 @@
 #define SCALE       10000  /* fixed-point math, for sub-pixel motion */
 #define DEF_COUNT   12    /* When planes and count are 0, how many blobs. */
 
-
 #define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n))))
 #define RANDSIGN() ((random() & 1) ? 1 : -1)
 
@@ -126,10 +125,18 @@ make_blob (Display *dpy, int maxx, int maxy, int size)
   b->spline = make_spline (b->npoints);
   b->r = (long *) malloc (sizeof(*b->r) * b->npoints);
   for (i = 0; i < b->npoints; i++)
-    b->r[i] = ((random() % mid) + (mid/2)) * RANDSIGN();
+    b->r[i] = (long) ((random() % mid) + (mid/2)) * RANDSIGN();
   return b;
 }
 
+static void
+free_blob(struct blob *blob)
+{
+  free_spline(blob->spline);
+  free(blob->r);
+  free(blob);
+}
+
 static void 
 throb_blob (struct blob *b)
 {
@@ -267,15 +274,27 @@ make_layer (Display *dpy, Window window, int width, int height, int nblobs)
   layer->pixmap = XCreatePixmap (dpy, window, width, height, 1);
   layer->gc = XCreateGC (dpy, layer->pixmap, 0, &gcv);
 
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
   jwxyz_XSetAlphaAllowed (dpy, layer->gc, True);
-# endif /* HAVE_COCOA */
+# endif /* HAVE_JWXYZ */
 
   return layer;
 }
 
+static void
+free_layer(struct layer *layer, Display *dpy)
+{
+  int i;
+  for (i = 0; i < layer->nblobs; i++){
+    free_blob(layer->blobs[i]);
+  }
+  free(layer->blobs);
+  XFreeGC(dpy, layer->gc);
+  free(layer);
+}
+
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 static void
 draw_layer_plane (Display *dpy, struct layer *layer, int width, int height)
 {
@@ -287,7 +306,7 @@ draw_layer_plane (Display *dpy, struct layer *layer, int width, int height)
       draw_blob (dpy, layer->pixmap, layer->gc, layer->blobs[i], True);
     }
 }
-#endif /* !HAVE_COCOA */
+#endif /* !HAVE_JWXYZ */
 
 
 static void
@@ -316,7 +335,7 @@ make_goop (Screen *screen, Visual *visual, Window window, Colormap cmap,
   int nblobs = get_integer_resource (dpy, "count", "Count");
 
   unsigned long *plane_masks = 0;
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
   unsigned long base_pixel = 0;
 # endif
   char *s;
@@ -331,6 +350,7 @@ make_goop (Screen *screen, Visual *visual, Window window, Colormap cmap,
     goop->mode = xor;
   else
     fprintf (stderr, "%s: bogus mode: \"%s\"\n", progname, s);
+  free(s);
 
   goop->delay = get_integer_resource (dpy, "delay", "Integer");
 
@@ -340,7 +360,9 @@ make_goop (Screen *screen, Visual *visual, Window window, Colormap cmap,
   goop->nlayers = get_integer_resource (dpy, "planes", "Planes");
   if (goop->nlayers <= 0)
     goop->nlayers = (random() % (depth-2)) + 2;
-  goop->layers = (struct layer **) malloc(sizeof(*goop->layers)*goop->nlayers);
+  if (! goop->layers)
+    goop->layers = (struct layer **) 
+      malloc(sizeof(*goop->layers)*goop->nlayers);
 
   goop->additive_p = get_boolean_resource (dpy, "additive", "Additive");
   goop->cmap_p = has_writable_cells (screen, visual);
@@ -348,7 +370,7 @@ make_goop (Screen *screen, Visual *visual, Window window, Colormap cmap,
   if (mono_p && goop->mode == transparent)
     goop->mode = opaque;
 
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
   /* Try to allocate some color planes before committing to nlayers.
    */
   if (goop->mode == transparent)
@@ -367,7 +389,7 @@ make_goop (Screen *screen, Visual *visual, Window window, Colormap cmap,
          goop->mode = opaque;
        }
     }
-# endif /* !HAVE_COCOA */
+# endif /* !HAVE_JWXYZ */
 
   {
     int lblobs[32];
@@ -382,21 +404,21 @@ make_goop (Screen *screen, Visual *visual, Window window, Colormap cmap,
                                    (nblobs > 0 ? nblobs : lblobs[i]));
   }
 
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
   if (goop->mode == transparent && plane_masks)
     {
       for (i = 0; i < goop->nlayers; i++)
        goop->layers[i]->pixel = base_pixel | plane_masks[i];
       goop->background = base_pixel;
     }
-# endif /* !HAVE_COCOA */
+# endif /* !HAVE_JWXYZ */
 
   if (plane_masks)
     free (plane_masks);
 
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
   if (goop->mode != transparent)
-# endif /* !HAVE_COCOA */
+# endif /* !HAVE_JWXYZ */
     {
       XColor color;
       color.flags = DoRed|DoGreen|DoBlue;
@@ -415,17 +437,17 @@ make_goop (Screen *screen, Visual *visual, Window window, Colormap cmap,
          else
            goop->layers[i]->pixel =
              WhitePixelOfScreen(DefaultScreenOfDisplay(dpy));
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
           if (goop->mode == transparent)
             {
               /* give a non-opaque alpha to the color */
               unsigned long pixel = goop->layers[i]->pixel;
-              unsigned long amask = BlackPixelOfScreen (0);
+              unsigned long amask = BlackPixelOfScreen (screen);
               unsigned long a = (0xBBBBBBBB & amask);
               pixel = (pixel & (~amask)) | a;
               goop->layers[i]->pixel = pixel;
             }
-# endif /* HAVE_COCOA */
+# endif /* HAVE_JWXYZ */
        }
     }
 
@@ -438,13 +460,28 @@ make_goop (Screen *screen, Visual *visual, Window window, Colormap cmap,
   goop->pixmap_gc = XCreateGC (dpy, goop->pixmap, GCLineWidth, &gcv);
   goop->window_gc = XCreateGC (dpy, window, GCForeground|GCBackground, &gcv);
 
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
   jwxyz_XSetAlphaAllowed (dpy, goop->pixmap_gc, True);
-# endif /* HAVE_COCOA */
+# endif /* HAVE_JWXYZ */
   
   return goop;
 }
 
+/* Well, the naming of this function is
+   confusing with goop_free()... */
+static void
+free_goop (struct goop *goop, Display *dpy)
+{
+  int i;
+  for (i = 0; i < goop->nlayers; i++){
+    struct layer * layer = goop->layers[i];
+    free_layer(layer, dpy);
+  }
+  free(goop->layers);
+  XFreeGC(dpy, goop->pixmap_gc);
+  XFreeGC(dpy, goop->window_gc);
+}
+
 static void *
 goop_init (Display *dpy, Window window)
 {
@@ -462,7 +499,7 @@ goop_draw (Display *dpy, Window window, void *closure)
 
   switch (goop->mode)
     {
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
     case transparent:
 
       for (i = 0; i < goop->nlayers; i++)
@@ -496,7 +533,7 @@ goop_draw (Display *dpy, Window window, void *closure)
       XCopyArea (dpy, goop->pixmap, window, goop->window_gc, 0, 0,
                 goop->width, goop->height, 0, 0);
       break;
-#endif /* !HAVE_COCOA */
+#endif /* !HAVE_JWXYZ */
 
     case xor:
       XSetFunction (dpy, goop->pixmap_gc, GXcopy);
@@ -513,7 +550,7 @@ goop_draw (Display *dpy, Window window, void *closure)
                  goop->width, goop->height, 0, 0, 1L);
       break;
 
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
     case transparent:
 # endif
     case opaque:
@@ -543,7 +580,15 @@ static void
 goop_reshape (Display *dpy, Window window, void *closure, 
                  unsigned int w, unsigned int h)
 {
-  /* #### write me */
+  struct goop *goop = (struct goop *) closure;
+
+  if (w != goop->width || h != goop->height)
+    {
+      struct goop *goop2 = goop_init (dpy, window);
+      free_goop(goop, dpy);
+      memcpy (goop, goop2, sizeof(*goop));
+      free(goop2);
+    }
 }
 
 static Bool
@@ -555,6 +600,9 @@ goop_event (Display *dpy, Window window, void *closure, XEvent *event)
 static void
 goop_free (Display *dpy, Window window, void *closure)
 {
+  struct goop *goop = (struct goop *) closure;
+  free_goop(goop, dpy);
+  free(goop);
 }
 
 
@@ -566,12 +614,15 @@ static const char *goop_defaults [] = {
   "*delay:             12000",
   "*additive:          true",
   "*mode:              transparent",
-  "*count:             0",
-  "*planes:            0",
+  "*count:             1",
+  "*planes:            12",
   "*thickness:         5",
   "*torque:            0.0075",
   "*elasticity:                0.9",
   "*maxVelocity:       0.5",
+#ifdef HAVE_MOBILE
+  "*ignoreRotation:     True",
+#endif
   0
 };