X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fqix.c;h=c86bf646265c5e8b37481ea40389de9e15ce292f;hb=c6b273ef7292ba10943694df1656b05203d7b62f;hp=d6146bb06c06ab2cbbf2bf811160601cf9c40ab2;hpb=88134d551a9911995c013c5ed06a32c2b1044b85;p=xscreensaver diff --git a/hacks/qix.c b/hacks/qix.c index d6146bb0..c86bf646 100644 --- a/hacks/qix.c +++ b/hacks/qix.c @@ -1,4 +1,5 @@ -/* xscreensaver, Copyright (c) 1992 Jamie Zawinski +/* xscreensaver, Copyright (c) 1992, 1995, 1996, 1997 + * 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 +11,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,42 +32,43 @@ 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 long maxx, maxy, max_spread, max_size; +static int color_shift; +static Bool random_p, solid_p, xor_p, transparent_p, gravity_p; static int delay; static int count; static Colormap cmap; -static unsigned long base_pixel; +static int npoly; static GC *gcs[2]; static void -get_geom (dpy, window) - Display *dpy; - Window window; +get_geom (Display *dpy, Window window) { XWindowAttributes xgwa; XGetWindowAttributes (dpy, window, &xgwa); - maxx = xgwa.width; - maxy = xgwa.height; + maxx = ((long)(xgwa.width+1)<nlines = nlines; qix->lines = (struct qline *) calloc (qix->nlines, sizeof (struct qline)); - + qix->npoly = npoly; + for (i = 0; i < qix->nlines; i++) + qix->lines[i].p = (struct qpoint *) + calloc(qix->npoly, sizeof(struct qpoint)); + if (!mono_p && !transparent_p) { hsv_to_rgb (random () % 360, frand (1.0), frand (0.5) + 0.5, @@ -76,28 +82,40 @@ init_one_qix (dpy, window, nlines) abort (); } } - qix->lines[0].p1.x = random () % maxx; - qix->lines[0].p1.y = random () % maxy; + if (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 () % maxx; + qix->lines[0].p[i].y = random () % 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 () % maxx; + qix->lines[0].p[0].y = random () % maxy; + qix->lines[0].p[1].x = qix->lines[0].p[0].x + (random () % (max_size/2)); + qix->lines[0].p[1].y = qix->lines[0].p[0].y + (random () % (max_size/2)); + if (qix->lines[0].p[1].x > maxx) qix->lines[0].p[1].x = maxx; + if (qix->lines[0].p[1].y > maxy) qix->lines[0].p[1].y = maxy; + } + + for (i = 0; i < qix->npoly; i++) + { + qix->lines[0].p[i].dx = (random () % (max_spread + 1)) - (max_spread /2); + qix->lines[0].p[i].dy = (random () % (max_spread + 1)) - (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]; + 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; + if (!mono_p && !transparent_p) if (!XAllocColor (dpy, cmap, &qix->lines[i].color)) abort (); @@ -105,80 +123,11 @@ init_one_qix (dpy, window, nlines) 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< MAXPOLY) npoly = MAXPOLY; get_geom (dpy, window); max_spread = get_integer_resource ("spread", "Integer"); if (max_spread <= 0) max_spread = 10; + max_spread <<= SCALE; max_size = get_integer_resource ("size", "Integer"); if (max_size < 0) max_size = 0; + max_size <<= SCALE; 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"); + gravity_p = get_boolean_resource("gravity", "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; + /* Clear up ambiguities regarding npoly */ + if (solid_p) + { + if (npoly != 2) + fprintf(stderr, "%s: Can't have -solid and -poly; using -poly 2\n", + progname); + npoly = 2; + } + if (npoly > 2) + { + if (max_size) + fprintf(stderr, "%s: Can't have -poly and -size; using -size 0\n", + progname); + max_size = 0; + } + if (count == 1 && transparent_p) transparent_p = False; /* it's a no-op */ @@ -223,20 +194,14 @@ init_qix (dpy, window) if (transparent_p) { - Bool increment_p = get_boolean_resource ("additive", "Boolean"); - unsigned long plane_masks [32]; - XColor *pcolors, *colors; + Bool additive_p = get_boolean_resource ("additive", "Boolean"); + unsigned long *plane_masks = 0; + unsigned long base_pixel; int nplanes = count; - int i, total_colors; + int i; - /* 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; - - while (nplanes > 1 && - !XAllocColorCells (dpy, cmap, False, plane_masks, nplanes, - &base_pixel, 1)) - nplanes--; + allocate_alpha_colors (dpy, cmap, &nplanes, additive_p, &plane_masks, + &base_pixel); if (nplanes <= 1) { @@ -259,9 +224,8 @@ init_qix (dpy, window) 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++) { gcv.plane_mask = plane_masks [i]; @@ -281,23 +245,8 @@ init_qix (dpy, window) gcs [1][i] = XCreateGC (dpy, window, GCForeground|GCPlaneMask, &gcv); } - - /* 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); - - 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); } @@ -323,35 +272,50 @@ init_qix (dpy, window) qixes [count] = 0; while (count--) { - qixes [count] = init_one_qix (dpy, window, nlines); + qixes [count] = init_one_qix (dpy, window, nlines, npoly); qixes [count]->id = count; } return qixes; } 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 (Display *dpy, Window window, Colormap cmap, + struct qline *qline, + struct qline *prev, + struct qix *qix) { + int i; if (qline->dead || !prev) ; else if (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; + /*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 (dpy, window, (transparent_p ? gcs[1][qix->id] : 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);*/ + static 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(dpy, window, (transparent_p ? gcs[1][qix->id] : erase_gc), + points, qix->npoly+1, CoordModeOrigin); + } if (!mono_p && !transparent_p) XFreeColors (dpy, cmap, &qline->color.pixel, 1, 0); @@ -360,49 +324,78 @@ free_qline (dpy, window, cmap, qline, prev, qix) } 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 (Display *dpy, Window window, Colormap cmap, + 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 (random_p) delta += (random () % (1 << (SCALE+1))) - (1 << SCALE); \ if (delta > max_spread) delta = max_spread; \ else if (delta < -max_spread) delta = -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 (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, maxx); + wiggle (qline->p[i].y, qline->p[i].dy, maxy); + } if (max_size) { - if (qline->p1.x - qline->p2.x > max_size) - qline->p1.x = qline->p2.x + max_size + /*assert(qix->npoly == 2);*/ + if (qline->p[0].x - qline->p[1].x > max_size) + qline->p[0].x = qline->p[1].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 + else if (qline->p[1].x - qline->p[0].x > max_size) + qline->p[1].x = qline->p[0].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 + if (qline->p[0].y - qline->p[1].y > max_size) + qline->p[0].y = qline->p[1].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 + else if (qline->p[1].y - qline->p[0].y > max_size) + qline->p[1].y = qline->p[0].y + max_size - (random_p ? random() % max_spread : 0); } if (!mono_p && !transparent_p) { - 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 + 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 (dpy, 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)) @@ -411,15 +404,30 @@ add_qline (dpy, window, cmap, qline, prev_qline, qix) XSetForeground (dpy, draw_gc, qline->color.pixel); } 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); + { + /* XDrawLine (dpy, window, (transparent_p ? gcs[0][qix->id] : draw_gc), + qline->p1.x, qline->p1.y, qline->p2.x, qline->p2.y);*/ + static 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(dpy, window, (transparent_p ? gcs[0][qix->id] : draw_gc), + points, qix->npoly+1, CoordModeOrigin); + } 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; + 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 (dpy, window, (transparent_p ? gcs[0][qix->id] : draw_gc), points, 4, Complex, CoordModeOrigin); } @@ -428,16 +436,13 @@ add_qline (dpy, window, cmap, qline, prev_qline, qix) } static void -qix1 (dpy, window, qix) - Display *dpy; - Window window; - struct qix *qix; +qix1 (Display *dpy, Window window, struct qix *qix) { int ofp = qix->fp - 1; static int gtick = 0; + if (ofp < 0) ofp = qix->nlines - 1; 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], &qix->lines[(qix->fp + 1) % qix->nlines], qix); add_qline (dpy, window, cmap, &qix->lines[qix->fp], &qix->lines[ofp], qix); @@ -453,6 +458,7 @@ char *defaults [] = { "*foreground: white", "*count: 1", "*segments: 50", + "*poly: 2", "*spread: 8", "*size: 0", "*colorShift: 3", @@ -461,6 +467,7 @@ char *defaults [] = { "*random: true", "*xor: false", "*transparent:false", + "*gravity: false", "*additive: true", 0 }; @@ -468,6 +475,7 @@ char *defaults [] = { XrmOptionDescRec 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,15 +488,15 @@ 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; +screenhack (Display *dpy, Window window) { struct qix **q1 = init_qix (dpy, window); struct qix **qn;