X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fblitspin.c;h=0be3c96d2a5648d325391edb6789e4e797b02b61;hb=de460e831dc8578acfa8b72251ab9346c99c1f96;hp=9a72b302d7ccba7d496877a921f85cd3a291a8b9;hpb=b08b6f995f8d5e0ff37d2f627bff3f61dcb75ac5;p=xscreensaver diff --git a/hacks/blitspin.c b/hacks/blitspin.c index 9a72b302..0be3c96d 100644 --- a/hacks/blitspin.c +++ b/hacks/blitspin.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 1992-1996 Jamie Zawinski +/* xscreensaver, Copyright (c) 1992-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 @@ -25,255 +25,330 @@ */ #include "screenhack.h" +#include "xpm-pixmap.h" #include -#ifdef HAVE_XPM -# include -# ifndef PIXEL_ALREADY_TYPEDEFED -# define PIXEL_ALREADY_TYPEDEFED /* Sigh, Xmu/Drawing.h needs this... */ -# endif -#endif +#include "images/som.xbm" -#include +struct state { + Display *dpy; + Window window; + XWindowAttributes xgwa; + int width, height, size; + Bool scale_up; + Pixmap self, temp, mask; + GC SET, CLR, CPY, IOR, AND, XOR; + GC gc; + int delay, delay2; + int duration; + Pixmap bitmap; + unsigned int fg, bg; -#include "default.xbm" + int qwad; /* fuckin' C, man... who needs namespaces? */ + int first_time; + int last_w, last_h; -static Display *dpy; -static Window window; -static unsigned int size; -static Pixmap self, temp, mask; -static GC SET, CLR, CPY, IOR, AND, XOR; -static GC gc; -static int delay, delay2; -static Pixmap bitmap; -static int depth; -static unsigned int fg, bg; + time_t start_time; + Bool loaded_p; + async_load_state *img_loader; +}; -static void rotate(), init (), display (); +static void display (struct state *, Pixmap); +static void blitspin_init_2 (struct state *); -#define copy_all_to(from, xoff, yoff, to, gc) \ - XCopyArea (dpy, (from), (to), (gc), 0, 0, \ - size-(xoff), size-(yoff), (xoff), (yoff)) +#define copy_all_to(from, xoff, yoff, to, gc) \ + XCopyArea (st->dpy, (from), (to), (gc), 0, 0, \ + st->size-(xoff), st->size-(yoff), (xoff), (yoff)) -#define copy_all_from(to, xoff, yoff, from, gc) \ - XCopyArea (dpy, (from), (to), (gc), (xoff), (yoff), \ - size-(xoff), size-(yoff), 0, 0) +#define copy_all_from(to, xoff, yoff, from, gc) \ + XCopyArea (st->dpy, (from), (to), (gc), (xoff), (yoff), \ + st->size-(xoff), st->size-(yoff), 0, 0) -static void -rotate () +static unsigned long +blitspin_draw (Display *dpy, Window window, void *closure) { - int qwad; /* fuckin' C, man... who needs namespaces? */ - XFillRectangle (dpy, mask, CLR, 0, 0, size, size); - XFillRectangle (dpy, mask, SET, 0, 0, size>>1, size>>1); - for (qwad = size>>1; qwad > 0; qwad>>=1) + struct state *st = (struct state *) closure; + int this_delay = st->delay; + + if (st->img_loader) /* still loading */ { - if (delay) usleep (delay); - copy_all_to (mask, 0, 0, temp, CPY); /* 1 */ - copy_all_to (mask, 0, qwad, temp, IOR); /* 2 */ - copy_all_to (self, 0, 0, temp, AND); /* 3 */ - copy_all_to (temp, 0, 0, self, XOR); /* 4 */ - copy_all_from (temp, qwad, 0, self, XOR); /* 5 */ - copy_all_from (self, qwad, 0, self, IOR); /* 6 */ - copy_all_to (temp, qwad, 0, self, XOR); /* 7 */ - copy_all_to (self, 0, 0, temp, CPY); /* 8 */ - copy_all_from (temp, qwad, qwad, self, XOR); /* 9 */ - copy_all_to (mask, 0, 0, temp, AND); /* A */ - copy_all_to (temp, 0, 0, self, XOR); /* B */ - copy_all_to (temp, qwad, qwad, self, XOR); /* C */ - copy_all_from (mask, qwad>>1, qwad>>1, mask, AND); /* D */ - copy_all_to (mask, qwad, 0, mask, IOR); /* E */ - copy_all_to (mask, 0, qwad, mask, IOR); /* F */ - display (self); + st->img_loader = load_image_async_simple (st->img_loader, 0, 0, 0, 0, 0); + + if (!st->img_loader) { /* just finished */ + st->first_time = 0; + st->loaded_p = False; + st->qwad = -1; + st->start_time = time ((time_t) 0); + } + + return this_delay; } -} -static void -read_bitmap (bitmap_name, widthP, heightP) - char *bitmap_name; - int *widthP, *heightP; -{ -#ifdef HAVE_XPM - XpmAttributes xpmattrs; - int result; - xpmattrs.valuemask = 0; - bitmap = 0; - -#ifdef XpmCloseness - xpmattrs.valuemask |= XpmCloseness; - xpmattrs.closeness = 40000; -#endif + if (!st->img_loader && + st->start_time + st->duration < time ((time_t) 0)) { + /* Start it loading, but keep rotating the old image until it arrives. */ + st->img_loader = load_image_async_simple (0, st->xgwa.screen, st->window, + st->bitmap, 0, 0); + } + + if (! st->loaded_p) { + blitspin_init_2 (st); + st->loaded_p = True; + } - result = XpmReadFileToPixmap (dpy, window, bitmap_name, &bitmap, 0, - &xpmattrs); - switch (result) + if (st->qwad == -1) { - case XpmColorError: - fprintf (stderr, "%s: warning: xpm color substitution performed\n", - progname); - /* fall through */ - case XpmSuccess: - *widthP = xpmattrs.width; - *heightP = xpmattrs.height; - break; - case XpmFileInvalid: - case XpmOpenFailed: - bitmap = 0; - break; - case XpmColorFailed: - fprintf (stderr, "%s: xpm: color allocation failed\n", progname); - exit (-1); - case XpmNoMemory: - fprintf (stderr, "%s: xpm: out of memory\n", progname); - exit (-1); - default: - fprintf (stderr, "%s: xpm: unknown error code %d\n", progname, result); - exit (-1); + XFillRectangle (st->dpy, st->mask, st->CLR, 0, 0, st->size, st->size); + XFillRectangle (st->dpy, st->mask, st->SET, 0, 0, st->size>>1, st->size>>1); + st->qwad = st->size>>1; } - if (! bitmap) -#endif + + if (st->first_time) { - int xh, yh; - Pixmap b2; - bitmap = XmuLocateBitmapFile (DefaultScreenOfDisplay (dpy), bitmap_name, - 0, 0, widthP, heightP, &xh, &yh); - if (! bitmap) - { - fprintf (stderr, "%s: couldn't find bitmap %s\n", progname, - bitmap_name); - exit (1); - } - b2 = XmuCreatePixmapFromBitmap (dpy, window, bitmap, *widthP, *heightP, - depth, fg, bg); - XFreePixmap (dpy, bitmap); - bitmap = b2; + st->first_time = 0; + display (st, st->self); + return st->delay2; } + + /* for (st->qwad = st->size>>1; st->qwad > 0; st->qwad>>=1) */ + + copy_all_to (st->mask, 0, 0, st->temp, st->CPY); /* 1 */ + copy_all_to (st->mask, 0, st->qwad, st->temp, st->IOR); /* 2 */ + copy_all_to (st->self, 0, 0, st->temp, st->AND); /* 3 */ + copy_all_to (st->temp, 0, 0, st->self, st->XOR); /* 4 */ + copy_all_from(st->temp, st->qwad, 0, st->self, st->XOR); /* 5 */ + copy_all_from(st->self, st->qwad, 0, st->self, st->IOR); /* 6 */ + copy_all_to (st->temp, st->qwad, 0, st->self, st->XOR); /* 7 */ + copy_all_to (st->self, 0, 0, st->temp, st->CPY); /* 8 */ + copy_all_from(st->temp, st->qwad, st->qwad, st->self,st->XOR);/*9*/ + copy_all_to (st->mask, 0, 0, st->temp, st->AND); /* A */ + copy_all_to (st->temp, 0, 0, st->self, st->XOR); /* B */ + copy_all_to (st->temp, st->qwad, st->qwad, st->self, st->XOR); /* C */ + copy_all_from(st->mask, st->qwad>>1,st->qwad>>1,st->mask,st->AND); /* D */ + copy_all_to (st->mask, st->qwad, 0, st->mask, st->IOR); /* E */ + copy_all_to (st->mask, 0, st->qwad, st->mask, st->IOR); /* F */ + display (st, st->self); + + st->qwad >>= 1; + if (st->qwad == 0) /* done with this round */ + { + st->qwad = -1; + this_delay = st->delay2; + } + + return this_delay; } -static void -init () + +static int +to_pow2(struct state *st, int n, Bool up) { - XWindowAttributes xgwa; - Colormap cmap; - XGCValues gcv; - int width, height; - unsigned int real_size; + /* sizeof(Dimension) == 2. */ + int powers_of_2[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, + 2048, 4096, 8192, 16384, 32768, 65536 }; + int i = 0; + if (n > 65536) st->size = 65536; + while (n >= powers_of_2[i]) i++; + if (n == powers_of_2[i-1]) + return n; + else + return powers_of_2[up ? i : i-1]; +} + +static void * +blitspin_init (Display *d_arg, Window w_arg) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); char *bitmap_name; - int i; - - XGetWindowAttributes (dpy, window, &xgwa); - cmap = xgwa.colormap; - depth = xgwa.depth; - - fg = get_pixel_resource ("foreground", "Foreground", dpy, cmap); - bg = get_pixel_resource ("background", "Background", dpy, cmap); - delay = get_integer_resource ("delay", "Integer"); - delay2 = get_integer_resource ("delay2", "Integer"); - if (delay < 0) delay = 0; - if (delay2 < 0) delay2 = 0; - bitmap_name = get_string_resource ("bitmap", "Bitmap"); + + st->dpy = d_arg; + st->window = w_arg; + + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + + st->fg = get_pixel_resource (st->dpy, st->xgwa.colormap, + "foreground", "Foreground"); + st->bg = get_pixel_resource (st->dpy, st->xgwa.colormap, + "background", "Background"); + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + st->delay2 = get_integer_resource (st->dpy, "delay2", "Integer"); + st->duration = get_integer_resource (st->dpy, "duration", "Seconds"); + if (st->delay < 0) st->delay = 0; + if (st->delay2 < 0) st->delay2 = 0; + if (st->duration < 1) st->duration = 1; + + st->start_time = time ((time_t) 0); + + bitmap_name = get_string_resource (st->dpy, "bitmap", "Bitmap"); if (! bitmap_name || !*bitmap_name) bitmap_name = "(default)"; - if (!strcmp (bitmap_name, "(default)")) + if (!strcasecmp (bitmap_name, "(default)") || + !strcasecmp (bitmap_name, "default")) +# ifdef HAVE_COCOA + /* I don't understand why it doesn't work with color images on OSX. + I guess "kCGBlendModeDarken" is not close enough to being "GXand". + */ + bitmap_name = "(builtin)"; +# else + bitmap_name = "(screen)"; +# endif + + if (!strcasecmp (bitmap_name, "(builtin)") || + !strcasecmp (bitmap_name, "builtin")) + { + st->width = som_width; + st->height = som_height; + st->bitmap = XCreatePixmapFromBitmapData (st->dpy, st->window, + (char *) som_bits, + st->width, st->height, + st->fg, st->bg, + st->xgwa.depth); + st->scale_up = True; /* definitely. */ + } + else if (!strcasecmp (bitmap_name, "(screen)") || + !strcasecmp (bitmap_name, "screen")) { - width = logo_width; - height = logo_height; - bitmap = XCreatePixmapFromBitmapData (dpy, window, (char *) logo_bits, - width, height, fg, bg, depth); + st->bitmap = XCreatePixmap (st->dpy, st->window, + st->xgwa.width, st->xgwa.height, + st->xgwa.depth); + st->width = st->xgwa.width; + st->height = st->xgwa.height; + st->scale_up = True; /* maybe? */ + st->img_loader = load_image_async_simple (0, st->xgwa.screen, st->window, + st->bitmap, 0, 0); } else { - read_bitmap (bitmap_name, &width, &height); + st->bitmap = xpm_file_to_pixmap (st->dpy, st->window, bitmap_name, + &st->width, &st->height, 0); + st->scale_up = True; /* probably? */ } - real_size = (width > height) ? width : height; - - size = real_size; - /* semi-sleazy way of doing (setq size (expt 2 (ceiling (log size 2)))). */ - for (i = 31; i > 0; i--) - if (size & (1<>i)<<(i+1); - self = XCreatePixmap (dpy, window, size, size, depth); - temp = XCreatePixmap (dpy, window, size, size, depth); - mask = XCreatePixmap (dpy, window, size, size, depth); - gcv.foreground = (depth == 1 ? 1 : (~0)); - gcv.function=GXset; SET = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv); - gcv.function=GXclear;CLR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv); - gcv.function=GXcopy; CPY = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv); - gcv.function=GXor; IOR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv); - gcv.function=GXand; AND = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv); - gcv.function=GXxor; XOR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv); - - gcv.foreground = gcv.background = bg; - gc = XCreateGC (dpy, window, GCForeground|GCBackground, &gcv); - /* Clear self to the background color (not to 0, which CLR does.) */ - XFillRectangle (dpy, self, gc, 0, 0, size, size); - XSetForeground (dpy, gc, fg); - - XCopyArea (dpy, bitmap, self, CPY, 0, 0, width, height, - (size - width)>>1, (size - height)>>1); + return st; } + static void -display (pixmap) - Pixmap pixmap; +blitspin_init_2 (struct state *st) { - XWindowAttributes xgwa; - static int last_w = 0, last_h = 0; - XGetWindowAttributes (dpy, window, &xgwa); - if (xgwa.width != last_w || xgwa.height != last_h) + XGCValues gcv; + + /* make it square */ + st->size = (st->width < st->height) ? st->height : st->width; + st->size = to_pow2(st, st->size, st->scale_up); /* round up to power of 2 */ + { /* don't exceed screen size */ + int s = XScreenNumberOfScreen(st->xgwa.screen); + int w = to_pow2(st, XDisplayWidth(st->dpy, s), False); + int h = to_pow2(st, XDisplayHeight(st->dpy, s), False); + if (st->size > w) st->size = w; + if (st->size > h) st->size = h; + } + + st->self = XCreatePixmap (st->dpy, st->window, st->size, st->size, st->xgwa.depth); + st->temp = XCreatePixmap (st->dpy, st->window, st->size, st->size, st->xgwa.depth); + st->mask = XCreatePixmap (st->dpy, st->window, st->size, st->size, st->xgwa.depth); + gcv.foreground = (st->xgwa.depth == 1 ? 1 : (~0)); + gcv.function=GXset; st->SET = XCreateGC(st->dpy,st->self,GCFunction|GCForeground,&gcv); + gcv.function=GXclear;st->CLR = XCreateGC(st->dpy,st->self,GCFunction|GCForeground,&gcv); + gcv.function=GXcopy; st->CPY = XCreateGC(st->dpy,st->self,GCFunction|GCForeground,&gcv); + gcv.function=GXor; st->IOR = XCreateGC(st->dpy,st->self,GCFunction|GCForeground,&gcv); + gcv.function=GXand; st->AND = XCreateGC(st->dpy,st->self,GCFunction|GCForeground,&gcv); + gcv.function=GXxor; st->XOR = XCreateGC(st->dpy,st->self,GCFunction|GCForeground,&gcv); + + gcv.foreground = gcv.background = st->bg; + st->gc = XCreateGC (st->dpy, st->window, GCForeground|GCBackground, &gcv); + /* Clear st->self to the background color (not to 0, which st->CLR does.) */ + XFillRectangle (st->dpy, st->self, st->gc, 0, 0, st->size, st->size); + XSetForeground (st->dpy, st->gc, st->fg); + +#if 0 +#ifdef HAVE_COCOA + jwxyz_XSetAntiAliasing (st->dpy, st->gc, False); + jwxyz_XSetAntiAliasing (st->dpy, st->SET, False); + jwxyz_XSetAntiAliasing (st->dpy, st->CLR, False); + jwxyz_XSetAntiAliasing (st->dpy, st->CPY, False); + jwxyz_XSetAntiAliasing (st->dpy, st->IOR, False); + jwxyz_XSetAntiAliasing (st->dpy, st->AND, False); + jwxyz_XSetAntiAliasing (st->dpy, st->XOR, False); +#endif /* HAVE_COCOA */ +#endif + + XCopyArea (st->dpy, st->bitmap, st->self, st->CPY, 0, 0, + st->width, st->height, + (st->size - st->width) >> 1, + (st->size - st->height) >> 1); +/* XFreePixmap(st->dpy, st->bitmap);*/ + + st->qwad = -1; + st->first_time = 1; +} + +static void +display (struct state *st, Pixmap pixmap) +{ + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + + if (st->xgwa.width != st->last_w || + st->xgwa.height != st->last_h) { - XClearWindow (dpy, window); - last_w = xgwa.width; - last_h = xgwa.height; + XClearWindow (st->dpy, st->window); + st->last_w = st->xgwa.width; + st->last_h = st->xgwa.height; } -#ifdef HAVE_XPM - if (depth != 1) - XCopyArea (dpy, pixmap, window, gc, 0, 0, size, size, - (xgwa.width-size)>>1, (xgwa.height-size)>>1); + if (st->xgwa.depth != 1) + XCopyArea (st->dpy, pixmap, st->window, st->gc, 0, 0, st->size, st->size, + (st->xgwa.width - st->size) >> 1, + (st->xgwa.height - st->size) >> 1); else -#endif - XCopyPlane (dpy, pixmap, window, gc, 0, 0, size, size, - (xgwa.width-size)>>1, (xgwa.height-size)>>1, 1); + XCopyPlane (st->dpy, pixmap, st->window, st->gc, 0, 0, st->size, st->size, + (st->xgwa.width - st->size) >> 1, + (st->xgwa.height - st->size) >> 1, + 1); /* - XDrawRectangle (dpy, window, gc, - ((xgwa.width-size)>>1)-1, ((xgwa.height-size)>>1)-1, - size+2, size+2); + XDrawRectangle (st->dpy, st->window, st->gc, + ((st->xgwa.width - st->size) >> 1) - 1, + ((st->xgwa.height - st->size) >> 1) - 1, + st->size+2, st->size+2); */ - XSync (dpy, True); } - -char *progclass = "BlitSpin"; +static void +blitspin_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +blitspin_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +blitspin_free (Display *dpy, Window window, void *closure) +{ +} -char *defaults [] = { - "BlitSpin.background: black", /* to placate SGI */ - "BlitSpin.foreground: white", + +static const char *blitspin_defaults [] = { + ".background: black", + ".foreground: white", "*delay: 500000", "*delay2: 500000", + "*duration: 120", "*bitmap: (default)", + "*geometry: 512x512", 0 }; -XrmOptionDescRec options [] = { +static XrmOptionDescRec blitspin_options [] = { { "-delay", ".delay", XrmoptionSepArg, 0 }, { "-delay2", ".delay2", XrmoptionSepArg, 0 }, - { "-bitmap", ".bitmap", XrmoptionSepArg, 0 } + { "-duration", ".duration", XrmoptionSepArg, 0 }, + { "-bitmap", ".bitmap", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } }; -int options_size = (sizeof (options) / sizeof (options[0])); -void -screenhack (d, w) - Display *d; - Window w; -{ - dpy = d; - window = w; - init (); - while (1) - { - rotate (); - if (delay2) usleep (delay2); - } -} + +XSCREENSAVER_MODULE ("BlitSpin", blitspin)