X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fgoop.c;h=0f5c139e34968bbf89536ffa4b3ed067332b4c65;hb=aa75c7476aeaa84cf3abc192b376a8b03c325213;hp=233708e6913fc714ae1d0845792d42a3198a47bb;hpb=ce3185de9d9705e259f2b60dd4b5509007fa17d4;p=xscreensaver diff --git a/hacks/goop.c b/hacks/goop.c index 233708e6..0f5c139e 100644 --- a/hacks/goop.c +++ b/hacks/goop.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 1997 Jamie Zawinski +/* xscreensaver, Copyright (c) 1997-2008 Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -44,11 +44,9 @@ 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) @@ -89,11 +87,14 @@ struct goop { 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; @@ -109,9 +110,9 @@ make_blob (int maxx, int maxy, int size) 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); @@ -124,10 +125,18 @@ make_blob (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) { @@ -256,23 +265,40 @@ make_layer (Display *dpy, Window window, int width, int height, int nblobs) 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_JWXYZ + jwxyz_XSetAlphaAllowed (dpy, layer->gc, True); +# 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_JWXYZ 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]); @@ -280,6 +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_JWXYZ */ static void @@ -290,51 +317,67 @@ draw_layer_blobs (Display *dpy, Drawable drawable, GC gc, 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_JWXYZ 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_JWXYZ /* 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; @@ -346,6 +389,7 @@ make_goop (Display *dpy, Window window, Colormap cmap, goop->mode = opaque; } } +# endif /* !HAVE_JWXYZ */ { int lblobs[32]; @@ -360,22 +404,27 @@ make_goop (Display *dpy, Window window, Colormap cmap, (nblobs > 0 ? nblobs : lblobs[i])); } +# 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_JWXYZ */ + if (plane_masks) free (plane_masks); +# ifndef HAVE_JWXYZ if (goop->mode != transparent) +# endif /* !HAVE_JWXYZ */ { 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++) { @@ -388,6 +437,17 @@ make_goop (Display *dpy, Window window, Colormap cmap, else goop->layers[i]->pixel = WhitePixelOfScreen(DefaultScreenOfDisplay(dpy)); +# 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 (screen); + unsigned long a = (0xBBBBBBBB & amask); + pixel = (pixel & (~amask)) | a; + goop->layers[i]->pixel = pixel; + } +# endif /* HAVE_JWXYZ */ } } @@ -395,50 +455,77 @@ make_goop (Display *dpy, Window window, Colormap cmap, (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_JWXYZ + jwxyz_XSetAlphaAllowed (dpy, goop->pixmap_gc, True); +# endif /* HAVE_JWXYZ */ + 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_JWXYZ 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); @@ -446,6 +533,7 @@ run_goop (Display *dpy, Window window, struct goop *goop) XCopyArea (dpy, goop->pixmap, window, goop->window_gc, 0, 0, goop->width, goop->height, 0, 0); break; +#endif /* !HAVE_JWXYZ */ case xor: XSetFunction (dpy, goop->pixmap_gc, GXcopy); @@ -462,6 +550,9 @@ run_goop (Display *dpy, Window window, struct goop *goop) goop->width, goop->height, 0, 0, 1L); break; +# ifdef HAVE_JWXYZ + case transparent: +# endif case opaque: case outline: XSetForeground (dpy, goop->pixmap_gc, goop->background); @@ -482,37 +573,69 @@ run_goop (Display *dpy, Window window, struct goop *goop) 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; + + 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 +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); } + -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 HAVE_MOBILE + "*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 }, @@ -520,15 +643,4 @@ XrmOptionDescRec options [] = { { 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)