diff options
Diffstat (limited to 'kscreensaver/xsavers/xs_colors.c')
-rw-r--r-- | kscreensaver/xsavers/xs_colors.c | 693 |
1 files changed, 0 insertions, 693 deletions
diff --git a/kscreensaver/xsavers/xs_colors.c b/kscreensaver/xsavers/xs_colors.c deleted file mode 100644 index 82dab33b..00000000 --- a/kscreensaver/xsavers/xs_colors.c +++ /dev/null @@ -1,693 +0,0 @@ -/* xscreensaver, Copyright (c) 1997 Jamie Zawinski <jwz@jwz.org> - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation. No representations are made about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - */ - -/* This file contains some utility routines for randomly picking the colors - to hack the screen with. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <math.h> - -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/Xos.h> -#include <X11/Xresource.h> - -#include "xs_visual.h" -#include "xs_yarandom.h" -#include "xs_hsv.h" -#include "xs_colors.h" - -/* extern char *progname; */ - -void -free_colors(Display *dpy, Colormap cmap, XColor *colors, int ncolors) -{ - int i; - if (ncolors > 0) - { - unsigned long *pixels = (unsigned long *) - malloc(sizeof(*pixels) * ncolors); - for (i = 0; i < ncolors; i++) - pixels[i] = colors[i].pixel; - XFreeColors (dpy, cmap, pixels, ncolors, 0L); - free(pixels); - } -} - - -void -allocate_writable_colors (Display *dpy, Colormap cmap, - unsigned long *pixels, int *ncolorsP) -{ - int desired = *ncolorsP; - int got = 0; - int requested = desired; - unsigned long *new_pixels = pixels; - - *ncolorsP = 0; - while (got < desired - && requested > 0) - { - if (desired - got < requested) - requested = desired - got; - - if (XAllocColorCells (dpy, cmap, False, 0, 0, new_pixels, requested)) - { - /* Got all the pixels we asked for. */ - new_pixels += requested; - got += requested; - } - else - { - /* We didn't get all/any of the pixels we asked for. This time, ask - for half as many. (If we do get all that we ask for, we ask for - the same number again next time, so we only do O(log(n)) server - roundtrips.) - */ - requested = requested / 2; - } - } - *ncolorsP += got; -} - - - -void -make_color_ramp (Display *dpy, Colormap cmap, - int h1, double s1, double v1, /* 0-360, 0-1.0, 0-1.0 */ - int h2, double s2, double v2, /* 0-360, 0-1.0, 0-1.0 */ - XColor *colors, int *ncolorsP, - Bool closed_p, - Bool allocate_p, - Bool writable_p) -{ - int i; - int ncolors = *ncolorsP; - double dh, ds, dv; /* deltas */ - - AGAIN: - - memset (colors, 0, (*ncolorsP) * sizeof(*colors)); - - if (closed_p) - ncolors = (ncolors / 2) + 1; - - /* Note: unlike other routines in this module, this function assumes that - if h1 and h2 are more than 180 degrees apart, then the desired direction - is always from h1 to h2 (rather than the shorter path.) make_uniform - depends on this. - */ - dh = ((double)h2 - (double)h1) / ncolors; - ds = (s2 - s1) / ncolors; - dv = (v2 - v1) / ncolors; - - for (i = 0; i < ncolors; i++) - { - colors[i].flags = DoRed|DoGreen|DoBlue; - hsv_to_rgb ((int) (h1 + (i*dh)), (s1 + (i*ds)), (v1 + (i*dv)), - &colors[i].red, &colors[i].green, &colors[i].blue); - } - - if (closed_p) - for (i = ncolors; i < *ncolorsP; i++) - colors[i] = colors[(*ncolorsP)-i]; - - if (!allocate_p) - return; - - if (writable_p) - { - unsigned long *pixels = (unsigned long *) - malloc(sizeof(*pixels) * ((*ncolorsP) + 1)); - - /* allocate_writable_colors() won't do here, because we need exactly this - number of cells, or the color sequence we've chosen won't fit. */ - if (! XAllocColorCells(dpy, cmap, False, 0, 0, pixels, *ncolorsP)) - { - free(pixels); - goto FAIL; - } - - for (i = 0; i < *ncolorsP; i++) - colors[i].pixel = pixels[i]; - free (pixels); - - XStoreColors (dpy, cmap, colors, *ncolorsP); - } - else - { - for (i = 0; i < *ncolorsP; i++) - { - XColor color; - color = colors[i]; - if (XAllocColor (dpy, cmap, &color)) - { - colors[i].pixel = color.pixel; - } - else - { - free_colors (dpy, cmap, colors, i); - goto FAIL; - } - } - } - - return; - - FAIL: - /* we weren't able to allocate all the colors we wanted; - decrease the requested number and try again. - */ - ncolors = (ncolors > 170 ? ncolors - 20 : - ncolors > 100 ? ncolors - 10 : - ncolors > 75 ? ncolors - 5 : - ncolors > 25 ? ncolors - 3 : - ncolors > 10 ? ncolors - 2 : - ncolors > 2 ? ncolors - 1 : - 0); - *ncolorsP = ncolors; - if (ncolors > 0) - goto AGAIN; -} - - -#define MAXPOINTS 50 /* yeah, so I'm lazy */ - - -static void -make_color_path (Display *dpy, Colormap cmap, - int npoints, int *h, double *s, double *v, - XColor *colors, int *ncolorsP, - Bool allocate_p, - Bool writable_p) -{ - int i, j, k; - int total_ncolors = *ncolorsP; - - int ncolors[MAXPOINTS]; /* number of pixels per edge */ - double dh[MAXPOINTS]; /* distance between pixels, per edge (0 - 360.0) */ - double ds[MAXPOINTS]; /* distance between pixels, per edge (0 - 1.0) */ - double dv[MAXPOINTS]; /* distance between pixels, per edge (0 - 1.0) */ - - if (npoints == 0) - { - *ncolorsP = 0; - return; - } - else if (npoints == 2) /* using make_color_ramp() will be faster */ - { - make_color_ramp (dpy, cmap, - h[0], s[0], v[0], h[1], s[1], v[1], - colors, ncolorsP, - True, /* closed_p */ - allocate_p, writable_p); - return; - } - else if (npoints >= MAXPOINTS) - { - npoints = MAXPOINTS-1; - } - - AGAIN: - - { - double DH[MAXPOINTS]; /* Distance between H values in the shortest - direction around the circle, that is, the - distance between 10 and 350 is 20. - (Range is 0 - 360.0.) - */ - double edge[MAXPOINTS]; /* lengths of edges in unit HSV space. */ - double ratio[MAXPOINTS]; /* proportions of the edges (total 1.0) */ - double circum = 0; - double one_point_oh = 0; /* (debug) */ - - for (i = 0; i < npoints; i++) - { - int j = (i+1) % npoints; - double d = ((double) (h[i] - h[j])) / 360; - if (d < 0) d = -d; - if (d > 0.5) d = 0.5 - (d - 0.5); - DH[i] = d; - } - - for (i = 0; i < npoints; i++) - { - int j = (i+1) % npoints; - edge[i] = sqrt((DH[i] * DH[j]) + - ((s[j] - s[i]) * (s[j] - s[i])) + - ((v[j] - v[i]) * (v[j] - v[i]))); - circum += edge[i]; - } - -#ifdef DEBUG - fprintf(stderr, "\ncolors:"); - for (i=0; i < npoints; i++) - fprintf(stderr, " (%d, %.3f, %.3f)", h[i], s[i], v[i]); - fprintf(stderr, "\nlengths:"); - for (i=0; i < npoints; i++) - fprintf(stderr, " %.3f", edge[i]); -#endif /* DEBUG */ - - if (circum < 0.0001) - goto FAIL; - - for (i = 0; i < npoints; i++) - { - ratio[i] = edge[i] / circum; - one_point_oh += ratio[i]; - } - -#ifdef DEBUG - fprintf(stderr, "\nratios:"); - for (i=0; i < npoints; i++) - fprintf(stderr, " %.3f", ratio[i]); -#endif /* DEBUG */ - - if (one_point_oh < 0.99999 || one_point_oh > 1.00001) - abort(); - - /* space the colors evenly along the circumference -- that means that the - number of pixels on a edge is proportional to the length of that edge - (relative to the lengths of the other edges.) - */ - for (i = 0; i < npoints; i++) - ncolors[i] = total_ncolors * ratio[i]; - - -#ifdef DEBUG - fprintf(stderr, "\npixels:"); - for (i=0; i < npoints; i++) - fprintf(stderr, " %d", ncolors[i]); - fprintf(stderr, " (%d)\n", total_ncolors); -#endif /* DEBUG */ - - for (i = 0; i < npoints; i++) - { - int j = (i+1) % npoints; - - if (ncolors[i] > 0) - { - dh[i] = 360 * (DH[i] / ncolors[i]); - ds[i] = (s[j] - s[i]) / ncolors[i]; - dv[i] = (v[j] - v[i]) / ncolors[i]; - } - } - } - - memset (colors, 0, (*ncolorsP) * sizeof(*colors)); - - k = 0; - for (i = 0; i < npoints; i++) - { - int distance, direction; - distance = h[(i+1) % npoints] - h[i]; - direction = (distance >= 0 ? -1 : 1); - - if (distance > 180) - distance = 180 - (distance - 180); - else if (distance < -180) - distance = -(180 - ((-distance) - 180)); - else - direction = -direction; - -#ifdef DEBUG - fprintf (stderr, "point %d: %3d %.2f %.2f\n", - i, h[i], s[i], v[i]); - fprintf(stderr, " h[i]=%d dh[i]=%.2f ncolors[i]=%d\n", - h[i], dh[i], ncolors[i]); -#endif /* DEBUG */ - for (j = 0; j < ncolors[i]; j++, k++) - { - double hh = (h[i] + (j * dh[i] * direction)); - if (hh < 0) hh += 360; - else if (hh > 360) hh -= 0; - colors[k].flags = DoRed|DoGreen|DoBlue; - hsv_to_rgb ((int) - hh, - (s[i] + (j * ds[i])), - (v[i] + (j * dv[i])), - &colors[k].red, &colors[k].green, &colors[k].blue); -#ifdef DEBUG - fprintf (stderr, "point %d+%d: %.2f %.2f %.2f %04X %04X %04X\n", - i, j, - hh, - (s[i] + (j * ds[i])), - (v[i] + (j * dv[i])), - colors[k].red, colors[k].green, colors[k].blue); -#endif /* DEBUG */ - } - } - - /* Floating-point round-off can make us decide to use fewer colors. */ - if (k < *ncolorsP) - { - *ncolorsP = k; - if (k <= 0) - return; - } - - if (!allocate_p) - return; - - if (writable_p) - { - unsigned long *pixels = (unsigned long *) - malloc(sizeof(*pixels) * ((*ncolorsP) + 1)); - - /* allocate_writable_colors() won't do here, because we need exactly this - number of cells, or the color sequence we've chosen won't fit. */ - if (! XAllocColorCells(dpy, cmap, False, 0, 0, pixels, *ncolorsP)) - { - free(pixels); - goto FAIL; - } - - for (i = 0; i < *ncolorsP; i++) - colors[i].pixel = pixels[i]; - free (pixels); - - XStoreColors (dpy, cmap, colors, *ncolorsP); - } - else - { - for (i = 0; i < *ncolorsP; i++) - { - XColor color; - color = colors[i]; - if (XAllocColor (dpy, cmap, &color)) - { - colors[i].pixel = color.pixel; - } - else - { - free_colors (dpy, cmap, colors, i); - goto FAIL; - } - } - } - - return; - - FAIL: - /* we weren't able to allocate all the colors we wanted; - decrease the requested number and try again. - */ - total_ncolors = (total_ncolors > 170 ? total_ncolors - 20 : - total_ncolors > 100 ? total_ncolors - 10 : - total_ncolors > 75 ? total_ncolors - 5 : - total_ncolors > 25 ? total_ncolors - 3 : - total_ncolors > 10 ? total_ncolors - 2 : - total_ncolors > 2 ? total_ncolors - 1 : - 0); - *ncolorsP = total_ncolors; - if (total_ncolors > 0) - goto AGAIN; -} - - -void -make_color_loop (Display *dpy, Colormap cmap, - int h0, double s0, double v0, /* 0-360, 0-1.0, 0-1.0 */ - int h1, double s1, double v1, /* 0-360, 0-1.0, 0-1.0 */ - int h2, double s2, double v2, /* 0-360, 0-1.0, 0-1.0 */ - XColor *colors, int *ncolorsP, - Bool allocate_p, - Bool writable_p) -{ - int h[3]; - double s[3], v[3]; - h[0] = h0; h[1] = h1; h[2] = h2; - s[0] = s0; s[1] = s1; s[2] = s2; - v[0] = v0; v[1] = v1; v[2] = v2; - make_color_path(dpy, cmap, - 3, h, s, v, - colors, ncolorsP, - allocate_p, writable_p); -} - - -static void -complain (int wanted_colors, int got_colors, - Bool wanted_writable, Bool got_writable) -{ - if (wanted_writable && !got_writable) - fprintf(stderr, - "%s: wanted %d writable colors; got %d read-only colors.\n", - "colors (kscreensaver)", wanted_colors, got_colors); - - else if (wanted_colors > (got_colors + 10)) - /* don't bother complaining if we're within ten pixels. */ - fprintf(stderr, "%s: wanted %d%s colors; got %d.\n", - "colors (kscreensaver)", wanted_colors, (got_writable ? " writable" : ""), - got_colors); -} - - -void -make_smooth_colormap (Display *dpy, Visual *visual, Colormap cmap, - XColor *colors, int *ncolorsP, - Bool allocate_p, - Bool *writable_pP, - Bool verbose_p) -{ - int npoints; - int ncolors = *ncolorsP; - Bool wanted_writable = (allocate_p && writable_pP && *writable_pP); - int i; - int h[MAXPOINTS]; - double s[MAXPOINTS]; - double v[MAXPOINTS]; - double total_s = 0; - double total_v = 0; - Screen *screen = DefaultScreenOfDisplay(dpy); /* #### WRONG! */ - - if (*ncolorsP <= 0) return; - - { - int n = random() % 20; - if (n <= 5) npoints = 2; /* 30% of the time */ - else if (n <= 15) npoints = 3; /* 50% of the time */ - else if (n <= 18) npoints = 4; /* 15% of the time */ - else npoints = 5; /* 5% of the time */ - } - - REPICK_ALL_COLORS: - for (i = 0; i < npoints; i++) - { - REPICK_THIS_COLOR: - h[i] = random() % 360; - s[i] = frand(1.0); - v[i] = frand(0.8) + 0.2; - - /* Make sure that no two adjascent colors are *too* close together. - If they are, try again. - */ - if (i > 0) - { - int j = (i+1 == npoints) ? 0 : (i-1); - double hi = ((double) h[i]) / 360; - double hj = ((double) h[j]) / 360; - double dh = hj - hi; - double distance; - if (dh < 0) dh = -dh; - if (dh > 0.5) dh = 0.5 - (dh - 0.5); - distance = sqrt ((dh * dh) + - ((s[j] - s[i]) * (s[j] - s[i])) + - ((v[j] - v[i]) * (v[j] - v[i]))); - if (distance < 0.2) - goto REPICK_THIS_COLOR; - } - total_s += s[i]; - total_v += v[i]; - } - - /* If the average saturation or intensity are too low, repick the colors, - so that we don't end up with a black-and-white or too-dark map. - */ - if (total_s / npoints < 0.2) - goto REPICK_ALL_COLORS; - if (total_v / npoints < 0.3) - goto REPICK_ALL_COLORS; - - /* If this visual doesn't support writable cells, don't bother trying. - */ - if (wanted_writable && !has_writable_cells(screen, visual)) - *writable_pP = False; - - RETRY_NON_WRITABLE: - make_color_path (dpy, cmap, npoints, h, s, v, colors, &ncolors, - allocate_p, (writable_pP && *writable_pP)); - - /* If we tried for writable cells and got none, try for non-writable. */ - if (allocate_p && *ncolorsP == 0 && *writable_pP) - { - *writable_pP = False; - goto RETRY_NON_WRITABLE; - } - - if (verbose_p) - complain(*ncolorsP, ncolors, wanted_writable, - wanted_writable && *writable_pP); - - *ncolorsP = ncolors; -} - - -void -make_uniform_colormap (Display *dpy, Visual *visual, Colormap cmap, - XColor *colors, int *ncolorsP, - Bool allocate_p, - Bool *writable_pP, - Bool verbose_p) -{ - int ncolors = *ncolorsP; - Bool wanted_writable = (allocate_p && writable_pP && *writable_pP); - Screen *screen = DefaultScreenOfDisplay(dpy); /* #### WRONG! */ - - double S = ((double) (random() % 34) + 66) / 100.0; /* range 66%-100% */ - double V = ((double) (random() % 34) + 66) / 100.0; /* range 66%-100% */ - - if (*ncolorsP <= 0) return; - - /* If this visual doesn't support writable cells, don't bother trying. */ - if (wanted_writable && !has_writable_cells(screen, visual)) - *writable_pP = False; - - RETRY_NON_WRITABLE: - make_color_ramp(dpy, cmap, - 0, S, V, - 359, S, V, - colors, &ncolors, - False, True, wanted_writable); - - /* If we tried for writable cells and got none, try for non-writable. */ - if (allocate_p && *ncolorsP == 0 && writable_pP && *writable_pP) - { - ncolors = *ncolorsP; - *writable_pP = False; - goto RETRY_NON_WRITABLE; - } - - if (verbose_p) - complain(*ncolorsP, ncolors, wanted_writable, - wanted_writable && *writable_pP); - - *ncolorsP = ncolors; -} - - -void -make_random_colormap (Display *dpy, Visual *visual, Colormap cmap, - XColor *colors, int *ncolorsP, - Bool bright_p, - Bool allocate_p, - Bool *writable_pP, - Bool verbose_p) -{ - Bool wanted_writable = (allocate_p && writable_pP && *writable_pP); - int ncolors = *ncolorsP; - int i; - Screen *screen = DefaultScreenOfDisplay(dpy); /* #### WRONG! */ - - if (*ncolorsP <= 0) return; - - /* If this visual doesn't support writable cells, don't bother trying. */ - if (wanted_writable && !has_writable_cells(screen, visual)) - *writable_pP = False; - - for (i = 0; i < ncolors; i++) - { - colors[i].flags = DoRed|DoGreen|DoBlue; - if (bright_p) - { - int H = random() % 360; /* range 0-360 */ - double S = ((double) (random()%70) + 30)/100.0; /* range 30%-100% */ - double V = ((double) (random()%34) + 66)/100.0; /* range 66%-100% */ - hsv_to_rgb (H, S, V, - &colors[i].red, &colors[i].green, &colors[i].blue); - } - else - { - colors[i].red = random() % 0xFFFF; - colors[i].green = random() % 0xFFFF; - colors[i].blue = random() % 0xFFFF; - } - } - - if (!allocate_p) - return; - - RETRY_NON_WRITABLE: - if (writable_pP && *writable_pP) - { - unsigned long *pixels = (unsigned long *) - malloc(sizeof(*pixels) * (ncolors + 1)); - - allocate_writable_colors (dpy, cmap, pixels, &ncolors); - if (ncolors > 0) - for (i = 0; i < ncolors; i++) - colors[i].pixel = pixels[i]; - free (pixels); - if (ncolors > 0) - XStoreColors (dpy, cmap, colors, ncolors); - } - else - { - for (i = 0; i < ncolors; i++) - { - XColor color; - color = colors[i]; - if (!XAllocColor (dpy, cmap, &color)) - break; - colors[i].pixel = color.pixel; - } - ncolors = i; - } - - /* If we tried for writable cells and got none, try for non-writable. */ - if (allocate_p && ncolors == 0 && writable_pP && *writable_pP) - { - ncolors = *ncolorsP; - *writable_pP = False; - goto RETRY_NON_WRITABLE; - } - - if (verbose_p) - complain(*ncolorsP, ncolors, wanted_writable, - wanted_writable && *writable_pP); - - *ncolorsP = ncolors; -} - - -void -rotate_colors (Display *dpy, Colormap cmap, - XColor *colors, int ncolors, int distance) -{ - int i; - XColor *colors2 = (XColor *) malloc(sizeof(*colors2) * ncolors); - if (ncolors < 2) return; - distance = distance % ncolors; - for (i = 0; i < ncolors; i++) - { - int j = i - distance; - if (j >= ncolors) j -= ncolors; - if (j < 0) j += ncolors; - colors2[i] = colors[j]; - colors2[i].pixel = colors[i].pixel; - } - XStoreColors (dpy, cmap, colors2, ncolors); - XFlush(dpy); - memcpy(colors, colors2, sizeof(*colors) * ncolors); - free(colors2); -} |