X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fhalo.c;h=7e8da8a2b2eead3e65baaa1045d9585eb22b7688;hb=f65151994eba80ecabcdac6eef6fa0dde7e2d45b;hp=d61e2ac33c60aeb310024e39281c5ea6e3758a56;hpb=ccbc9f87eb59497b23bd0424ee1ed20ad7c7db54;p=xscreensaver diff --git a/hacks/halo.c b/hacks/halo.c index d61e2ac3..7e8da8a2 100644 --- a/hacks/halo.c +++ b/hacks/halo.c @@ -1,4 +1,5 @@ -/* xscreensaver, Copyright (c) 1993, 1995 Jamie Zawinski +/* xscreensaver, Copyright (c) 1993, 1995, 1996, 1997, 1998 + * 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 @@ -36,20 +37,24 @@ static struct circle *circles; static int count, global_count; static Pixmap pixmap, buffer; static int width, height, global_inc; -static int delay; +static int delay, delay2, cycle_delay; static unsigned long fg_pixel, bg_pixel; -static XColor fgc, bgc; static GC draw_gc, erase_gc, copy_gc, merge_gc; static Bool anim_p; static Colormap cmap; +static int ncolors; +static XColor *colors; +static Bool cycle_p; +static int fg_index; +static int bg_index; + + #define min(x,y) ((x)<(y)?(x):(y)) #define max(x,y) ((x)>(y)?(x):(y)) static void -init_circles_1 (dpy, window) - Display *dpy; - Window window; +init_circles_1 (Display *dpy, Window window) { int i; count = (global_count ? global_count @@ -76,9 +81,7 @@ init_circles_1 (dpy, window) } static void -init_circles (dpy, window) - Display *dpy; - Window window; +init_circles (Display *dpy, Window window) { XGCValues gcv; XWindowAttributes xgwa; @@ -91,6 +94,8 @@ init_circles (dpy, window) if (global_inc < 0) global_inc = 0; anim_p = get_boolean_resource ("animate", "Boolean"); delay = get_integer_resource ("delay", "Integer"); + delay2 = get_integer_resource ("delay2", "Integer") * 1000000; + cycle_delay = get_integer_resource ("cycleDelay", "Integer"); mode_str = get_string_resource ("colorMode", "ColorMode"); if (! mode_str) cmode = random_mode; else if (!strcmp (mode_str, "seuss")) cmode = seuss_mode; @@ -110,26 +115,43 @@ init_circles (dpy, window) if (cmode == ramp_mode) anim_p = False; /* This combo doesn't work right... */ + ncolors = get_integer_resource ("colors", "Colors"); + if (ncolors < 2) ncolors = 2; + if (ncolors <= 2) mono_p = True; + + if (mono_p) + colors = 0; + else + colors = (XColor *) malloc(sizeof(*colors) * (ncolors+1)); + + cycle_p = mono_p ? False : get_boolean_resource ("cycle", "Cycle"); + + + if (mono_p) + ; + else if (random() % (cmode == seuss_mode ? 2 : 10)) + make_uniform_colormap (dpy, xgwa.visual, cmap, colors, &ncolors, + True, &cycle_p, True); + else + make_smooth_colormap (dpy, xgwa.visual, cmap, colors, &ncolors, + True, &cycle_p, True); + + if (ncolors <= 2) mono_p = True; + if (mono_p) cycle_p = False; + if (mono_p) cmode = seuss_mode; + if (mono_p) { - fg_pixel = get_pixel_resource ("foreground","Foreground", dpy, cmap); - bg_pixel = get_pixel_resource ("background","Background", dpy, cmap); + fg_pixel = get_pixel_resource ("foreground", "Foreground", dpy, cmap); + bg_pixel = get_pixel_resource ("background", "Background", dpy, cmap); } else { - int r = random() % 360; - int r2 = (random() % 180) + 45; - double fs, bs; - if (cmode == seuss_mode) - fs = 0.5, bs = 1.0; - else - fs = 1.0, bs = 0.1; - hsv_to_rgb (r, fs, 1.0, &fgc.red, &fgc.green, &fgc.blue); - hsv_to_rgb ((r+r2)%360, bs, 0.7, &bgc.red, &bgc.green, &bgc.blue); - XAllocColor (dpy, cmap, &fgc); - XAllocColor (dpy, cmap, &bgc); - fg_pixel = fgc.pixel; - bg_pixel = bgc.pixel; + fg_index = 0; + bg_index = ncolors / 4; + if (fg_index == bg_index) bg_index++; + fg_pixel = colors[fg_index].pixel; + bg_pixel = colors[bg_index].pixel; } width = max (50, xgwa.width); @@ -177,9 +199,7 @@ init_circles (dpy, window) } static void -run_circles (dpy, window) - Display *dpy; - Window window; +run_circles (Display *dpy, Window window) { int i; static int iterations = 0; @@ -192,13 +212,14 @@ run_circles (dpy, window) { int radius = circles [i].radius; int inc = circles [i].increment; - if (! (iterations & 1)) + + if (! (iterations & 1)) /* never stop on an odd number of iterations */ ; - else if (radius == 0) + else if (radius == 0) /* eschew inf */ ; - else if (radius < 0) + else if (radius < 0) /* stop when the circles are points */ done = True; - else + else /* stop when the circles fill the window */ { /* Probably there's a simpler way to ask the musical question, "is this square completely enclosed by this circle," but I've @@ -212,16 +233,40 @@ run_circles (dpy, window) if ((x1 + y1) < 1 && (x2 + y2) < 1 && (x1 + y2) < 1 && (x2 + y1) < 1) done = True; } + if (radius > 0 && - (cmode == seuss_mode || circles [0].increment < 0)) - XFillArc (dpy, - (cmode == seuss_mode ? pixmap : window), - (cmode == seuss_mode ? draw_gc : merge_gc), - circles [i].x - radius, circles [i].y - radius, - radius * 2, radius * 2, 0, 360*64); + (cmode == seuss_mode || /* drawing all circles, or */ + circles [0].increment < 0)) /* on the way back in */ + { + XFillArc (dpy, + (cmode == seuss_mode ? pixmap : window), + (cmode == seuss_mode ? draw_gc : merge_gc), + circles [i].x - radius, circles [i].y - radius, + radius * 2, radius * 2, 0, 360*64); + } circles [i].radius += inc; } + if (cycle_p && cmode != seuss_mode) + { + struct timeval now; + static struct timeval then = { 0, }; + unsigned long diff; +#ifdef GETTIMEOFDAY_TWO_ARGS + struct timezone tzp; + gettimeofday(&now, &tzp); +#else + gettimeofday(&now); +#endif + diff = (((now.tv_sec - then.tv_sec) * 1000000) + + (now.tv_usec - then.tv_usec)); + if (diff > cycle_delay) + { + rotate_colors (dpy, cmap, colors, ncolors, 1); + then = now; + } + } + if (anim_p && !first_time_p) inhibit_sleep = !done; @@ -249,28 +294,33 @@ run_circles (dpy, window) } else if (circles [0].increment < 0) { + /* We've zoomed out and the screen is blank -- re-pick the + center points, and shift the colors. + */ free (circles); init_circles_1 (dpy, window); if (! mono_p) { - XColor d1, d2; - cycle_hue (&fgc, 10); - cycle_hue (&bgc, 10); - XFreeColors (dpy, cmap, &fgc.pixel, 1, 0); - XFreeColors (dpy, cmap, &bgc.pixel, 1, 0); - d1 = fgc; - d2 = bgc; - XAllocColor (dpy, cmap, &fgc); - XAllocColor (dpy, cmap, &bgc); - fgc.red = d1.red; fgc.green = d1.green; fgc.blue = d1.blue; - bgc.red = d2.red; bgc.green = d2.green; bgc.blue = d2.blue; - XSetForeground (dpy, copy_gc, fgc.pixel); - XSetBackground (dpy, copy_gc, bgc.pixel); + fg_index = (fg_index + 1) % ncolors; + bg_index = (fg_index + (ncolors/2)) % ncolors; + XSetForeground (dpy, copy_gc, colors [fg_index].pixel); + XSetBackground (dpy, copy_gc, colors [bg_index].pixel); } } -#if 0 - else if ((random () % 2) == 0) +#if 1 + /* Sometimes go out from the inside instead of the outside */ + else if ((random () % 10) == 0) { +# if 0 + if (! mono_p) + { + unsigned long swap = fg_index; + fg_index = bg_index; + bg_index = swap; + XSetForeground (dpy, copy_gc, colors [fg_index].pixel); + XSetBackground (dpy, copy_gc, colors [bg_index].pixel); + } +# endif iterations = 0; /* ick */ for (i = 0; i < count; i++) circles [i].radius %= circles [i].increment; @@ -291,53 +341,40 @@ run_circles (dpy, window) XCopyPlane (dpy, pixmap, buffer, merge_gc, 0, 0, width, height, 0, 0, 1); else if (cmode != seuss_mode) { - static int ncolors = 0; - static XColor *colors = 0; - if (circles [0].increment >= 0) - inhibit_sleep = True; - else if (done) - { - int fgh, bgh; - double fgs, fgv, bgs, bgv; - if (colors) - for (i = 0; i < ncolors; i++) - XFreeColors (dpy, cmap, &colors [i].pixel, 1, 0); - - rgb_to_hsv (fgc.red, fgc.green, fgc.blue, &fgh, &fgs, &fgv); - rgb_to_hsv (bgc.red, bgc.green, bgc.blue, &bgh, &bgs, &bgv); - ncolors = oiterations; - colors = ((XColor *) - (colors - ? realloc (colors, sizeof (XColor) * ncolors) - : malloc (sizeof (XColor) * ncolors))); - - make_color_ramp (bgh, bgs, bgv, fgh, fgs, fgv, colors, ncolors); - for (i = 0; i < ncolors; i++) - XAllocColor (dpy, cmap, &colors [i]); - XSetForeground (dpy, merge_gc, colors [0].pixel); - } - else + + if (!mono_p) { - XSetForeground (dpy, merge_gc, colors [iterations].pixel); + fg_index++; + bg_index++; + if (fg_index >= ncolors) fg_index = 0; + if (bg_index >= ncolors) bg_index = 0; + XSetForeground (dpy, merge_gc, colors [fg_index].pixel); } + + if (circles [0].increment >= 0) + inhibit_sleep = True; + else if (done && cmode == seuss_mode) + XFillRectangle (dpy, window, merge_gc, 0, 0, width, height); } else XCopyPlane (dpy, pixmap, window, merge_gc, 0, 0, width, height, 0, 0, 1); + /* buffer is only used in seuss-mode or anim-mode */ if (buffer && (anim_p ? (done || (first_time_p && (iterations & 1))) : (iterations & 1))) { XCopyPlane (dpy, buffer, window, copy_gc, 0, 0, width, height, 0, 0, 1); - XSync (dpy, True); + XSync (dpy, False); if (anim_p && done) XFillRectangle (dpy, buffer, erase_gc, 0, 0, width, height); } + #ifdef DEBUG XCopyPlane (dpy, pixmap, window, copy_gc, 0,0,width,height,width,height, 1); if (buffer) XCopyPlane (dpy, buffer, window, copy_gc, 0,0,width,height,0,height, 1); - XSync (dpy, True); + XSync (dpy, False); #endif if (done) @@ -345,35 +382,72 @@ run_circles (dpy, window) else iterations++; - if (delay && !inhibit_sleep) usleep (delay); + if (delay && !inhibit_sleep) + { + static Bool really_first_p = True; + int direction = 1; + int d = delay; + if (done && cycle_p && cmode != seuss_mode && !really_first_p) + { + d = delay2; + if (! (random() % 10)) + direction = -1; + } + if (done) + really_first_p = False; + + XSync(dpy, False); + + if (cycle_p && cycle_delay) + { + int i = 0; + while (i < d) + { + rotate_colors (dpy, cmap, colors, ncolors, direction); + usleep(cycle_delay); + i += cycle_delay; + } + } + else + usleep (d); + } } char *progclass = "Halo"; char *defaults [] = { - "Halo.background: black", /* to placate SGI */ - "Halo.foreground: white", + ".background: black", + ".foreground: white", "*colorMode: random", + "*colors: 100", + "*cycle: true", "*count: 0", "*delay: 100000", + "*delay2: 20", + "*cycleDelay: 100000", 0 }; XrmOptionDescRec options [] = { { "-count", ".count", XrmoptionSepArg, 0 }, { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-cycle-delay", ".cycleDelay", XrmoptionSepArg, 0 }, { "-animate", ".animate", XrmoptionNoArg, "True" }, - { "-mode", ".colorMode", XrmoptionSepArg, 0 } + { "-mode", ".colorMode", XrmoptionSepArg, 0 }, + { "-colors", ".colors", XrmoptionSepArg, 0 }, + { "-cycle", ".cycle", XrmoptionNoArg, "True" }, + { "-no-cycle", ".cycle", 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) { init_circles (dpy, window); while (1) - run_circles (dpy, window); + { + run_circles (dpy, window); + screenhack_handle_events (dpy); + } }