Exemple #1
0
/* set up the colormap */
static void setupColormap (struct state *st, XWindowAttributes *xgwa)
{
    int n;
    XGCValues gcv;
    XColor *colors = (XColor *) calloc (sizeof (XColor), st->colorCount + 1);

    unsigned short r, g, b;
    int h1, h2;
    double s1, s2, v1, v2;

    r = RAND_FLOAT_01 * 0x10000;
    g = RAND_FLOAT_01 * 0x10000;
    b = RAND_FLOAT_01 * 0x10000;
    rgb_to_hsv (r, g, b, &h1, &s1, &v1);
    v1 = 1.0;
    s1 = 1.0;

    r = RAND_FLOAT_01 * 0x10000;
    g = RAND_FLOAT_01 * 0x10000;
    b = RAND_FLOAT_01 * 0x10000;
    rgb_to_hsv (r, g, b, &h2, &s2, &v2);
    s2 = 0.7;
    v2 = 0.7;
    
    colors[0].pixel = get_pixel_resource (st->dpy, xgwa->colormap,
                                          "background", "Background");
    
    make_color_ramp (xgwa->screen, xgwa->visual, xgwa->colormap,
                     h1, s1, v1, h2, s2, v2,
		     colors + 1, &st->colorCount, False, True, False);

    if (st->colorCount < 1)
    {
        fprintf (stderr, "%s: couldn't allocate any colors\n", progname);
	exit (-1);
    }
    
    st->gcs = (GC *) calloc (sizeof (GC), st->colorCount + 1);

    for (n = 0; n <= st->colorCount; n++) 
    {
	gcv.foreground = colors[n].pixel;
	gcv.line_width = st->lineWidth;
	st->gcs[n] = XCreateGC (st->dpy, st->window, GCForeground | GCLineWidth, &gcv);
    }

    free (colors);
}
ENTRYPOINT void
init_glschool(ModeInfo *mi)
{
	int						width = MI_WIDTH(mi);
	int						height = MI_HEIGHT(mi);
	Bool					wire = MI_IS_WIREFRAME(mi);
	glschool_configuration	*sc;

	if (!scs) {
		scs = (glschool_configuration *)calloc(MI_NUM_SCREENS(mi), sizeof(glschool_configuration));
		if (!scs) {
			perror("init_glschool: ");
			exit(1);
		}
	}
	sc = &scs[MI_SCREEN(mi)];

	sc->drawGoal = DoDrawGoal;
	sc->drawBBox = DoDrawBBox;

	sc->nColors = 360;
	sc->context = init_GL(mi);
	sc->colors = (XColor *)calloc(sc->nColors, sizeof(XColor));
	make_color_ramp(0, 0, 0,
					0.0, 1.0, 1.0,
					359.0, 1.0, 1.0,
					sc->colors, &sc->nColors,
					False, 0, False);

	sc->school = glschool_initSchool(NFish, AccLimit, MaxVel, MinVel, DistExp, Momentum,
							MinRadius, AvoidFact, MatchFact, CenterFact, TargetFact,
							DistComp);
	if (sc->school == (School *)0) {
		fprintf(stderr, "couldn't initialize TheSchool, exiting\n");
		exit(1);
	}

	reshape_glschool(mi, width, height);

	glschool_initGLEnv(DoFog);
	glschool_initFishes(sc->school);
	glschool_createDrawLists(&SCHOOL_BBOX(sc->school), 
                                 &sc->bboxList, &sc->goalList, &sc->fishList,
                                 &sc->fish_polys, &sc->box_polys, wire);
	glschool_computeAccelerations(sc->school);
}
Exemple #3
0
void
make_uniform_colormap(ModeInfo * mi, Colormap cmap,
		      XColor * colors, int *ncolorsP,
		      Bool allocate_p,
		      Bool * writable_pP)
{
	int         ncolors = *ncolorsP;
	Bool        wanted_writable = (allocate_p && writable_pP && *writable_pP);

	double      S = ((double) (LRAND() % 34) + 66) / 100.0;		/* range 66%-100% */
	double      V = ((double) (LRAND() % 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(mi))
		*writable_pP = False;

      RETRY_NON_WRITABLE:
	make_color_ramp(MI_DISPLAY(mi), 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 (MI_IS_VERBOSE(mi) || MI_IS_DEBUG(mi))
		complain(*ncolorsP, ncolors, wanted_writable,
			 wanted_writable && *writable_pP);

	*ncolorsP = ncolors;
}
Exemple #4
0
static void *
popsquares_init (Display *dpy, Window window)
{
  struct state *st = (struct state *) calloc (1, sizeof(*st));
  int x, y;
  double s1, v1, s2, v2 = 0;
  int h1, h2 = 0;
  /* Not sure how to use DBEClear */
  /* Bool dbeclear_p = get_boolean_resource(dpy, "useDBEClear", "Boolean"); */
  XColor fg, bg;
  XGCValues gcv;
  
  st->dpy = dpy;
  st->window = window;

  st->delay = get_integer_resource (st->dpy, "delay", "Integer");
  st->subdivisionx = get_integer_resource(st->dpy, "subdivision", "Integer");
  st->subdivisiony = st->subdivisionx;
  st->border = get_integer_resource(st->dpy, "border", "Integer");
  st->ncolors = get_integer_resource(st->dpy, "ncolors", "Integer");
  st->twitch = get_boolean_resource(st->dpy, "twitch", "Boolean");
  st->dbuf = get_boolean_resource(st->dpy, "doubleBuffer", "Boolean");

# ifdef HAVE_JWXYZ	/* Don't second-guess Quartz's double-buffering */
  st->dbuf = False;
# endif

  XGetWindowAttributes (st->dpy, st->window, &st->xgwa);

  fg.pixel = get_pixel_resource (st->dpy, st->xgwa.colormap, "foreground", "Foreground");
  bg.pixel = get_pixel_resource (st->dpy, st->xgwa.colormap, "background", "Background");

  XQueryColor (st->dpy, st->xgwa.colormap, &fg);
  XQueryColor (st->dpy, st->xgwa.colormap, &bg);

  st->sw = st->xgwa.width / st->subdivisionx;
  st->sh = st->xgwa.height / st->subdivisiony;
  st->gw = st->sw ? st->xgwa.width / st->sw : 0;
  st->gh = st->sh ? st->xgwa.height / st->sh : 0;
  st->nsquares = st->gw * st->gh;
  if (st->nsquares < 1) st->nsquares = 1;
  if (st->ncolors < 1) st->ncolors = 1;

  gcv.foreground = fg.pixel;
  gcv.background = bg.pixel;
  st->gc = XCreateGC (st->dpy, st->window, GCForeground|GCBackground, &gcv);

  st->colors = (XColor *) calloc (st->ncolors, sizeof(XColor));
  st->squares = (square *) calloc (st->nsquares, sizeof(square));

  rgb_to_hsv (fg.red, fg.green, fg.blue, &h1, &s1, &v1);
  rgb_to_hsv (bg.red, bg.green, bg.blue, &h2, &s2, &v2);
  make_color_ramp (st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap,
                   h1, s1, v1,
                   h2, s2, v2,
                   st->colors, &st->ncolors,  /* would this be considered a value-result argument? */
                   True, True, False);
  if (st->ncolors < 2)
    {
      fprintf (stderr, "%s: insufficient colors!\n", progname);
      exit (1);
    }

  for (y = 0; y < st->gh; y++)
    for (x = 0; x < st->gw; x++) 
      {
        square *s = (square *) &st->squares[st->gw * y + x];
        s->w = st->sw;
        s->h = st->sh;
        s->x = x * st->sw;
        s->y = y * st->sh;
      }

  randomize_square_colors(st->squares, st->nsquares, st->ncolors);

  if (st->dbuf)
    {
#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
      st->b = xdbe_get_backbuffer (st->dpy, st->window, XdbeUndefined);
      st->backb = st->b;
#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
      if (!st->b)                      
        {
          st->ba = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height, st->xgwa.depth);
          st->bb = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height, st->xgwa.depth);
          st->b = st->ba;
        }
    }
  else 
    {
      st->b = st->window;
    }

  popsquares_reshape (dpy, window, st, st->xgwa.width, st->xgwa.height);

  return st;
}
static void *
intermomentary_init (Display *dpy, Window window)
{
  struct state *st = (struct state *) calloc (1, sizeof(*st));

#ifdef TIME_ME
    time_t start_time = time(NULL);
#endif

    int tempx;
    XGCValues gcv;

    st->dpy = dpy;
    st->window = window;

    XGetWindowAttributes(dpy, window, &st->xgwa);
 
    st->ncolors = get_integer_resource (st->dpy, "colors", "Colors");
    st->ncolors++;
    st->colors = (XColor *) malloc(sizeof(*st->colors) * (st->ncolors+1));

    gcv.foreground = get_pixel_resource(dpy, st->xgwa.colormap,
                                        "foreground", "Foreground");
    gcv.background = get_pixel_resource(dpy, st->xgwa.colormap,
                                        "background", "Background");

    {
      XColor fgc, bgc;
      int fgh, bgh;
      double fgs, fgv, bgs, bgv;
      fgc.pixel = gcv.foreground;
      bgc.pixel = gcv.background;
      XQueryColor (st->dpy, st->xgwa.colormap, &fgc);
      XQueryColor (st->dpy, st->xgwa.colormap, &bgc);
      rgb_to_hsv (fgc.red, fgc.green, fgc.blue, &fgh, &fgs, &fgv);
      rgb_to_hsv (bgc.red, bgc.green, bgc.blue, &bgh, &bgs, &bgv);
#if 0
      bgh = fgh;
      bgs = fgs;
      bgv = fgv / 10.0;
#endif
      make_color_ramp (st->dpy, st->xgwa.colormap,
                       bgh, bgs, bgv,
                       fgh, fgs, fgv,
                       st->colors, &st->ncolors,
                       False, /* closed */
                       True, False);
    }

    st->f = init_field();

    st->f->height = st->xgwa.height;
    st->f->width = st->xgwa.width;
    st->f->visdepth = st->xgwa.depth;

    st->draw_delay = (get_integer_resource(dpy, "drawDelay", "Integer"));
    st->f->maxrider = (get_integer_resource(dpy, "maxRiders", "Integer"));
    st->f->maxradius = (get_integer_resource(dpy, "maxRadius", "Integer"));
    st->f->initial_discs = (get_integer_resource(dpy, "numDiscs", "Integer"));

    if (st->f->initial_discs <= 10) {
        fprintf(stderr, "%s: Initial discs must be greater than 10\n", progname);
        exit (1);
    }

    if (st->f->maxradius <= 30) {
        fprintf(stderr, "%s: Max radius must be greater than 30\n", progname);
        exit (1);
    }

    if (st->f->maxrider <= 10) {
        fprintf(stderr, "%s: Max riders must be greater than 10\n", progname);
        exit (1);
    }
    
    st->fgc = XCreateGC(dpy, window, GCForeground, &gcv);
    st->copygc = XCreateGC(dpy, window, GCForeground, &gcv);

    st->f->fgcolor = gcv.foreground;
    st->f->bgcolor = gcv.background;

    /* Initialize stuff */
    build_img(dpy, window, st->f);

    for (tempx = 0; tempx < st->f->initial_discs; tempx++) {
        float fx, fy, x, y, r;
        int bt;

        /* Arrange in anti-collapsing circle */
        fx = 0.4 * st->f->width * cos((2 * M_PI) * tempx / st->f->initial_discs);
        fy = 0.4 * st->f->height * sin((2 * M_PI) * tempx / st->f->initial_discs);
        x = frand(st->f->width / 2) + fx;
        y = frand(st->f->height / 2) + fy;
        r = 5 + frand(st->f->maxradius);
        bt = 1;

        if ((random() % 100) < 50)
            bt = -1;

        make_disc(st->f, x, y, bt * fx / 1000.0, bt * fy / 1000.0, r);
        
    }
    
    return st;
}
Exemple #6
0
static void
moire_init_1 (struct state *st)
{
  int oncolors;
  int i;
  int fgh, bgh;
  double fgs, fgv, bgs, bgv;
  XWindowAttributes xgwa;
  XColor fgc, bgc;
  XGCValues gcv;

  XGetWindowAttributes (st->dpy, st->window, &xgwa);

  //st->delay = get_integer_resource (st->dpy, "delay", "Integer");
  //st->offset = get_integer_resource (st->dpy, "offset", "Integer");
  st->delay = delay;
  st->offset = offset;
  if (st->offset < 2) st->offset = 2;

#ifdef HAVE_XSHM_EXTENSION
  st->use_shm = get_boolean_resource(st->dpy, "useSHM", "Boolean");
#endif /*  HAVE_XSHM_EXTENSION */

 MONO:
  if (st->colors)
    {
      for (i = 0; i < st->ncolors; i++)
	XFreeColors (st->dpy, xgwa.colormap, &st->colors[i].pixel, 1, 0);
      free(st->colors);
      st->colors = 0;
    }

  if (mono_p)
    {
      st->fg_pixel = WhitePixelOfScreen (DefaultScreenOfDisplay(st->dpy));
      st->bg_pixel = BlackPixelOfScreen (DefaultScreenOfDisplay(st->dpy));
    }
  else
    {
#if 1
      st->fg_pixel = load_color(st->dpy, xgwa.colormap, foreground);
      st->bg_pixel = load_color(st->dpy, xgwa.colormap, background);
#else
      st->fg_pixel = get_pixel_resource (st->dpy,
				     xgwa.colormap, "foreground", "Foreground");
      st->bg_pixel = get_pixel_resource (st->dpy,
				     xgwa.colormap, "background", "Background");
#endif
    }

  if (mono_p)
    {
      st->offset *= 20;   /* compensate for lack of shading */
      gcv.foreground = st->fg_pixel;
    }
  else
    {
      //st->ncolors = get_integer_resource (st->dpy, "ncolors", "Integer");
      st->ncolors = ncolors;
      if (st->ncolors < 2) st->ncolors = 2;
      oncolors = st->ncolors;

      fgc.flags = bgc.flags = DoRed|DoGreen|DoBlue;
      //if (get_boolean_resource(st->dpy, "random","Boolean"))
      if (random_)
	{
	  fgc.red   = random() & 0xFFFF;
	  fgc.green = random() & 0xFFFF;
	  fgc.blue  = random() & 0xFFFF;
	  bgc.red   = random() & 0xFFFF;
	  bgc.green = random() & 0xFFFF;
	  bgc.blue  = random() & 0xFFFF;
	}
      else
	{
	  fgc.pixel = st->fg_pixel;
	  bgc.pixel = st->bg_pixel;
	  XQueryColor (st->dpy, xgwa.colormap, &fgc);
	  XQueryColor (st->dpy, xgwa.colormap, &bgc);
	}
      rgb_to_hsv (fgc.red, fgc.green, fgc.blue, &fgh, &fgs, &fgv);
      rgb_to_hsv (bgc.red, bgc.green, bgc.blue, &bgh, &bgs, &bgv);

      st->colors = (XColor *) malloc (sizeof (XColor) * (st->ncolors+2));
      memset(st->colors, 0, (sizeof (XColor) * (st->ncolors+2)));
      make_color_ramp (xgwa.screen, xgwa.visual, xgwa.colormap,
		       fgh, fgs, fgv, bgh, bgs, bgv,
		       st->colors, &st->ncolors,
		       True, True, False);
      if (st->ncolors != oncolors)
	fprintf(stderr, "%s: got %d of %d requested colors.\n",
		progname, st->ncolors, oncolors);

      if (st->ncolors <= 2)
	{
	  mono_p = True;
	  goto MONO;
	}

      gcv.foreground = st->colors[0].pixel;
    }
  st->gc = XCreateGC (st->dpy, st->window, GCForeground, &gcv);
}
Exemple #7
0
static void *
phosphor_init (Display *dpy, Window window)
{
  int i;
  unsigned long flags;
  p_state *state = (p_state *) calloc (sizeof(*state), 1);
  char *fontname = get_string_resource (dpy, "font", "Font");
  XFontStruct *font;

  state->dpy = dpy;
  state->window = window;

  XGetWindowAttributes (dpy, window, &state->xgwa);
/*  XSelectInput (dpy, window, state->xgwa.your_event_mask | ExposureMask);*/

  state->delay = get_integer_resource (dpy, "delay", "Integer");
  state->meta_sends_esc_p = get_boolean_resource (dpy, "metaSendsESC", "Boolean");
  state->swap_bs_del_p    = get_boolean_resource (dpy, "swapBSDEL",    "Boolean");

  if (!strcasecmp (fontname, "builtin") ||
      !strcasecmp (fontname, "(builtin)"))
    {
#ifndef BUILTIN_FONT
      fprintf (stderr, "%s: no builtin font\n", progname);
      state->font = XLoadQueryFont (dpy, "fixed");
#endif /* !BUILTIN_FONT */
    }
  else
    {
      state->font = XLoadQueryFont (dpy, fontname);

      if (!state->font)
        {
          fprintf(stderr, "couldn't load font \"%s\"\n", fontname);
          state->font = XLoadQueryFont (dpy, "fixed");
        }
      if (!state->font)
        {
          fprintf(stderr, "couldn't load font \"fixed\"");
          exit(1);
        }
    }

  font = state->font;
  state->scale = get_integer_resource (dpy, "scale", "Integer");
  state->ticks = STATE_MAX + get_integer_resource (dpy, "ticks", "Integer");
  state->escstate = 0;

  {
    char *s = get_string_resource (dpy, "mode", "Integer");
    state->mode = 0;
    if (!s || !*s || !strcasecmp (s, "pipe"))
      state->mode = 0;
    else if (!strcasecmp (s, "pty"))
      state->mode = 1;
    else
      fprintf (stderr, "%s: mode must be either `pipe' or `pty', not `%s'\n",
               progname, s);

#ifndef HAVE_FORKPTY
    fprintf (stderr, "%s: no pty support on this system; using -pipe mode.\n",
             progname);
    state->mode = 0;
#endif /* HAVE_FORKPTY */
  }

#if 0
  for (i = 0; i < font->n_properties; i++)
    if (font->properties[i].name == XA_FONT)
      printf ("font: %s\n", XGetAtomName(dpy, font->properties[i].card32));
#endif /* 0 */

  state->cursor_blink = get_integer_resource (dpy, "cursor", "Time");
  state->subproc_relaunch_delay =
    (1000 * get_integer_resource (dpy, "relaunch", "Time"));

# ifdef BUILTIN_FONT
  if (! font)
    {
      state->char_width  = (font6x10_width / 256) - 1;
      state->char_height = font6x10_height;
    }
  else
# endif /* BUILTIN_FONT */
    {
      state->char_width  = font->max_bounds.width;
      state->char_height = font->max_bounds.ascent + font->max_bounds.descent;
    }

  state->grid_width = state->xgwa.width / (state->char_width * state->scale);
  state->grid_height = state->xgwa.height /(state->char_height * state->scale);
  state->cells = (p_cell *) calloc (sizeof(p_cell),
                                    state->grid_width * state->grid_height);
  state->chars = (p_char **) calloc (sizeof(p_char *), 256);

  state->gcs = (GC *) calloc (sizeof(GC), state->ticks + 1);

  {
    int ncolors = MAX (0, state->ticks - 3);
    XColor *colors = (XColor *) calloc (ncolors, sizeof(XColor));
    int h1, h2;
    double s1, s2, v1, v2;

    unsigned long fg = get_pixel_resource (state->dpy, state->xgwa.colormap,
                                           "foreground", "Foreground");
    unsigned long bg = get_pixel_resource (state->dpy, state->xgwa.colormap,
                                           "background", "Background");
    unsigned long flare = get_pixel_resource (state->dpy,state->xgwa.colormap,
                                              "flareForeground", "Foreground");
    unsigned long fade = get_pixel_resource (state->dpy,state->xgwa.colormap,
                                             "fadeForeground", "Foreground");

    XColor start, end;

    start.pixel = fade;
    XQueryColor (state->dpy, state->xgwa.colormap, &start);

    end.pixel = bg;
    XQueryColor (state->dpy, state->xgwa.colormap, &end);

    /* Now allocate a ramp of colors from the main color to the background. */
    rgb_to_hsv (start.red, start.green, start.blue, &h1, &s1, &v1);
    rgb_to_hsv (end.red, end.green, end.blue, &h2, &s2, &v2);
    make_color_ramp (state->dpy, state->xgwa.colormap,
                     h1, s1, v1,
                     h2, s2, v2,
                     colors, &ncolors,
                     False, True, False);

    /* Adjust to the number of colors we actually got. */
    state->ticks = ncolors + STATE_MAX;

    /* Now, GCs all around.
     */
    state->gcv.font = (font ? font->fid : 0);
    state->gcv.cap_style = CapRound;
#ifdef FUZZY_BORDER
    state->gcv.line_width = (int) (((long) state->scale) * 1.3);
    if (state->gcv.line_width == state->scale)
      state->gcv.line_width++;
#else /* !FUZZY_BORDER */
    state->gcv.line_width = (int) (((long) state->scale) * 0.9);
    if (state->gcv.line_width >= state->scale)
      state->gcv.line_width = state->scale - 1;
    if (state->gcv.line_width < 1)
      state->gcv.line_width = 1;
#endif /* !FUZZY_BORDER */

    flags = (GCForeground | GCBackground | GCCapStyle | GCLineWidth);

    state->gcv.background = bg;
    state->gcv.foreground = bg;
    state->gcs[BLANK] = XCreateGC (state->dpy, state->window, flags,
                                   &state->gcv);

    state->gcv.foreground = flare;
    state->gcs[FLARE] = XCreateGC (state->dpy, state->window, flags,
                                   &state->gcv);

    state->gcv.foreground = fg;
    state->gcs[NORMAL] = XCreateGC (state->dpy, state->window, flags,
                                    &state->gcv);

    for (i = 0; i < ncolors; i++)
      {
        state->gcv.foreground = colors[i].pixel;
        state->gcs[STATE_MAX + i] = XCreateGC (state->dpy, state->window,
                                               flags, &state->gcv);
      }
  }

  capture_font_bits (state);

  set_cursor (state, True);

  launch_text_generator (state);
/*  clear (state);*/

  return state;
}
Exemple #8
0
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, 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
		(void) fprintf(stderr, "\ncolors:");
		for (i = 0; i < npoints; i++)
			(void) fprintf(stderr, " (%d, %.3f, %.3f)", h[i], s[i], v[i]);
		(void) fprintf(stderr, "\nlengths:");
		for (i = 0; i < npoints; i++)
			(void) 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
		(void) fprintf(stderr, "\nratios:");
		for (i = 0; i < npoints; i++)
			(void) 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] = (int) (total_ncolors * ratio[i]);


#ifdef DEBUG
		(void) fprintf(stderr, "\npixels:");
		for (i = 0; i < npoints; i++)
			(void) fprintf(stderr, " %d", ncolors[i]);
		(void) 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];
			}
		}
	}

	(void) memset(colors, 0, (*ncolorsP) * sizeof (*colors));

	k = 0;
	for (i = 0; i < npoints; i++) {
		int         distance, direction, j;

		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
		(void) fprintf(stderr, "point %d: %3d %.2f %.2f\n",
			i, h[i], s[i], v[i]);
		(void) 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
			(void) 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 (unsigned long) * ((*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;
}