Logo Search packages:      
Sourcecode: acm version File versions  Download package

VBindColors.c

#include "Vlib.h"
#ifdef HAVE_STRINGS_H
#include <strings.h>
#else
#include <string.h>
#endif

int _VProcessColor PARAMS((VWorkContext * cxt, Viewport * v, VColor * vc));

static char *errmsg = "Not enough pixel space for all colors\n";
static char *errmsg2 = "Unable to parse color \"%s\".\n";

/*
 *  We'll create the notion of a viewport-specific color tweaking
 *  procedure.  This procedure allows some user code to get control just
 *  before we hand the color name to XParseColor() so that we might
 *  alter the name a bit.  Why use it?  It allows us to shrink down the
 *  color space a bit on color-poor screens.
 */

void
VSetColorTweakProc(Viewport * v, void (*proc) ( /* ??? */ ))
{
      v->colorTweakProc = proc;
}

static int
pmap(long unsigned int *vec, int n)
{

      static int itbl[] =
      {1, 2, 4, 8};
      register int i, r = 0;

      for (i = 0; i < 4; ++i)
            if (itbl[i] & n)
                  r += vec[i];
      return r;
}

int
VBindColors(Viewport * v, char *background)
{

      register int i, j, k, n, c;
      static int parseComplete = 0;
      unsigned int pixel;
      VColor   *p, *bg;
      XColor   *colorSet;
      Display  *dpy;
      unsigned long planemask[PLANECOUNT * 2];
      unsigned long pixels[1];
      int       maxpcolors;
      char      realColor[64];

      maxpcolors = (v->flags & VPMono) ? 256 : v->visual->map_entries;

      dpy = v->dpy;

      _VDefaultWorkContext->nextPixel = 0;

/*
 *  If this is a color or greyscale pixmap, allocate color cells for each
 *  color, and then set up the Viewport for drawing.
 *
 *  If this is a monochrome monitor, then the aPixel value for this color is
 *  an index into our standard pixmap table rather than being a Pixel value.
 */

      if (v->flags & (VPPixmap | VPFastAnimation | VPMono | VPDoubleBuffer)) {

            bg = VAllocColor(background);

            if (_VProcessColor(_VDefaultWorkContext, v, bg) != 0) {
                  return -1;
            }

            for ((i = 0, p = _VDefaultWorkContext->VColorList); p; i++) {

                  if (i > maxpcolors) {
                        fprintf(stderr, "Too many colors selected.\n");
                        return -1;
                  }

                  if (_VProcessColor(_VDefaultWorkContext, v, p) != 0) {
                        return -1;
                  }

                  p = p->next;
            }

            v->colors = _VDefaultWorkContext->nextPixel;
            v->set = 0;
            v->pixel = v->aPixel;
            v->mask = AllPlanes;

            return 0;
      }

/*
 *  If we fall through to here, we are doing double buffering using plane
 *  masks.  This is obsolete code, but I'll leave it around for now.
 */

      colorSet = (XColor *) Vmalloc(sizeof(XColor) * maxpcolors);

      n = PLANECOUNT;
      c = 1 << n;

      if (XAllocColorCells(dpy, v->cmap, False, planemask, n * 2, pixels, 1) == 0) {
            fprintf(stderr, "Cannot allocate color cells\n");
            free((char *) colorSet);
            return -1;
      }

/*
 *  Parse background color
 */

      if ( /*parseComplete == 0 */ 1) {

            if (v->colorTweakProc) {
                  (*v->colorTweakProc) (v, background, realColor);
            }
            else {
                  strcpy(realColor, background);
            }

            if (XParseColor(dpy, v->cmap, realColor, &colorSet[0]) == 0) {
                  fprintf(stderr, errmsg2, background);
                  free(colorSet);
                  return -1;
            }

/*
 *  Parse each color defined in the V Color List
 */

            for ((i = 0, p = _VDefaultWorkContext->VColorList); p; i++) {
                  if (i > c) {
                        fprintf(stderr, "Too many colors selected.\n");
                        free(colorSet);
                        return -1;
                  }

                  if (v->colorTweakProc) {
                        (*v->colorTweakProc) (v, p->color_name, realColor);
                  }
                  else {
                        strcpy(realColor, p->color_name);
                  }

                  if (XParseColor(dpy, v->cmap, realColor, &colorSet[i + 1]) == 0) {
                        fprintf(stderr, errmsg2, p->color_name);
                        free(colorSet);
                        return -1;
                  }
                  p->cIndex = i + 1;
                  p = p->next;
            }

            parseComplete = 1;
      }

      v->colors = i + 1;

#ifdef DEBUG
      fprintf(stderr, "%d colors defined in the V color list.\n", i);
#endif

/*
 *  PAY ATTENTION!
 *
 *  We will now create a two lists of XColors. Each will expose a particular
 *  drawing buffer (there are two drawing buffers created here).
 *  A drawing is exposed by passing one of these lists to the XSetColors
 *  procedure.
 *  We create a list by iterating through each possible combination of
 *  pixel values, based on the values returned in pixel and planemask.
 *  The pixel value is determined using a function called pmap.  Each pixel
 *  value is assigned the appropriate XColor.
 */

      k = 0;
      for (i = 0; i < v->colors; ++i) {
            pixel = v->aPixel[i] = (Color) (pmap(&planemask[0], i) | pixels[0]);
            for (j = 0; j < v->colors; ++j) {
                  v->aColor[k] = colorSet[i];
                  v->aColor[k++].pixel = pixel | pmap(&planemask[n], j);
            }
      }

      v->aMask = pmap(&planemask[0], (c - 1)) | pixels[0];

      k = 0;
      for (i = 0; i < v->colors; ++i) {
            pixel = v->bPixel[i] = (Color) (pmap(&planemask[n], i) | pixels[0]);
            for (j = 0; j < v->colors; ++j) {
                  v->bColor[k] = colorSet[i];
                  v->bColor[k++].pixel = pixel | pmap(&planemask[0], j);
            }
      }

      v->bMask = pmap(&planemask[n], (c - 1)) | pixels[0];

      free(colorSet);
      return 0;
}

