-/* xscreensaver, Copyright (c) 1997 Jamie Zawinski <jwz@netscape.com>
+/* 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
blobs could have thickness, and curved edges with specular reflections...
*/
-
#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)
Pixmap pixmap;
GC pixmap_gc;
GC window_gc;
+ Bool additive_p;
+ Bool cmap_p;
+ int delay;
};
static struct blob *
-make_blob (int maxx, int maxy, int size)
+make_blob (Display *dpy, int maxx, int maxy, int size)
{
struct blob *b = (struct blob *) calloc(1, sizeof(*b));
int i;
if (b->min_r < (5*SCALE)) b->min_r = (5*SCALE);
mid = ((b->min_r + b->max_r) / 2);
- b->torque = get_float_resource ("torque", "Torque");
- b->elasticity = SCALE * get_float_resource ("elasticity", "Elasticity");
- b->max_velocity = SCALE * get_float_resource ("maxVelocity", "MaxVelocity");
+ b->torque = get_float_resource (dpy, "torque", "Torque");
+ b->elasticity = SCALE * get_float_resource (dpy, "elasticity", "Elasticity");
+ b->max_velocity = SCALE * get_float_resource (dpy, "maxVelocity", "MaxVelocity");
b->x = RAND(maxx);
b->y = RAND(maxy);
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)
{
blob_max = (width < height ? width : height) / 2;
blob_min = (blob_max * 2) / 3;
- for (i = 0; i < layer->nblobs; i++)
- layer->blobs[i] = make_blob (width, height,
- (random() % (blob_max-blob_min)) + blob_min);
+ for (i = 0; i < layer->nblobs; i++){
+ int j = blob_max - blob_min;
+ layer->blobs[i] = make_blob (dpy, width, height,
+ (j ? random() % j : 0) + blob_min);
+ }
layer->pixmap = XCreatePixmap (dpy, window, width, height, 1);
layer->gc = XCreateGC (dpy, layer->pixmap, 0, &gcv);
+# ifdef HAVE_COCOA
+ jwxyz_XSetAlphaAllowed (dpy, layer->gc, True);
+# endif /* HAVE_COCOA */
+
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
static void
draw_layer_plane (Display *dpy, struct layer *layer, int width, int height)
{
int i;
- XSetForeground (dpy, layer->gc, 1L);
- XFillRectangle (dpy, layer->pixmap, layer->gc, 0, 0, width, height);
- XSetForeground (dpy, layer->gc, 0L);
for (i = 0; i < layer->nblobs; i++)
{
throb_blob (layer->blobs[i]);
draw_blob (dpy, layer->pixmap, layer->gc, layer->blobs[i], True);
}
}
+#endif /* !HAVE_COCOA */
static void
int i;
for (i = 0; i < layer->nblobs; i++)
{
+ draw_blob (dpy, drawable, gc, layer->blobs[i], fill_p);
throb_blob (layer->blobs[i]);
move_blob (layer->blobs[i], width, height);
- draw_blob (dpy, drawable, gc, layer->blobs[i], fill_p);
}
}
static struct goop *
-make_goop (Display *dpy, Window window, Colormap cmap,
+make_goop (Screen *screen, Visual *visual, Window window, Colormap cmap,
int width, int height, long depth)
{
+ Display *dpy = DisplayOfScreen (screen);
int i;
struct goop *goop = (struct goop *) calloc(1, sizeof(*goop));
XGCValues gcv;
- int nblobs = get_integer_resource ("count", "Count");
+ int nblobs = get_integer_resource (dpy, "count", "Count");
unsigned long *plane_masks = 0;
+# ifndef HAVE_COCOA
unsigned long base_pixel = 0;
+# endif
+ char *s;
+
+ s = get_string_resource (dpy, "mode", "Mode");
+ goop->mode = transparent;
+ if (!s || !*s || !strcasecmp (s, "transparent"))
+ ;
+ else if (!strcasecmp (s, "opaque"))
+ goop->mode = opaque;
+ else if (!strcasecmp (s, "xor"))
+ goop->mode = xor;
+ else
+ fprintf (stderr, "%s: bogus mode: \"%s\"\n", progname, s);
+ free(s);
- goop->mode = (get_boolean_resource("xor", "Xor")
- ? xor
- : (get_boolean_resource("transparent", "Transparent")
- ? transparent
- : opaque));
+ goop->delay = get_integer_resource (dpy, "delay", "Integer");
goop->width = width;
goop->height = height;
-
- goop->nlayers = get_integer_resource ("planes", "Planes");
+ 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);
if (mono_p && goop->mode == transparent)
goop->mode = opaque;
+# ifndef HAVE_COCOA
/* Try to allocate some color planes before committing to nlayers.
*/
if (goop->mode == transparent)
{
- Bool additive_p = get_boolean_resource ("additive", "Additive");
int nplanes = goop->nlayers;
- allocate_alpha_colors (dpy, cmap, &nplanes, additive_p, &plane_masks,
+ allocate_alpha_colors (screen, visual, cmap,
+ &nplanes, goop->additive_p, &plane_masks,
&base_pixel);
if (nplanes > 1)
goop->nlayers = nplanes;
goop->mode = opaque;
}
}
+# endif /* !HAVE_COCOA */
{
int lblobs[32];
(nblobs > 0 ? nblobs : lblobs[i]));
}
+# ifndef HAVE_COCOA
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 */
+
if (plane_masks)
free (plane_masks);
+# ifndef HAVE_COCOA
if (goop->mode != transparent)
+# endif /* !HAVE_COCOA */
{
XColor color;
color.flags = DoRed|DoGreen|DoBlue;
goop->background =
- get_pixel_resource ("background", "Background", dpy,cmap);
+ get_pixel_resource (dpy,cmap, "background", "Background");
for (i = 0; i < goop->nlayers; i++)
{
else
goop->layers[i]->pixel =
WhitePixelOfScreen(DefaultScreenOfDisplay(dpy));
+# ifdef HAVE_COCOA
+ 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 a = (0xBBBBBBBB & amask);
+ pixel = (pixel & (~amask)) | a;
+ goop->layers[i]->pixel = pixel;
+ }
+# endif /* HAVE_COCOA */
}
}
(goop->mode == xor ? 1L : depth));
gcv.background = goop->background;
- gcv.foreground = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
- gcv.line_width = get_integer_resource ("thickness","Thickness");
+ gcv.foreground = get_pixel_resource (dpy, cmap, "foreground", "Foreground");
+ gcv.line_width = get_integer_resource (dpy, "thickness","Thickness");
goop->pixmap_gc = XCreateGC (dpy, goop->pixmap, GCLineWidth, &gcv);
goop->window_gc = XCreateGC (dpy, window, GCForeground|GCBackground, &gcv);
+# ifdef HAVE_COCOA
+ jwxyz_XSetAlphaAllowed (dpy, goop->pixmap_gc, True);
+# endif /* HAVE_COCOA */
+
return goop;
}
-static struct goop *
-init_goop (Display *dpy, Window window)
+/* 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)
{
XWindowAttributes xgwa;
XGetWindowAttributes (dpy, window, &xgwa);
-
- return make_goop (dpy, window, xgwa.colormap,
+ return make_goop (xgwa.screen, xgwa.visual, window, xgwa.colormap,
xgwa.width, xgwa.height, xgwa.depth);
}
-static void
-run_goop (Display *dpy, Window window, struct goop *goop)
+static unsigned long
+goop_draw (Display *dpy, Window window, void *closure)
{
+ struct goop *goop = (struct goop *) closure;
int i;
switch (goop->mode)
{
+# ifndef HAVE_COCOA
case transparent:
for (i = 0; i < goop->nlayers; i++)
draw_layer_plane (dpy, goop->layers[i], goop->width, goop->height);
XSetForeground (dpy, goop->pixmap_gc, goop->background);
+ XSetFunction (dpy, goop->pixmap_gc, GXcopy);
XSetPlaneMask (dpy, goop->pixmap_gc, AllPlanes);
XFillRectangle (dpy, goop->pixmap, goop->pixmap_gc, 0, 0,
goop->width, goop->height);
+
XSetForeground (dpy, goop->pixmap_gc, ~0L);
+
+ if (!goop->cmap_p && !goop->additive_p)
+ {
+ int j;
+ for (i = 0; i < goop->nlayers; i++)
+ for (j = 0; j < goop->layers[i]->nblobs; j++)
+ draw_blob (dpy, goop->pixmap, goop->pixmap_gc,
+ goop->layers[i]->blobs[j], True);
+ XSetFunction (dpy, goop->pixmap_gc, GXclear);
+ }
+
for (i = 0; i < goop->nlayers; i++)
{
XSetPlaneMask (dpy, goop->pixmap_gc, goop->layers[i]->pixel);
-/*
- XSetForeground (dpy, goop->pixmap_gc, ~0L);
- XFillRectangle (dpy, goop->pixmap, goop->pixmap_gc, 0, 0,
- goop->width, goop->height);
- XSetForeground (dpy, goop->pixmap_gc, 0L);
- */
draw_layer_blobs (dpy, goop->pixmap, goop->pixmap_gc,
goop->layers[i], goop->width, goop->height,
True);
XCopyArea (dpy, goop->pixmap, window, goop->window_gc, 0, 0,
goop->width, goop->height, 0, 0);
break;
+#endif /* !HAVE_COCOA */
case xor:
XSetFunction (dpy, goop->pixmap_gc, GXcopy);
goop->width, goop->height, 0, 0, 1L);
break;
+# ifdef HAVE_COCOA
+ case transparent:
+# endif
case opaque:
case outline:
XSetForeground (dpy, goop->pixmap_gc, goop->background);
abort ();
break;
}
+ return goop->delay;
+}
+
+static void
+goop_reshape (Display *dpy, Window window, void *closure,
+ unsigned int w, unsigned int h)
+{
+ struct goop *goop = (struct goop *) closure;
+
+ struct goop *goop2 = goop_init (dpy, window);
+ free_goop(goop, dpy);
+ memcpy (goop, goop2, sizeof(*goop));
+ free(goop2);
}
+static Bool
+goop_event (Display *dpy, Window window, void *closure, XEvent *event)
+{
+ return False;
+}
+
+static void
+goop_free (Display *dpy, Window window, void *closure)
+{
+ struct goop *goop = (struct goop *) closure;
+ free_goop(goop, dpy);
+ free(goop);
+}
+
+
\f
-char *progclass = "Goop";
-char *defaults [] = {
+static const char *goop_defaults [] = {
".background: black",
- ".foreground: white",
+ ".foreground: yellow",
"*delay: 12000",
- "*transparent: true",
"*additive: true",
- "*xor: false",
- "*count: 0",
- "*planes: 0",
+ "*mode: transparent",
+ "*count: 1",
+ "*planes: 12",
"*thickness: 5",
"*torque: 0.0075",
- "*elasticity: 1.8",
- "*maxVelocity: 1.2",
+ "*elasticity: 0.9",
+ "*maxVelocity: 0.5",
+#ifdef USE_IPHONE
+ "*ignoreRotation: True",
+#endif
0
};
-XrmOptionDescRec options [] = {
+static XrmOptionDescRec goop_options [] = {
{ "-delay", ".delay", XrmoptionSepArg, 0 },
{ "-count", ".count", XrmoptionSepArg, 0 },
{ "-planes", ".planes", XrmoptionSepArg, 0 },
- { "-transparent", ".transparent", XrmoptionNoArg, "True" },
- { "-non-transparent", ".transparent", XrmoptionNoArg, "False" },
+ { "-mode", ".mode", XrmoptionSepArg, 0 },
+ { "-xor", ".mode", XrmoptionNoArg, "xor" },
+ { "-transparent", ".mode", XrmoptionNoArg, "transparent" },
+ { "-opaque", ".mode", XrmoptionNoArg, "opaque" },
{ "-additive", ".additive", XrmoptionNoArg, "True" },
{ "-subtractive", ".additive", XrmoptionNoArg, "false" },
- { "-xor", ".xor", XrmoptionNoArg, "true" },
- { "-no-xor", ".xor", XrmoptionNoArg, "false" },
{ "-thickness", ".thickness", XrmoptionSepArg, 0 },
{ "-torque", ".torque", XrmoptionSepArg, 0 },
{ "-elasticity", ".elasticity", XrmoptionSepArg, 0 },
{ 0, 0, 0, 0 }
};
-void
-screenhack (Display *dpy, Window window)
-{
- struct goop *g = init_goop (dpy, window);
- int delay = get_integer_resource ("delay", "Integer");
- while (1)
- {
- run_goop (dpy, window, g);
- XSync (dpy, True);
- if (delay) usleep (delay);
- }
-}
+XSCREENSAVER_MODULE ("Goop", goop)