ftp://ftp.sunet.se/pub/vendor/sco/skunkware/osr5/x11/savers/xscreensaver/xscreensaver...
[xscreensaver] / utils / colors.c
diff --git a/utils/colors.c b/utils/colors.c
deleted file mode 100644 (file)
index 698bc94..0000000
+++ /dev/null
@@ -1,686 +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 "utils.h"
-#include "hsv.h"
-#include "yarandom.h"
-#include "visual.h"
-#include "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",
-           progname, 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",
-           progname, 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,
-                  (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)
-    {
-      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);
-}