int
_VProcessColor(VWorkContext * cxt, Viewport * v, VColor * vc)
{
      char      realColor[256];
      Display  *dpy = v->dpy;
      XColor    xcolor, xcolor2, hcolor;
      double    d;
      int       i, swap = 0;
      unsigned long temp;

/*
 *  First, if we are doing any depth cueing, insure that the haze color has
 *  been converted to RGB values.
 */

      if (cxt->depthCueSteps > 1 && (v->flags & VPDepthCueParsed) == 0) {

            if (v->colorTweakProc) {
                  (*v->colorTweakProc) (v, cxt->depthCueColor->color_name,
                                                  realColor);
            }
            else {
                  strcpy(realColor, cxt->depthCueColor->color_name);
            }

            if (XParseColor(dpy, v->cmap,
                        realColor, &hcolor) == 0) {
                  fprintf(stderr, errmsg2,
                        cxt->depthCueColor->color_name);
                  return -1;
            }

            if (v->AllocColor(v, v->cmap, &hcolor) == 0) {
                  fprintf(stderr, errmsg);
                  return -1;
              }

            cxt->depthCueColor->cIndex = cxt->nextPixel;
            v->aPixel[cxt->nextPixel++] = hcolor.pixel;
            v->xdepthCueColor = hcolor;
            v->flags |= VPDepthCueParsed;
            swap = 1;
      }

/*
 *  Now parse this color.
 */

      if (v->colorTweakProc) {
            (*v->colorTweakProc) (v, vc->color_name, realColor);
      }
      else {
            strcpy(realColor, vc->color_name);
      }

      if (XParseColor(dpy, v->cmap, realColor, &xcolor) == 0) {
            fprintf(stderr, errmsg2, vc->color_name);
            return -1;
      }

      if (v->flags & VPMono) {
            vc->cIndex = cxt->nextPixel;
            v->aPixel[cxt->nextPixel++] = (
                                                              xcolor.red * 299L +
                                                              xcolor.green * 587L +
                                                       xcolor.blue * 114L) / (1000 * 8192);
      }
      else if (v->flags & VPDepthCueing && cxt->depthCueSteps > 1 &&
                   vc->flags & ColorEnableDepthCueing) {
            vc->cIndex = cxt->nextPixel;
            hcolor = v->xdepthCueColor;
            for (i = 0; i < cxt->depthCueSteps - 1; ++i) {
                  d = (double) i / (double) cxt->depthCueSteps;
                  xcolor2.red = (unsigned short) (xcolor.red * (1.0 - d) + hcolor.red * d);
                  xcolor2.green = (unsigned short) (xcolor.green * (1.0 - d) + hcolor.green * d);
                  xcolor2.blue = (unsigned short) (xcolor.blue * (1.0 - d) + hcolor.blue * d);
                  xcolor2.flags = xcolor.flags;
                  if (v->AllocColor(v, v->cmap, &xcolor2) == 0) {
                        fprintf(stderr, errmsg);
                        return -1;
                  }
                  v->aPixel[cxt->nextPixel++] = xcolor2.pixel;
      
            }
      }
      else {
            if (v->AllocColor(v, v->cmap, &xcolor) == 0) {
                  fprintf(stderr, errmsg);
                  return -1;
            }
            vc->cIndex = cxt->nextPixel;
            v->aPixel[cxt->nextPixel++] = xcolor.pixel;
      }

/*
 *  Sorry for the hack, but here goes ...
 *
 *  The background color in the V library is a bit of an orphan.  It is
 *  defined when VBindColors is called.  There are parts of the V library
 *  that assume that v->aPixel[0] is the pixel value of the background color,
 *  but that is not true at this point in time if we just got through parsing
 *  the depth cue color.  By swapping the aPixel[0] and aPixel[1] values
 *  (and updating the corresponding VColor entries that point to them), we
 *  an hack around the problem.
 */

      if (swap) {
            temp = v->aPixel[0];
            v->aPixel[0] = v->aPixel[1];
            v->aPixel[1] = (Color) temp;
            temp = cxt->depthCueColor->cIndex;
            cxt->depthCueColor->cIndex = vc->cIndex;
            vc->cIndex = (Color) temp;
      }

      return 0;
}

Generated by  Doxygen 1.6.0   Back to index