X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fdeluxe.c;h=06cfe1b9dc7373b3c4d1b15e4331930f8f6fcc04;hb=4ade52359b6eba3621566dac79793a33aa4c915f;hp=75b9832900956d7d6369d2fbbe3bb87e997e3840;hpb=96a411663168b0ba5432b407a83be55f3df0c802;p=xscreensaver diff --git a/hacks/deluxe.c b/hacks/deluxe.c index 75b98329..06cfe1b9 100644 --- a/hacks/deluxe.c +++ b/hacks/deluxe.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 1999, 2001, 2002 Jamie Zawinski +/* xscreensaver, Copyright (c) 1999-2013 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 @@ -20,9 +20,29 @@ #define countof(x) (sizeof(x)/sizeof(*(x))) #define ABS(x) ((x)<0?-(x):(x)) -static Bool transparent_p; -static int nplanes; -static unsigned long base_pixel, *plane_masks; +struct state { + Display *dpy; + Window window; + + Bool transparent_p; + int nplanes; + unsigned long base_pixel, *plane_masks; + + int count; + int delay; + int ncolors; + Bool dbuf; + XColor *colors; + GC erase_gc; + struct throbber **throbbers; + XWindowAttributes xgwa; + Pixmap b, ba, bb; /* double-buffer to reduce flicker */ + +# ifdef HAVE_DOUBLE_BUFFER_EXTENSION + Bool dbeclear_p; + XdbeBackBuffer backb; +# endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ +}; struct throbber { int x, y; @@ -32,16 +52,24 @@ struct throbber { int speed; int fuse; GC gc; - void (*draw) (Display *, Drawable, struct throbber *); + void (*draw) (struct state *, Drawable, struct throbber *); }; + static void -draw_star (Display *dpy, Drawable w, struct throbber *t) +draw_star (struct state *st, Drawable w, struct throbber *t) { XPoint points[11]; int x = t->x; int y = t->y; - int s = t->size / 0.383; /* trial and error, I forget how to derive this */ + + /* + The following constant is really: + sqrt(5 - sqrt(5)) / sqrt(25 - 11 * sqrt(5)) + + Reference: http://mathworld.wolfram.com/Pentagram.html + */ + int s = t->size * 2.6180339887498985; int s2 = t->size; double c = M_PI * 2; double o = -M_PI / 2; @@ -58,13 +86,13 @@ draw_star (Display *dpy, Drawable w, struct throbber *t) points[9].x = x + s2 * cos(o + 0.9*c); points[9].y = y + s2 * sin(o + 0.9*c); points[10] = points[0]; - XDrawLines (dpy, w, t->gc, points, countof(points), CoordModeOrigin); + XDrawLines (st->dpy, w, t->gc, points, countof(points), CoordModeOrigin); } static void -draw_circle (Display *dpy, Drawable w, struct throbber *t) +draw_circle (struct state *st, Drawable w, struct throbber *t) { - XDrawArc (dpy, w, t->gc, + XDrawArc (st->dpy, w, t->gc, t->x - t->size / 2, t->y - t->size / 2, t->size, t->size, @@ -72,96 +100,112 @@ draw_circle (Display *dpy, Drawable w, struct throbber *t) } static void -draw_hlines (Display *dpy, Drawable w, struct throbber *t) +draw_hlines (struct state *st, Drawable w, struct throbber *t) { - XDrawLine (dpy, w, t->gc, 0, + XDrawLine (st->dpy, w, t->gc, 0, t->y - t->size, t->max_size, t->y - t->size); - XDrawLine (dpy, w, t->gc, 0, + XDrawLine (st->dpy, w, t->gc, 0, t->y + t->size, t->max_size, t->y + t->size); } static void -draw_vlines (Display *dpy, Drawable w, struct throbber *t) +draw_vlines (struct state *st, Drawable w, struct throbber *t) { - XDrawLine (dpy, w, t->gc, + XDrawLine (st->dpy, w, t->gc, t->x - t->size, 0, t->x - t->size, t->max_size); - XDrawLine (dpy, w, t->gc, + XDrawLine (st->dpy, w, t->gc, t->x + t->size, 0, t->x + t->size, t->max_size); } static void -draw_corners (Display *dpy, Drawable w, struct throbber *t) +draw_corners (struct state *st, Drawable w, struct throbber *t) { int s = (t->size + t->thickness) / 2; XPoint points[3]; - points[0].x = 0; points[0].y = t->y - s; - points[1].x = t->x - s; points[1].y = t->y - s; - points[2].x = t->x - s; points[2].y = 0; - XDrawLines (dpy, w, t->gc, points, countof(points), CoordModeOrigin); - - points[0].x = 0; points[0].y = t->y + s; - points[1].x = t->x - s; points[1].y = t->y + s; - points[2].x = t->x - s; points[2].y = t->max_size; - XDrawLines (dpy, w, t->gc, points, countof(points), CoordModeOrigin); - - points[0].x = t->x + s; points[0].y = 0; - points[1].x = t->x + s; points[1].y = t->y - s; - points[2].x = t->max_size; points[2].y = t->y - s; - XDrawLines (dpy, w, t->gc, points, countof(points), CoordModeOrigin); - - points[0].x = t->x + s; points[0].y = t->max_size; - points[1].x = t->x + s; points[1].y = t->y + s; - points[2].x = t->max_size; points[2].y = t->y + s; - XDrawLines (dpy, w, t->gc, points, countof(points), CoordModeOrigin); + if (t->y > s) + { + points[0].x = 0; points[0].y = t->y - s; + points[1].x = t->x - s; points[1].y = t->y - s; + points[2].x = t->x - s; points[2].y = 0; + XDrawLines (st->dpy, w, t->gc, points, countof(points), CoordModeOrigin); + + points[0].x = t->x + s; points[0].y = 0; + points[1].x = t->x + s; points[1].y = t->y - s; + points[2].x = t->max_size; points[2].y = t->y - s; + XDrawLines (st->dpy, w, t->gc, points, countof(points), CoordModeOrigin); + } + + if (t->x > s) + { + points[0].x = 0; points[0].y = t->y + s; + points[1].x = t->x - s; points[1].y = t->y + s; + points[2].x = t->x - s; points[2].y = t->max_size; + XDrawLines (st->dpy, w, t->gc, points, countof(points), CoordModeOrigin); + + points[0].x = t->x + s; points[0].y = t->max_size; + points[1].x = t->x + s; points[1].y = t->y + s; + points[2].x = t->max_size; points[2].y = t->y + s; + XDrawLines (st->dpy, w, t->gc, points, countof(points), CoordModeOrigin); + } } static struct throbber * -make_throbber (Display *dpy, Drawable d, int w, int h, unsigned long pixel) +make_throbber (struct state *st, Drawable d, int w, int h, unsigned long pixel) { XGCValues gcv; unsigned long flags; struct throbber *t = (struct throbber *) malloc (sizeof (*t)); t->x = w / 2; t->y = h / 2; - t->max_size = w; - t->speed = get_integer_resource ("speed", "Speed"); + t->max_size = (w > h ? w : h); + t->speed = get_integer_resource (st->dpy, "speed", "Speed"); t->fuse = 1 + (random() % 4); - t->thickness = get_integer_resource ("thickness", "Thickness"); + t->thickness = get_integer_resource (st->dpy, "thickness", "Thickness"); if (t->speed < 0) t->speed = -t->speed; t->speed += (((random() % t->speed) / 2) - (t->speed / 2)); if (t->speed > 0) t->speed = -t->speed; - if (random() % 4) - t->size = t->max_size; - else - t->size = t->thickness, t->speed = -t->speed; - flags = GCForeground; - if (transparent_p) +# ifndef HAVE_COCOA + if (st->transparent_p) { gcv.foreground = ~0L; - gcv.plane_mask = base_pixel | plane_masks[random() % nplanes]; + gcv.plane_mask = st->base_pixel | st->plane_masks[random() % st->nplanes]; flags |= GCPlaneMask; } else +# endif /* !HAVE_COCOA */ { gcv.foreground = pixel; } gcv.line_width = t->thickness; - gcv.line_style = LineSolid; gcv.cap_style = CapProjecting; gcv.join_style = JoinMiter; - flags |= (GCLineWidth | GCLineStyle | GCCapStyle | GCJoinStyle); - t->gc = XCreateGC (dpy, d, flags, &gcv); + flags |= (GCLineWidth | GCCapStyle | GCJoinStyle); + t->gc = XCreateGC (st->dpy, d, flags, &gcv); + +# ifdef HAVE_COCOA + if (st->transparent_p) + { + /* give a non-opaque alpha to the color */ + unsigned long pixel = gcv.foreground; + unsigned long amask = BlackPixelOfScreen (st->xgwa.screen); + unsigned long a = (0xCCCCCCCC & amask); + pixel = (pixel & (~amask)) | a; + + jwxyz_XSetAlphaAllowed (st->dpy, t->gc, True); + XSetForeground (st->dpy, t->gc, pixel); + } +# endif /* HAVE_COCOA */ switch (random() % 11) { case 0: case 1: case 2: case 3: t->draw = draw_star; break; @@ -172,11 +216,19 @@ make_throbber (Display *dpy, Drawable d, int w, int h, unsigned long pixel) default: abort(); break; } + if (t->draw == draw_circle) + t->max_size *= 1.5; + + if (random() % 4) + t->size = t->max_size; + else + t->size = t->thickness, t->speed = -t->speed; + return t; } static int -throb (Display *dpy, Drawable window, struct throbber *t) +throb (struct state *st, Drawable window, struct throbber *t) { t->size += t->speed; if (t->size <= (t->thickness / 2)) @@ -193,180 +245,219 @@ throb (Display *dpy, Drawable window, struct throbber *t) if (t->fuse <= 0) { - XFreeGC (dpy, t->gc); + XFreeGC (st->dpy, t->gc); memset (t, 0, sizeof(*t)); free (t); return -1; } else { - t->draw (dpy, window, t); + t->draw (st, window, t); return 0; } } - -char *progclass = "Deluxe"; - -char *defaults [] = { - ".background: black", - ".foreground: white", - "*delay: 5000", - "*count: 5", - "*thickness: 50", - "*speed: 15", - "*ncolors: 20", - "*nlayers: 0", - "*transparent: False", - "*doubleBuffer: True", -#ifdef HAVE_DOUBLE_BUFFER_EXTENSION - "*useDBE: True", - "*useDBEClear: True", -#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ - 0 -}; - -XrmOptionDescRec options [] = { - { "-delay", ".delay", XrmoptionSepArg, 0 }, - { "-thickness", ".thickness", XrmoptionSepArg, 0 }, - { "-count", ".count", XrmoptionSepArg, 0 }, - { "-ncolors", ".ncolors", XrmoptionSepArg, 0 }, - { "-speed", ".speed", XrmoptionSepArg, 0 }, - { "-transparent", ".transparent", XrmoptionNoArg, "True" }, - { "-opaque", ".transparent", XrmoptionNoArg, "False" }, - { "-db", ".doubleBuffer", XrmoptionNoArg, "True" }, - { "-no-db", ".doubleBuffer", XrmoptionNoArg, "False" }, - { 0, 0, 0, 0 } -}; - -void -screenhack (Display *dpy, Window window) +static void * +deluxe_init (Display *dpy, Window window) { - int count = get_integer_resource ("count", "Integer"); - int delay = get_integer_resource ("delay", "Integer"); - int ncolors = get_integer_resource ("ncolors", "Integer"); - Bool dbuf = get_boolean_resource ("doubleBuffer", "Boolean"); - Bool dbeclear_p = get_boolean_resource ("useDBEClear", "Boolean"); - XColor *colors = 0; + struct state *st = (struct state *) calloc (1, sizeof(*st)); XGCValues gcv; - GC erase_gc = 0; int i; - struct throbber **throbbers; - XWindowAttributes xgwa; - Pixmap b=0, ba=0, bb=0; /* double-buffer to reduce flicker */ -#ifdef HAVE_DOUBLE_BUFFER_EXTENSION - XdbeBackBuffer backb = 0; -#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + st->dpy = dpy; + st->window = window; + st->count = get_integer_resource (st->dpy, "count", "Integer"); + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + st->ncolors = get_integer_resource (st->dpy, "ncolors", "Integer"); + st->dbuf = get_boolean_resource (st->dpy, "doubleBuffer", "Boolean"); + +# ifdef HAVE_DOUBLE_BUFFER_EXTENSION + st->dbeclear_p = get_boolean_resource (st->dpy, "useDBEClear", "Boolean"); +#endif - XGetWindowAttributes (dpy, window, &xgwa); +# ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + st->dbuf = False; +# endif - transparent_p = get_boolean_resource("transparent", "Transparent"); + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); - colors = (XColor *) calloc (sizeof(*colors), ncolors); + st->transparent_p = get_boolean_resource(st->dpy, "transparent", "Transparent"); - if (get_boolean_resource("mono", "Boolean")) + st->colors = (XColor *) calloc (sizeof(*st->colors), st->ncolors); + + if (get_boolean_resource(st->dpy, "mono", "Boolean")) { MONO: - ncolors = 1; - colors[0].pixel = get_pixel_resource("foreground", "Foreground", - dpy, xgwa.colormap); + st->ncolors = 1; + st->colors[0].pixel = get_pixel_resource(st->dpy, st->xgwa.colormap, + "foreground", "Foreground"); } - else if (transparent_p) +#ifndef HAVE_COCOA + else if (st->transparent_p) { - nplanes = get_integer_resource ("planes", "Planes"); - if (nplanes <= 0) - nplanes = (random() % (xgwa.depth-2)) + 2; - - allocate_alpha_colors (xgwa.screen, xgwa.visual, xgwa.colormap, - &nplanes, True, &plane_masks, - &base_pixel); - if (nplanes <= 1) + st->nplanes = get_integer_resource (st->dpy, "planes", "Planes"); + if (st->nplanes <= 0) + st->nplanes = (random() % (st->xgwa.depth-2)) + 2; + + allocate_alpha_colors (st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap, + &st->nplanes, True, &st->plane_masks, + &st->base_pixel); + if (st->nplanes <= 1) { +# if 0 fprintf (stderr, "%s: couldn't allocate any color planes; turning transparency off.\n", progname); - transparent_p = False; +# endif + st->transparent_p = False; goto COLOR; } } +#endif /* !HAVE_COCOA */ else { +#ifndef HAVE_COCOA COLOR: - make_random_colormap (dpy, xgwa.visual, xgwa.colormap, - colors, &ncolors, True, True, 0, True); - if (ncolors < 2) +#endif + make_random_colormap (st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap, + st->colors, &st->ncolors, True, True, 0, True); + if (st->ncolors < 2) goto MONO; } - if (dbuf) + if (st->dbuf) { #ifdef HAVE_DOUBLE_BUFFER_EXTENSION - if (dbeclear_p) - b = xdbe_get_backbuffer (dpy, window, XdbeBackground); + if (st->dbeclear_p) + st->b = xdbe_get_backbuffer (st->dpy, st->window, XdbeBackground); else - b = xdbe_get_backbuffer (dpy, window, XdbeUndefined); - backb = b; + st->b = xdbe_get_backbuffer (st->dpy, st->window, XdbeUndefined); + st->backb = st->b; #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ - if (!b) + if (!st->b) { - ba = XCreatePixmap (dpy, window, xgwa.width, xgwa.height,xgwa.depth); - bb = XCreatePixmap (dpy, window, xgwa.width, xgwa.height,xgwa.depth); - b = ba; + st->ba = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height,st->xgwa.depth); + st->bb = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height,st->xgwa.depth); + st->b = st->ba; } } else { - b = window; + st->b = st->window; } - throbbers = (struct throbber **) calloc (count, sizeof(struct throbber *)); - for (i = 0; i < count; i++) - throbbers[i] = make_throbber (dpy, b, xgwa.width, xgwa.height, - colors[random() % ncolors].pixel); + st->throbbers = (struct throbber **) calloc (st->count, sizeof(struct throbber *)); + for (i = 0; i < st->count; i++) + st->throbbers[i] = make_throbber (st, st->b, st->xgwa.width, st->xgwa.height, + st->colors[random() % st->ncolors].pixel); - gcv.foreground = get_pixel_resource ("background", "Background", - dpy, xgwa.colormap); - erase_gc = XCreateGC (dpy, b, GCForeground, &gcv); + gcv.foreground = get_pixel_resource (st->dpy, st->xgwa.colormap, + "background", "Background"); + st->erase_gc = XCreateGC (st->dpy, st->b, GCForeground, &gcv); - if (ba) XFillRectangle (dpy, ba, erase_gc, 0, 0, xgwa.width, xgwa.height); - if (bb) XFillRectangle (dpy, bb, erase_gc, 0, 0, xgwa.width, xgwa.height); + if (st->ba) XFillRectangle (st->dpy, st->ba, st->erase_gc, 0, 0, st->xgwa.width, st->xgwa.height); + if (st->bb) XFillRectangle (st->dpy, st->bb, st->erase_gc, 0, 0, st->xgwa.width, st->xgwa.height); - while (1) - { - if (!dbeclear_p + return st; +} + +static unsigned long +deluxe_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int i; #ifdef HAVE_DOUBLE_BUFFER_EXTENSION - || !backb + if (!st->dbeclear_p || !st->backb) #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ - ) - XFillRectangle (dpy, b, erase_gc, 0, 0, xgwa.width, xgwa.height); + XFillRectangle (st->dpy, st->b, st->erase_gc, 0, 0, st->xgwa.width, st->xgwa.height); - for (i = 0; i < count; i++) - if (throb (dpy, b, throbbers[i]) < 0) - throbbers[i] = make_throbber (dpy, b, xgwa.width, xgwa.height, - colors[random() % ncolors].pixel); + for (i = 0; i < st->count; i++) + if (throb (st, st->b, st->throbbers[i]) < 0) + st->throbbers[i] = make_throbber (st, st->b, st->xgwa.width, st->xgwa.height, + st->colors[random() % st->ncolors].pixel); #ifdef HAVE_DOUBLE_BUFFER_EXTENSION - if (backb) - { - XdbeSwapInfo info[1]; - info[0].swap_window = window; - info[0].swap_action = (dbeclear_p ? XdbeBackground : XdbeUndefined); - XdbeSwapBuffers (dpy, info, 1); - } - else + if (st->backb) + { + XdbeSwapInfo info[1]; + info[0].swap_window = st->window; + info[0].swap_action = (st->dbeclear_p ? XdbeBackground : XdbeUndefined); + XdbeSwapBuffers (st->dpy, info, 1); + } + else #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ - if (dbuf) - { - XCopyArea (dpy, b, window, erase_gc, 0, 0, - xgwa.width, xgwa.height, 0, 0); - b = (b == ba ? bb : ba); - } + if (st->dbuf) + { + XCopyArea (st->dpy, st->b, st->window, st->erase_gc, 0, 0, + st->xgwa.width, st->xgwa.height, 0, 0); + st->b = (st->b == st->ba ? st->bb : st->ba); + } + + return st->delay; +} - XSync (dpy, False); - screenhack_handle_events (dpy); - if (delay) - usleep (delay); - } +static void +deluxe_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + if (! st->dbuf) { /* #### more complicated if we have a back buffer... */ + int i; + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + XClearWindow (dpy, window); + for (i = 0; i < st->count; i++) + if (st->throbbers[i]) + st->throbbers[i]->fuse = 0; + } +} + +static Bool +deluxe_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +deluxe_free (Display *dpy, Window window, void *closure) +{ } + + +static const char *deluxe_defaults [] = { + ".background: black", + ".foreground: white", + "*delay: 10000", + "*count: 5", + "*thickness: 50", + "*speed: 15", + "*ncolors: 20", + "*transparent: True", + "*doubleBuffer: True", +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + "*useDBE: True", + "*useDBEClear: True", +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ +#ifdef USE_IPHONE + "*ignoreRotation: True", +#endif + 0 +}; + +static XrmOptionDescRec deluxe_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-thickness", ".thickness", XrmoptionSepArg, 0 }, + { "-count", ".count", XrmoptionSepArg, 0 }, + { "-ncolors", ".ncolors", XrmoptionSepArg, 0 }, + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-transparent", ".transparent", XrmoptionNoArg, "True" }, + { "-no-transparent", ".transparent", XrmoptionNoArg, "False" }, + { "-opaque", ".transparent", XrmoptionNoArg, "False" }, + { "-no-opaque", ".transparent", XrmoptionNoArg, "True" }, + { "-db", ".doubleBuffer", XrmoptionNoArg, "True" }, + { "-no-db", ".doubleBuffer", XrmoptionNoArg, "False" }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("Deluxe", deluxe)