X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fblitspin.c;h=a1eaf3138d5daf9cac9398ba4655aefe14ae56d2;hb=40eacb5812ef7c0e3374fb139afbb4f5bc8bbfb5;hp=a532e2967fe71b68208239fa165202d7f439c45e;hpb=0a1527cc01e9894017614b7c36b838b2b6914ba9;p=xscreensaver diff --git a/hacks/blitspin.c b/hacks/blitspin.c index a532e296..a1eaf313 100644 --- a/hacks/blitspin.c +++ b/hacks/blitspin.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 1992 Jamie Zawinski +/* xscreensaver, Copyright (c) 1992-1997, 2003 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 @@ -16,17 +16,20 @@ The input bitmap may be non-square, it is padded and centered with the background color. Another way would be to subdivide - the bitmap into square components and rotate them independently, - but I don't think that would be as interesting looking. + the bitmap into square components and rotate them independently + (and preferably in parallel), but I don't think that would be as + interesting looking. It's too bad almost nothing uses blitter hardware these days, or this might actually win. */ #include "screenhack.h" -#include +#include "xpm-pixmap.h" #include +#include "images/som.xbm" + static Display *dpy; static Window window; static unsigned int size; @@ -35,8 +38,10 @@ 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; -static void rotate(), init (), display (); +static void display (Pixmap); #define copy_all_to(from, xoff, yoff, to, gc) \ XCopyArea (dpy, (from), (to), (gc), 0, 0, \ @@ -47,7 +52,7 @@ static void rotate(), init (), display (); size-(xoff), size-(yoff), 0, 0) static void -rotate () +rotate (void) { int qwad; /* fuckin' C, man... who needs namespaces? */ XFillRectangle (dpy, mask, CLR, 0, 0, size, size); @@ -74,49 +79,107 @@ rotate () } } +static Pixmap +read_screen (Display *dpy, Window window, int *widthP, int *heightP) +{ + Pixmap p; + XWindowAttributes xgwa; + XGCValues gcv; + GC gc; + XGetWindowAttributes (dpy, window, &xgwa); + *widthP = xgwa.width; + *heightP = xgwa.height; + + p = XCreatePixmap(dpy, window, *widthP, *heightP, xgwa.depth); + gcv.function = GXcopy; + gc = XCreateGC (dpy, window, GCFunction, &gcv); + + load_random_image (xgwa.screen, window, p); + + /* Reset the window's background color... */ + XSetWindowBackground (dpy, window, + get_pixel_resource ("background", "Background", + dpy, xgwa.colormap)); + XCopyArea (dpy, p, window, gc, 0, 0, *widthP, *heightP, 0, 0); + XFreeGC (dpy, gc); + + return p; +} + + +static int +to_pow2(int n, Bool up) +{ + /* 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) 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 -init () +init (void) { XWindowAttributes xgwa; Colormap cmap; XGCValues gcv; - int width, height, xh, yh; - unsigned int real_size; + int width, height; char *bitmap_name; - int i; + Bool scale_up; + 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"); - if (! bitmap_name) + if (! bitmap_name || !*bitmap_name) + bitmap_name = "(default)"; + + if (!strcmp (bitmap_name, "(default)")) { - fprintf (stderr, "%s: no bitmap specified\n", progname); - exit (1); + width = som_width; + height = som_height; + bitmap = XCreatePixmapFromBitmapData (dpy, window, (char *) som_bits, + width, height, fg, bg, depth); + scale_up = True; /* definitely. */ } - bitmap = XmuLocateBitmapFile (DefaultScreenOfDisplay (dpy), bitmap_name, - 0, 0, &width, &height, &xh, &yh); - if (! bitmap) + else if (!strcmp (bitmap_name, "(screen)")) { - fprintf (stderr, "%s: couldn't find bitmap %s\n", progname, bitmap_name); - exit (1); + bitmap = read_screen (dpy, window, &width, &height); + scale_up = True; /* maybe? */ } + else + { + bitmap = xpm_file_to_pixmap (dpy, window, bitmap_name, + &width, &height, 0); + scale_up = True; /* probably? */ + } + + size = (width < height) ? height : width; /* make it square */ + size = to_pow2(size, scale_up); /* round up to power of 2 */ + { /* don't exceed screen size */ + int s = XScreenNumberOfScreen(xgwa.screen); + int w = to_pow2(XDisplayWidth(dpy, s), False); + int h = to_pow2(XDisplayHeight(dpy, s), False); + if (size > w) size = w; + if (size > h) size = h; + } - 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, 1); - temp = XCreatePixmap (dpy, window, size, size, 1); - mask = XCreatePixmap (dpy, window, size, size, 1); - gcv.foreground = 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); @@ -124,18 +187,23 @@ init () gcv.function=GXand; AND = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv); gcv.function=GXxor; XOR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv); - XFillRectangle (dpy, self, CLR, 0, 0, size, size); + 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); + XFreePixmap(dpy, bitmap); - gcv.foreground = get_pixel_resource ("foreground", "Foreground", dpy, cmap); - gcv.background = get_pixel_resource ("background", "Background", dpy, cmap); - gc = XCreateGC (dpy, window, GCForeground|GCBackground, &gcv); + display (self); + XSync(dpy, False); + screenhack_handle_events (dpy); } static void -display (pixmap) - Pixmap pixmap; +display (Pixmap pixmap) { XWindowAttributes xgwa; static int last_w = 0, last_h = 0; @@ -146,46 +214,53 @@ display (pixmap) last_w = xgwa.width; last_h = xgwa.height; } - XCopyPlane (dpy, pixmap, window, gc, 0, 0, size, size, - (xgwa.width-size)>>1, (xgwa.height-size)>>1, 1); + if (depth != 1) + XCopyArea (dpy, pixmap, window, gc, 0, 0, size, size, + (xgwa.width-size)>>1, (xgwa.height-size)>>1); + else + XCopyPlane (dpy, pixmap, window, gc, 0, 0, size, size, + (xgwa.width-size)>>1, (xgwa.height-size)>>1, 1); /* XDrawRectangle (dpy, window, gc, ((xgwa.width-size)>>1)-1, ((xgwa.height-size)>>1)-1, size+2, size+2); */ - XSync (dpy, True); + XSync (dpy, False); + screenhack_handle_events (dpy); } char *progclass = "BlitSpin"; char *defaults [] = { - "*background: black", - "*foreground: white", + ".background: black", + ".foreground: white", "*delay: 500000", "*delay2: 500000", - "*bitmap: xlogo64", /* hey, pick something better! */ + "*bitmap: (default)", + "*geometry: 512x512", 0 }; XrmOptionDescRec options [] = { { "-delay", ".delay", XrmoptionSepArg, 0 }, { "-delay2", ".delay2", XrmoptionSepArg, 0 }, - { "-bitmap", ".bitmap", XrmoptionSepArg, 0 } + { "-bitmap", ".bitmap", XrmoptionSepArg, 0 }, + { "-grab-screen", ".bitmap", XrmoptionNoArg, "(screen)" }, + { 0, 0, 0, 0 } }; -int options_size = (sizeof (options) / sizeof (options[0])); void -screenhack (d, w) - Display *d; - Window w; +screenhack (Display *d, Window w) { dpy = d; window = w; init (); + if (delay2) usleep (delay2 * 2); while (1) { rotate (); + screenhack_handle_events (d); if (delay2) usleep (delay2); } }