X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fqix.c;h=04d0928009e09471495460f6e9218c3558180a6c;hb=4ade52359b6eba3621566dac79793a33aa4c915f;hp=e45c795595c0ad6f5b8b49cb45dccd05d4010fdc;hpb=6edc84f12f15860a71430c45e8392a5e4ef8203c;p=xscreensaver diff --git a/hacks/qix.c b/hacks/qix.c index e45c7955..04d09280 100644 --- a/hacks/qix.c +++ b/hacks/qix.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 1992 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 @@ -10,15 +10,19 @@ */ #include "screenhack.h" +#include "alpha.h" #include +#define MAXPOLY 16 +#define SCALE 6 + struct qpoint { int x, y; int dx, dy; }; struct qline { - struct qpoint p1, p2; + struct qpoint *p; XColor color; Bool dead; }; @@ -27,400 +31,491 @@ struct qix { int id; int fp; int nlines; + int npoly; struct qline *lines; }; -static GC draw_gc, erase_gc; -static unsigned int default_fg_pixel; -static int maxx, maxy, max_spread, max_size, color_shift; -static Bool random_p, solid_p, xor_p, transparent_p; -static int delay; -static int count; -static Colormap cmap; -static unsigned long base_pixel; +struct state { + Display *dpy; + Window window; + + GC draw_gc, erase_gc; + unsigned int default_fg_pixel; + long maxx, maxy, max_spread, max_size; + int color_shift; + Bool random_p, solid_p, xor_p, transparent_p, gravity_p; + int delay; + int count; + Colormap cmap; + int npoly; + Bool additive_p; + Bool cmap_p; + + GC *gcs[2]; + + int gtick; + + struct qix **qixes; +}; -static GC *gcs[2]; static void -get_geom (dpy, window) - Display *dpy; - Window window; +get_geom (struct state *st) { XWindowAttributes xgwa; - XGetWindowAttributes (dpy, window, &xgwa); - maxx = xgwa.width; - maxy = xgwa.height; + XGetWindowAttributes (st->dpy, st->window, &xgwa); + st->maxx = ((long)(xgwa.width+1)<maxy = ((long)(xgwa.height+1)<nlines = nlines; qix->lines = (struct qline *) calloc (qix->nlines, sizeof (struct qline)); - - if (!mono_p && !transparent_p) + qix->npoly = st->npoly; + for (i = 0; i < qix->nlines; i++) + qix->lines[i].p = (struct qpoint *) + calloc(qix->npoly, sizeof(struct qpoint)); + +# ifndef HAVE_COCOA + if (!mono_p && !st->transparent_p) +# endif { hsv_to_rgb (random () % 360, frand (1.0), frand (0.5) + 0.5, &qix->lines[0].color.red, &qix->lines[0].color.green, &qix->lines[0].color.blue); - if (!XAllocColor (dpy, cmap, &qix->lines[0].color)) + if (!XAllocColor (st->dpy, st->cmap, &qix->lines[0].color)) { - qix->lines[0].color.pixel = default_fg_pixel; - XQueryColor (dpy, cmap, &qix->lines[0].color); - if (!XAllocColor (dpy, cmap, &qix->lines[0].color)) + qix->lines[0].color.pixel = st->default_fg_pixel; + XQueryColor (st->dpy, st->cmap, &qix->lines[0].color); + if (!XAllocColor (st->dpy, st->cmap, &qix->lines[0].color)) abort (); } } - qix->lines[0].p1.x = random () % maxx; - qix->lines[0].p1.y = random () % maxy; - if (max_size == 0) + + if (st->max_size == 0) { - qix->lines[0].p2.x = random () % maxx; - qix->lines[0].p2.y = random () % maxy; + for (i = 0; i < qix->npoly; i++) + { + qix->lines[0].p[i].x = random () % st->maxx; + qix->lines[0].p[i].y = random () % st->maxy; + } } else { - qix->lines[0].p2.x = qix->lines[0].p1.x + (random () % (max_size/2)); - qix->lines[0].p2.y = qix->lines[0].p1.y + (random () % (max_size/2)); - if (qix->lines[0].p2.x > maxx) qix->lines[0].p2.x = maxx; - if (qix->lines[0].p2.y > maxy) qix->lines[0].p2.y = maxy; + /*assert(qix->npoly == 2);*/ + qix->lines[0].p[0].x = random () % st->maxx; + qix->lines[0].p[0].y = random () % st->maxy; + qix->lines[0].p[1].x = qix->lines[0].p[0].x + (random () % (st->max_size/2)); + qix->lines[0].p[1].y = qix->lines[0].p[0].y + (random () % (st->max_size/2)); + if (qix->lines[0].p[1].x > st->maxx) qix->lines[0].p[1].x = st->maxx; + if (qix->lines[0].p[1].y > st->maxy) qix->lines[0].p[1].y = st->maxy; + } + + for (i = 0; i < qix->npoly; i++) + { + qix->lines[0].p[i].dx = (random () % (st->max_spread + 1)) - (st->max_spread /2); + qix->lines[0].p[i].dy = (random () % (st->max_spread + 1)) - (st->max_spread /2); } - qix->lines[0].p1.dx = (random () % (max_spread + 1)) - (max_spread / 2); - qix->lines[0].p1.dy = (random () % (max_spread + 1)) - (max_spread / 2); - qix->lines[0].p2.dx = (random () % (max_spread + 1)) - (max_spread / 2); - qix->lines[0].p2.dy = (random () % (max_spread + 1)) - (max_spread / 2); qix->lines[0].dead = True; + for (i = 1; i < qix->nlines; i++) { - qix->lines[i] = qix->lines[0]; - if (!mono_p && !transparent_p) - if (!XAllocColor (dpy, cmap, &qix->lines[i].color)) + for(j=0; jnpoly; j++) + qix->lines[i].p[j] = qix->lines[0].p[j]; + qix->lines[i].color = qix->lines[0].color; + qix->lines[i].dead = qix->lines[0].dead; + +# ifndef HAVE_COCOA + if (!mono_p && !st->transparent_p) +# endif + if (!XAllocColor (st->dpy, st->cmap, &qix->lines[i].color)) abort (); } return qix; } -/* I don't believe this fucking language doesn't have builtin exponentiation. - I further can't believe that the fucking ^ character means fucking XOR!! */ -static int i_exp(i,j) - int i, j; -{ - int k = 1; - while (j--) k *= i; - return k; -} - - -static void -merge_colors (argc, argv, into_color, mask, increment_p) - int argc; - XColor **argv; - XColor *into_color; - int mask; - Bool increment_p; -{ - int j; - *into_color = *argv [0]; - into_color->pixel |= mask; -#define SHORT_INC(x,y) (x = ((((x)+(y)) > 0xFFFF) ? 0xFFFF : ((x)+(y)))) -#define SHORT_DEC(x,y) (x = ((((x)-(y)) < 0) ? 0 : ((x)-(y)))) - for (j = 1; j < argc; j++) - if (increment_p) - { - SHORT_INC (into_color->red, argv[j]->red); - SHORT_INC (into_color->green, argv[j]->green); - SHORT_INC (into_color->blue, argv[j]->blue); - } - else - { - SHORT_DEC (into_color->red, argv[j]->red); - SHORT_DEC (into_color->green, argv[j]->green); - SHORT_DEC (into_color->blue, argv[j]->blue); - } -#undef SHORT_INC -#undef SHORT_DEC -} -/* fill in all the permutations of colors that XAllocColorCells() has - allocated for us. Thanks Ron, you're an additive kind of guy. */ -static void -permute_colors (pcolors, colors, count, plane_masks, increment_p) - XColor *pcolors, *colors; - int count; - unsigned long *plane_masks; - Bool increment_p; -{ - int out = 0; - int max = i_exp (2, count); - if (count > 31) abort (); - for (out = 1; out < max; out++) - { - XColor *argv [32]; - int this_mask = 0; - int argc = 0; - int bit; - for (bit = 0; bit < 32; bit++) - if (out & (1<dpy = dpy; + st->window = window; + XGetWindowAttributes (st->dpy, st->window, &xgwa); + st->cmap = xgwa.colormap; + st->count = get_integer_resource (st->dpy, "count", "Integer"); + if (st->count <= 0) st->count = 1; + nlines = get_integer_resource (st->dpy, "segments", "Integer"); if (nlines <= 0) nlines = 20; - get_geom (dpy, window); - max_spread = get_integer_resource ("spread", "Integer"); - if (max_spread <= 0) max_spread = 10; - max_size = get_integer_resource ("size", "Integer"); - if (max_size < 0) max_size = 0; - random_p = get_boolean_resource ("random", "Boolean"); - solid_p = get_boolean_resource ("solid", "Boolean"); - xor_p = get_boolean_resource ("xor", "Boolean"); - transparent_p = get_boolean_resource ("transparent", "Boolean"); - delay = get_integer_resource ("delay", "Integer"); - color_shift = get_integer_resource ("colorShift", "Integer"); - if (color_shift < 0 || color_shift >= 360) color_shift = 5; - if (delay < 0) delay = 0; - - if (count == 1 && transparent_p) - transparent_p = False; /* it's a no-op */ - - if (transparent_p && CellsOfScreen (DefaultScreenOfDisplay (dpy)) <= 2) + st->npoly = get_integer_resource(st->dpy, "poly", "Integer"); + if (st->npoly <= 2) st->npoly = 2; + if (st->npoly > MAXPOLY) st->npoly = MAXPOLY; + get_geom (st); + st->max_spread = get_integer_resource (st->dpy, "spread", "Integer"); + if (st->max_spread <= 0) st->max_spread = 10; + st->max_spread <<= SCALE; + st->max_size = get_integer_resource (st->dpy, "size", "Integer"); + if (st->max_size < 0) st->max_size = 0; + st->max_size <<= SCALE; + st->random_p = get_boolean_resource (st->dpy, "random", "Boolean"); + st->solid_p = get_boolean_resource (st->dpy, "solid", "Boolean"); + st->xor_p = get_boolean_resource (st->dpy, "xor", "Boolean"); + st->transparent_p = get_boolean_resource (st->dpy, "transparent", "Boolean"); + st->gravity_p = get_boolean_resource(st->dpy, "gravity", "Boolean"); + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + st->color_shift = get_integer_resource (st->dpy, "colorShift", "Integer"); + if (st->color_shift < 0 || st->color_shift >= 360) st->color_shift = 5; + if (st->delay < 0) st->delay = 0; + + /* Clear up ambiguities regarding npoly */ + if (st->solid_p) + { + if (st->npoly != 2) + fprintf(stderr, "%s: Can't have -solid and -poly; using -poly 2\n", + progname); + st->npoly = 2; + } + if (st->npoly > 2) + { + if (st->max_size) + fprintf(stderr, "%s: Can't have -poly and -size; using -size 0\n", + progname); + st->max_size = 0; + } + + if (st->count == 1 && st->transparent_p) + st->transparent_p = False; /* it's a no-op */ + + if (st->transparent_p && CellsOfScreen (DefaultScreenOfDisplay (st->dpy)) <= 2) { fprintf (stderr, "%s: -transparent only works on color displays.\n", progname); - transparent_p = False; + st->transparent_p = False; } - if (xor_p && !transparent_p) + if (st->xor_p && !st->transparent_p) mono_p = True; - gcs[0] = gcs[1] = 0; - gcv.foreground = default_fg_pixel = - get_pixel_resource ("foreground", "Foreground", dpy, cmap); + st->gcs[0] = st->gcs[1] = 0; + gcv.foreground = st->default_fg_pixel = + get_pixel_resource (st->dpy, st->cmap, "foreground", "Foreground"); - if (transparent_p) - { - Bool increment_p = get_boolean_resource ("additive", "Boolean"); - unsigned long plane_masks [32]; - XColor *pcolors, *colors; - int nplanes = count; - int i, total_colors; + st->additive_p = get_boolean_resource (st->dpy, "additive", "Boolean"); + st->cmap_p = has_writable_cells (xgwa.screen, xgwa.visual); - /* permutations would be harder if the number of planes didn't fit - in an int. Who has >32-bit displays anyway... */ - if (nplanes > 31) nplanes = 31; +# ifndef HAVE_COCOA + if (st->transparent_p) + { + unsigned long *plane_masks = 0; + unsigned long base_pixel; + int nplanes = st->count; + int i; - while (nplanes > 1 && - !XAllocColorCells (dpy, cmap, False, plane_masks, nplanes, - &base_pixel, 1)) - nplanes--; + allocate_alpha_colors (xgwa.screen, xgwa.visual, st->cmap, + &nplanes, st->additive_p, &plane_masks, + &base_pixel); if (nplanes <= 1) { fprintf (stderr, "%s: couldn't allocate any color planes; turning -transparent off.\n", progname); - transparent_p = False; - if (xor_p) + st->transparent_p = False; + if (st->xor_p) goto NON_TRANSPARENT_XOR; else goto NON_TRANSPARENT; } - else if (nplanes != count) + else if (nplanes != st->count) { fprintf (stderr, "%s: only allocated %d color planes (instead of %d).\n", - progname, nplanes, count); - count = nplanes; + progname, nplanes, st->count); + st->count = nplanes; } - gcs[0] = (GC *) malloc (count * sizeof (GC)); - gcs[1] = xor_p ? gcs[0] : (GC *) malloc (count * sizeof (GC)); - total_colors = i_exp (2, count); - pcolors = (XColor *) calloc (count, sizeof (XColor)); - colors = (XColor *) calloc (total_colors, sizeof (XColor)); - for (i = 0; i < count; i++) + st->gcs[0] = (GC *) malloc (st->count * sizeof (GC)); + st->gcs[1] = (st->xor_p + ? st->gcs[0] + : (GC *) malloc (st->count * sizeof (GC))); + + for (i = 0; i < st->count; i++) { gcv.plane_mask = plane_masks [i]; gcv.foreground = ~0; - if (xor_p) + +/* argh, I'm not sure how to make "-subtractive" work in truecolor... + if (!cmap_p && !additive_p) + gcv.function = GXclear; + */ + + if (st->xor_p) { gcv.function = GXxor; - gcs [0][i] = XCreateGC (dpy, window, - GCForeground|GCFunction|GCPlaneMask, - &gcv); + st->gcs [0][i] = XCreateGC (st->dpy, st->window, + GCForeground|GCFunction|GCPlaneMask, + &gcv); } else { - gcs [0][i] = XCreateGC (dpy, window, GCForeground|GCPlaneMask, - &gcv); + st->gcs [0][i] = XCreateGC (st->dpy, st->window, + GCForeground|GCPlaneMask, + &gcv); gcv.foreground = 0; - gcs [1][i] = XCreateGC (dpy, window, GCForeground|GCPlaneMask, - &gcv); + st->gcs [1][i] = XCreateGC (st->dpy, st->window, + GCForeground|GCPlaneMask, + &gcv); +# ifdef HAVE_COCOA + /* jwxyz_XSetAntiAliasing (st->dpy, st->gcs [0][i], False); + jwxyz_XSetAntiAliasing (st->dpy, st->gcs [1][i], False); */ + if (st->transparent_p) + { + jwxyz_XSetAlphaAllowed (dpy, st->gcs [0][i], True); + jwxyz_XSetAlphaAllowed (dpy, st->gcs [1][i], True); + } +# endif /* HAVE_COCOA */ } + } - /* pick the "primary" (not in that sense) colors. - If we are in subtractive mode, pick higher intensities. */ - hsv_to_rgb (random () % 360, frand (1.0), - frand (0.5) + (increment_p ? 0.2 : 0.5), - &pcolors[i].red, &pcolors[i].green, &pcolors[i].blue); + if (plane_masks) + free (plane_masks); - pcolors [i].flags = DoRed | DoGreen | DoBlue; - pcolors [i].pixel = base_pixel | plane_masks [i]; - } - permute_colors (pcolors, colors, count, plane_masks, increment_p); - /* clone the default background of the window into our "base" pixel */ - colors [total_colors - 1].pixel = - get_pixel_resource ("background", "Background", dpy, cmap); - XQueryColor (dpy, cmap, &colors [total_colors - 1]); - colors [total_colors - 1].pixel = base_pixel; - XStoreColors (dpy, cmap, colors, total_colors); - XSetWindowBackground (dpy, window, base_pixel); - XClearWindow (dpy, window); + XSetWindowBackground (st->dpy, st->window, base_pixel); + XClearWindow (st->dpy, st->window); } - else if (xor_p) + else +#endif /* !HAVE_COCOA */ + if (st->xor_p) { +#ifndef HAVE_COCOA NON_TRANSPARENT_XOR: +#endif gcv.function = GXxor; gcv.foreground = - (default_fg_pixel ^ get_pixel_resource ("background", "Background", - dpy, cmap)); - draw_gc = erase_gc = XCreateGC(dpy,window,GCForeground|GCFunction,&gcv); + (st->default_fg_pixel /* ^ get_pixel_resource (st->dpy, st->cmap, + "background", "Background")*/); + st->draw_gc = st->erase_gc = XCreateGC(st->dpy,st->window,GCForeground|GCFunction,&gcv); } else { +#ifndef HAVE_COCOA NON_TRANSPARENT: - draw_gc = XCreateGC (dpy, window, GCForeground, &gcv); - gcv.foreground = get_pixel_resource ("background", "Background", - dpy, cmap); - erase_gc = XCreateGC (dpy, window, GCForeground, &gcv); +#endif + st->draw_gc = XCreateGC (st->dpy, st->window, GCForeground, &gcv); + gcv.foreground = get_pixel_resource (st->dpy, st->cmap, + "background", "Background"); + st->erase_gc = XCreateGC (st->dpy, st->window, GCForeground, &gcv); } - qixes = (struct qix **) malloc ((count + 1) * sizeof (struct qix *)); - qixes [count] = 0; - while (count--) +#ifdef HAVE_COCOA + if (st->transparent_p) + jwxyz_XSetAlphaAllowed (dpy, st->draw_gc, True); +#endif + + st->qixes = (struct qix **) malloc ((st->count + 1) * sizeof (struct qix *)); + st->qixes [st->count] = 0; + while (st->count--) { - qixes [count] = init_one_qix (dpy, window, nlines); - qixes [count]->id = count; + st->qixes [st->count] = init_one_qix (st, nlines); + st->qixes [st->count]->id = st->count; } - return qixes; + +# ifdef HAVE_COCOA + /* line-mode leaves turds without this. */ + jwxyz_XSetAntiAliasing (st->dpy, st->erase_gc, False); + jwxyz_XSetAntiAliasing (st->dpy, st->draw_gc, False); +# endif + + return st; } static void -free_qline (dpy, window, cmap, qline, prev, qix) - Display *dpy; - Window window; - Colormap cmap; - struct qline *qline, *prev; - struct qix *qix; +free_qline (struct state *st, + struct qline *qline, + struct qline *prev, + struct qix *qix) { + int i; if (qline->dead || !prev) ; - else if (solid_p) + else if (st->solid_p) { XPoint points [4]; - points [0].x = qline->p1.x; points [0].y = qline->p1.y; - points [1].x = qline->p2.x; points [1].y = qline->p2.y; - points [2].x = prev->p2.x; points [2].y = prev->p2.y; - points [3].x = prev->p1.x; points [3].y = prev->p1.y; - XFillPolygon (dpy, window, (transparent_p ? gcs[1][qix->id] : erase_gc), + /*assert(qix->npoly == 2);*/ + points [0].x = qline->p[0].x >> SCALE; + points [0].y = qline->p[0].y >> SCALE; + points [1].x = qline->p[1].x >> SCALE; + points [1].y = qline->p[1].y >> SCALE; + points [2].x = prev->p[1].x >> SCALE; + points [2].y = prev->p[1].y >> SCALE; + points [3].x = prev->p[0].x >> SCALE; + points [3].y = prev->p[0].y >> SCALE; + XFillPolygon (st->dpy, st->window, + (st->transparent_p && st->gcs[1] + ? st->gcs[1][qix->id] + : st->erase_gc), points, 4, Complex, CoordModeOrigin); } else - XDrawLine (dpy, window, (transparent_p ? gcs[1][qix->id] : erase_gc), - qline->p1.x, qline->p1.y, qline->p2.x, qline->p2.y); + { + /* XDrawLine (dpy, window, (transparent_p ? gcs[1][qix->id] : erase_gc), + qline->p1.x, qline->p1.y, qline->p2.x, qline->p2.y);*/ + XPoint points[MAXPOLY+1]; + for(i = 0; i < qix->npoly; i++) + { + points[i].x = qline->p[i].x >> SCALE; + points[i].y = qline->p[i].y >> SCALE; + } + points[qix->npoly] = points[0]; + XDrawLines(st->dpy, st->window, + (st->transparent_p && st->gcs[1] + ? st->gcs[1][qix->id] + : st->erase_gc), + points, qix->npoly+1, CoordModeOrigin); + } - if (!mono_p && !transparent_p) - XFreeColors (dpy, cmap, &qline->color.pixel, 1, 0); + if (!mono_p && !st->transparent_p) + XFreeColors (st->dpy, st->cmap, &qline->color.pixel, 1, 0); qline->dead = True; } static void -add_qline (dpy, window, cmap, qline, prev_qline, qix) - Display *dpy; - Window window; - Colormap cmap; - struct qline *qline, *prev_qline; - struct qix *qix; +add_qline (struct state *st, + struct qline *qline, + struct qline *prev_qline, + struct qix *qix) { - *qline = *prev_qline; + int i; + + for(i=0; inpoly; i++) + qline->p[i] = prev_qline->p[i]; + qline->color = prev_qline->color; + qline->dead = prev_qline->dead; #define wiggle(point,delta,max) \ - if (random_p) delta += (random () % 3) - 1; \ - if (delta > max_spread) delta = max_spread; \ - else if (delta < -max_spread) delta = -max_spread; \ + if (st->random_p) delta += (random () % (1 << (SCALE+1))) - (1 << SCALE); \ + if (delta > st->max_spread) delta = st->max_spread; \ + else if (delta < -st->max_spread) delta = -st->max_spread; \ point += delta; \ if (point < 0) point = 0, delta = -delta, point += delta<<1; \ else if (point > max) point = max, delta = -delta, point += delta<<1; - - wiggle (qline->p1.x, qline->p1.dx, maxx); - wiggle (qline->p1.y, qline->p1.dy, maxy); - wiggle (qline->p2.x, qline->p2.dx, maxx); - wiggle (qline->p2.y, qline->p2.dy, maxy); - if (max_size) + if (st->gravity_p) + for(i=0; inpoly; i++) + qline->p[i].dy += 3; + + for (i = 0; i < qix->npoly; i++) + { + wiggle (qline->p[i].x, qline->p[i].dx, st->maxx); + wiggle (qline->p[i].y, qline->p[i].dy, st->maxy); + } + + if (st->max_size) { - if (qline->p1.x - qline->p2.x > max_size) - qline->p1.x = qline->p2.x + max_size - - (random_p ? random() % max_spread : 0); - else if (qline->p2.x - qline->p1.x > max_size) - qline->p2.x = qline->p1.x + max_size - - (random_p ? random() % max_spread : 0); - if (qline->p1.y - qline->p2.y > max_size) - qline->p1.y = qline->p2.y + max_size - - (random_p ? random() % max_spread : 0); - else if (qline->p2.y - qline->p1.y > max_size) - qline->p2.y = qline->p1.y + max_size - - (random_p ? random() % max_spread : 0); + /*assert(qix->npoly == 2);*/ + if (qline->p[0].x - qline->p[1].x > st->max_size) + qline->p[0].x = qline->p[1].x + st->max_size + - (st->random_p ? random() % st->max_spread : 0); + else if (qline->p[1].x - qline->p[0].x > st->max_size) + qline->p[1].x = qline->p[0].x + st->max_size + - (st->random_p ? random() % st->max_spread : 0); + if (qline->p[0].y - qline->p[1].y > st->max_size) + qline->p[0].y = qline->p[1].y + st->max_size + - (st->random_p ? random() % st->max_spread : 0); + else if (qline->p[1].y - qline->p[0].y > st->max_size) + qline->p[1].y = qline->p[0].y + st->max_size + - (st->random_p ? random() % st->max_spread : 0); } - if (!mono_p && !transparent_p) +#ifndef HAVE_COCOA + if (!mono_p && !st->transparent_p) +#endif { - cycle_hue (&qline->color, color_shift); + XColor desired; + + int h; + double s, v; + rgb_to_hsv (qline->color.red, qline->color.green, qline->color.blue, + &h, &s, &v); + h = (h + st->color_shift) % 360; + hsv_to_rgb (h, s, v, + &qline->color.red, &qline->color.green, &qline->color.blue); + qline->color.flags = DoRed | DoGreen | DoBlue; - if (!XAllocColor (dpy, cmap, &qline->color)) + desired = qline->color; + if (XAllocColor (st->dpy, st->cmap, &qline->color)) + { + /* XAllocColor returns the actual RGB that the hardware let us + allocate. Restore the requested values into the XColor struct + so that limited-resolution hardware doesn't cause the cycle to + get "stuck". */ + qline->color.red = desired.red; + qline->color.green = desired.green; + qline->color.blue = desired.blue; + } + else { qline->color = prev_qline->color; - if (!XAllocColor (dpy, cmap, &qline->color)) + if (!XAllocColor (st->dpy, st->cmap, &qline->color)) abort (); /* same color should work */ } - XSetForeground (dpy, draw_gc, qline->color.pixel); + +# ifdef HAVE_COCOA + if (st->transparent_p) + { + /* give a non-opaque alpha to the color */ + unsigned long pixel = qline->color.pixel; + unsigned long amask = BlackPixelOfScreen (0); + unsigned long a = (0xBBBBBBBB & amask); + pixel = (pixel & (~amask)) | a; + qline->color.pixel = pixel; + } +# endif /* HAVE_COCOA */ + + XSetForeground (st->dpy, st->draw_gc, qline->color.pixel); + } + if (! st->solid_p) + { + /* XDrawLine (dpy, window, (transparent_p ? gcs[0][qix->id] : draw_gc), + qline->p1.x, qline->p1.y, qline->p2.x, qline->p2.y);*/ + XPoint points[MAXPOLY+1]; + for (i = 0; i < qix->npoly; i++) + { + points[i].x = qline->p[i].x >> SCALE; + points[i].y = qline->p[i].y >> SCALE; + } + points[qix->npoly] = points[0]; + XDrawLines(st->dpy, st->window, + (st->transparent_p && st->gcs[0] + ? st->gcs[0][qix->id] + : st->draw_gc), + points, qix->npoly+1, CoordModeOrigin); } - if (! solid_p) - XDrawLine (dpy, window, (transparent_p ? gcs[0][qix->id] : draw_gc), - qline->p1.x, qline->p1.y, qline->p2.x, qline->p2.y); else if (!prev_qline->dead) { XPoint points [4]; - points [0].x = qline->p1.x; points [0].y = qline->p1.y; - points [1].x = qline->p2.x; points [1].y = qline->p2.y; - points [2].x = prev_qline->p2.x; points [2].y = prev_qline->p2.y; - points [3].x = prev_qline->p1.x; points [3].y = prev_qline->p1.y; - XFillPolygon (dpy, window, (transparent_p ? gcs[0][qix->id] : draw_gc), + points [0].x = qline->p[0].x >> SCALE; + points [0].y = qline->p[0].y >> SCALE; + points [1].x = qline->p[1].x >> SCALE; + points [1].y = qline->p[1].y >> SCALE; + points [2].x = prev_qline->p[1].x >> SCALE; + points [2].y = prev_qline->p[1].y >> SCALE; + points [3].x = prev_qline->p[0].x >> SCALE; + points [3].y = prev_qline->p[0].y >> SCALE; + XFillPolygon (st->dpy, st->window, + (st->transparent_p && st->gcs[0] + ? st->gcs[0][qix->id] + : st->draw_gc), points, 4, Complex, CoordModeOrigin); } @@ -428,46 +523,85 @@ add_qline (dpy, window, cmap, qline, prev_qline, qix) } static void -qix1 (dpy, window, qix) - Display *dpy; - Window window; - struct qix *qix; +qix1 (struct state *st, struct qix *qix) { int ofp = qix->fp - 1; - static int gtick = 0; - if (gtick++ == 500) - get_geom (dpy, window), gtick = 0; if (ofp < 0) ofp = qix->nlines - 1; - free_qline (dpy, window, cmap, &qix->lines [qix->fp], + if (st->gtick++ == 500) + get_geom (st), st->gtick = 0; + free_qline (st, &qix->lines [qix->fp], &qix->lines[(qix->fp + 1) % qix->nlines], qix); - add_qline (dpy, window, cmap, &qix->lines[qix->fp], &qix->lines[ofp], qix); + add_qline (st, &qix->lines[qix->fp], &qix->lines[ofp], qix); if ((++qix->fp) >= qix->nlines) qix->fp = 0; } - -char *progclass = "Qix"; -char *defaults [] = { - "Qix.background: black", /* to placate SGI */ - "Qix.foreground: white", - "*count: 1", - "*segments: 50", +static unsigned long +qix_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + struct qix **q1 = st->qixes; + struct qix **qn; + for (qn = q1; *qn; qn++) + qix1 (st, *qn); + return st->delay; +} + +static void +qix_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + get_geom (st); +} + +static Bool +qix_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +qix_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + if (st->gcs[0]) + free (st->gcs[0]); + if (st->gcs[1] && st->gcs[0] != st->gcs[1]) + free (st->gcs[1]); + free (st->qixes); + free (st); +} + + +static const char *qix_defaults [] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*count: 4", + "*segments: 250", + "*poly: 2", "*spread: 8", - "*size: 0", + "*size: 200", "*colorShift: 3", - "*solid: false", + "*solid: true", "*delay: 10000", - "*random: true", + "*random: false", "*xor: false", - "*transparent:false", + "*transparent:true", + "*gravity: false", "*additive: true", +#ifdef USE_IPHONE + "*ignoreRotation: True", +#endif 0 }; -XrmOptionDescRec options [] = { +static XrmOptionDescRec qix_options [] = { { "-count", ".count", XrmoptionSepArg, 0 }, { "-segments", ".segments", XrmoptionSepArg, 0 }, + { "-poly", ".poly", XrmoptionSepArg, 0 }, { "-spread", ".spread", XrmoptionSepArg, 0 }, { "-size", ".size", XrmoptionSepArg, 0 }, { "-delay", ".delay", XrmoptionSepArg, 0 }, @@ -480,23 +614,11 @@ XrmOptionDescRec options [] = { { "-no-xor", ".xor", XrmoptionNoArg, "false" }, { "-transparent", ".transparent", XrmoptionNoArg, "true" }, { "-non-transparent", ".transparent", XrmoptionNoArg, "false" }, + { "-gravity", ".gravity", XrmoptionNoArg, "true" }, + { "-no-gravity", ".gravity", XrmoptionNoArg, "false" }, { "-additive", ".additive", XrmoptionNoArg, "true" }, { "-subtractive", ".additive", XrmoptionNoArg, "false" }, + { 0, 0, 0, 0 } }; -int options_size = (sizeof (options) / sizeof (options[0])); -void -screenhack (dpy, window) - Display *dpy; - Window window; -{ - struct qix **q1 = init_qix (dpy, window); - struct qix **qn; - while (1) - for (qn = q1; *qn; qn++) - { - qix1 (dpy, window, *qn); - XSync (dpy, True); - if (delay) usleep (delay); - } -} +XSCREENSAVER_MODULE ("Qix", qix)