Actual source code: xcolor.c

      1: /*
      2:     Code for managing color the X implementation of the PetscDraw routines.

      4:     Currently we default to using cmapping[0 to PETSC_DRAW_BASIC_COLORS-1] for the basic colors and
      5:     cmapping[DRAW_BASIC_COLORS to 255] for contour plots.

      7: */
      8: #include <../src/sys/classes/draw/impls/x/ximpl.h>
      9: #include <X11/Xatom.h>

     11: static const char *colornames[PETSC_DRAW_BASIC_COLORS] = {"white",   "black",     "red",      "green",      "cyan",      "blue",       "magenta",   "aquamarine",      "forestgreen", "orange",        "violet",
     12:                                                           "brown",   "pink",      "coral",    "gray",       "yellow",    "gold",       "lightpink", "mediumturquoise", "khaki",       "dimgray",       "yellowgreen",
     13:                                                           "skyblue", "darkgreen", "navyblue", "sandybrown", "cadetblue", "powderblue", "deeppink",  "thistle",         "limegreen",   "lavenderblush", "plum"};

     15: /*
     16:    Sets up a color map for a display. This is shared by all the windows
     17:   opened on that display; this is to save time when windows are open so
     18:   each one does not have to create its own color map which can take 15 to 20 seconds

     20:      This is new code written 2/26/1999 Barry Smith,I hope it can replace
     21:   some older,rather confusing code.

     23:      The calls to XAllocNamedColor() and XAllocColor() are very slow
     24:      because we have to request from the X server for each
     25:      color. Could not figure out a way to request a large number at the
     26:      same time.

     28:    IMPORTANT: this code will fail if user opens windows on two different
     29:   displays: should add error checking to detect this. This is because all windows
     30:   share the same gColormap and gCmapping.

     32: */
     33: static Colormap          gColormap = 0;
     34: static PetscDrawXiPixVal gCmapping[PETSC_DRAW_MAXCOLOR];
     35: static unsigned char     gCpalette[PETSC_DRAW_MAXCOLOR][3];

     37: static PetscErrorCode PetscDrawSetUpColormap_Shared(Display *display, int screen, Visual *visual, Colormap colormap)
     38: {
     39:   int           i, k, ncolors = PETSC_DRAW_MAXCOLOR - PETSC_DRAW_BASIC_COLORS;
     40:   unsigned char R[PETSC_DRAW_MAXCOLOR - PETSC_DRAW_BASIC_COLORS];
     41:   unsigned char G[PETSC_DRAW_MAXCOLOR - PETSC_DRAW_BASIC_COLORS];
     42:   unsigned char B[PETSC_DRAW_MAXCOLOR - PETSC_DRAW_BASIC_COLORS];
     43:   XColor        colordef, ecolordef;
     44:   PetscBool     fast = PETSC_FALSE;

     46:   PetscFunctionBegin;
     47:   if (colormap) gColormap = colormap;
     48:   else gColormap = DefaultColormap(display, screen);

     50:   /* set the basic colors into the color map */
     51:   for (i = 0; i < PETSC_DRAW_BASIC_COLORS; i++) {
     52:     XAllocNamedColor(display, gColormap, colornames[i], &colordef, &ecolordef);
     53:     gCmapping[i]    = colordef.pixel;
     54:     gCpalette[i][0] = (unsigned char)(colordef.red >> 8);
     55:     gCpalette[i][1] = (unsigned char)(colordef.green >> 8);
     56:     gCpalette[i][2] = (unsigned char)(colordef.blue >> 8);
     57:   }

     59:   /* set the contour colors into the colormap */
     60:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-draw_fast", &fast, NULL));
     61:   PetscCall(PetscDrawUtilitySetCmap(NULL, ncolors, R, G, B));
     62:   for (i = 0, k = PETSC_DRAW_BASIC_COLORS; i < ncolors; i++, k++) {
     63:     colordef.red   = (unsigned short)(R[i] << 8);
     64:     colordef.green = (unsigned short)(G[i] << 8);
     65:     colordef.blue  = (unsigned short)(B[i] << 8);
     66:     colordef.flags = DoRed | DoGreen | DoBlue;
     67:     colordef.pixel = gCmapping[PETSC_DRAW_BLACK];
     68:     if (!fast) XAllocColor(display, gColormap, &colordef);
     69:     gCmapping[k]    = colordef.pixel;
     70:     gCpalette[k][0] = R[i];
     71:     gCpalette[k][1] = G[i];
     72:     gCpalette[k][2] = B[i];
     73:   }

     75:   PetscCall(PetscInfo(NULL, "Successfully allocated colors\n"));
     76:   PetscFunctionReturn(PETSC_SUCCESS);
     77: }

     79: /*
     80:     Keep a record of which pixel numbers in the cmap have been
     81:   used so far; this is to allow us to try to reuse as much of the current
     82:   colormap as possible.
     83: */
     84: static PetscBool cmap_pixvalues_used[PETSC_DRAW_MAXCOLOR];
     85: static int       cmap_base = 0;

     87: static PetscErrorCode PetscDrawSetUpColormap_Private(Display *display, int screen, Visual *visual, Colormap colormap)
     88: {
     89:   int           found, i, k, ncolors = PETSC_DRAW_MAXCOLOR - PETSC_DRAW_BASIC_COLORS;
     90:   unsigned char R[PETSC_DRAW_MAXCOLOR - PETSC_DRAW_BASIC_COLORS];
     91:   unsigned char G[PETSC_DRAW_MAXCOLOR - PETSC_DRAW_BASIC_COLORS];
     92:   unsigned char B[PETSC_DRAW_MAXCOLOR - PETSC_DRAW_BASIC_COLORS];
     93:   Colormap      defaultmap = DefaultColormap(display, screen);
     94:   XColor        colordef;
     95:   PetscBool     fast = PETSC_FALSE;

     97:   PetscFunctionBegin;
     98:   if (colormap) gColormap = colormap;
     99:   else gColormap = XCreateColormap(display, RootWindow(display, screen), visual, AllocAll);

    101:   cmap_base = 0;

    103:   PetscCall(PetscMemzero(cmap_pixvalues_used, sizeof(cmap_pixvalues_used)));

    105:   /* set the basic colors into the color map */
    106:   for (i = 0; i < PETSC_DRAW_BASIC_COLORS; i++) {
    107:     XParseColor(display, gColormap, colornames[i], &colordef);
    108:     /* try to allocate the color in the default-map */
    109:     found = XAllocColor(display, defaultmap, &colordef);
    110:     /* use it, if it exists and is not already used in the new colormap */
    111:     if (found && colordef.pixel < PETSC_DRAW_MAXCOLOR && !cmap_pixvalues_used[colordef.pixel]) {
    112:       cmap_pixvalues_used[colordef.pixel] = PETSC_TRUE;
    113:       /* otherwise search for the next available slot */
    114:     } else {
    115:       while (cmap_pixvalues_used[cmap_base]) cmap_base++;
    116:       colordef.pixel                   = cmap_base;
    117:       cmap_pixvalues_used[cmap_base++] = PETSC_TRUE;
    118:     }
    119:     XStoreColor(display, gColormap, &colordef);
    120:     gCmapping[i]    = colordef.pixel;
    121:     gCpalette[i][0] = (unsigned char)(colordef.red >> 8);
    122:     gCpalette[i][1] = (unsigned char)(colordef.green >> 8);
    123:     gCpalette[i][2] = (unsigned char)(colordef.blue >> 8);
    124:   }

    126:   /* set the contour colors into the colormap */
    127:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-draw_fast", &fast, NULL));
    128:   PetscCall(PetscDrawUtilitySetCmap(NULL, ncolors, R, G, B));
    129:   for (i = 0, k = PETSC_DRAW_BASIC_COLORS; i < ncolors; i++, k++) {
    130:     colordef.red   = (unsigned short)(R[i] << 8);
    131:     colordef.green = (unsigned short)(G[i] << 8);
    132:     colordef.blue  = (unsigned short)(B[i] << 8);
    133:     colordef.flags = DoRed | DoGreen | DoBlue;
    134:     colordef.pixel = gCmapping[PETSC_DRAW_BLACK];
    135:     if (!fast) {
    136:       /* try to allocate the color in the default-map */
    137:       found = XAllocColor(display, defaultmap, &colordef);
    138:       /* use it, if it exists and is not already used in the new colormap */
    139:       if (found && colordef.pixel < PETSC_DRAW_MAXCOLOR && !cmap_pixvalues_used[colordef.pixel]) {
    140:         cmap_pixvalues_used[colordef.pixel] = PETSC_TRUE;
    141:         /* otherwise search for the next available slot */
    142:       } else {
    143:         while (cmap_pixvalues_used[cmap_base]) cmap_base++;
    144:         colordef.pixel                   = cmap_base;
    145:         cmap_pixvalues_used[cmap_base++] = PETSC_TRUE;
    146:       }
    147:       XStoreColor(display, gColormap, &colordef);
    148:     }
    149:     gCmapping[k]    = colordef.pixel;
    150:     gCpalette[k][0] = R[i];
    151:     gCpalette[k][1] = G[i];
    152:     gCpalette[k][2] = B[i];
    153:   }

    155:   PetscCall(PetscInfo(NULL, "Successfully allocated colors\n"));
    156:   PetscFunctionReturn(PETSC_SUCCESS);
    157: }

    159: static PetscErrorCode PetscDrawSetUpColormap_X(Display *display, int screen, Visual *visual, Colormap colormap)
    160: {
    161:   PetscBool   sharedcolormap = PETSC_FALSE;
    162:   XVisualInfo vinfo;

    164:   PetscFunctionBegin;
    165:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-draw_x_shared_colormap", &sharedcolormap, NULL));
    166:   /*
    167:      Need to determine if window supports allocating a private colormap,
    168:   */
    169:   if (XMatchVisualInfo(display, screen, 24, StaticColor, &vinfo) || XMatchVisualInfo(display, screen, 24, TrueColor, &vinfo) || XMatchVisualInfo(display, screen, 16, StaticColor, &vinfo) || XMatchVisualInfo(display, screen, 16, TrueColor, &vinfo) || XMatchVisualInfo(display, screen, 15, StaticColor, &vinfo) || XMatchVisualInfo(display, screen, 15, TrueColor, &vinfo))
    170:     sharedcolormap = PETSC_TRUE;
    171:   /*
    172:      Generate the X colormap object
    173:   */
    174:   if (sharedcolormap) {
    175:     PetscCall(PetscDrawSetUpColormap_Shared(display, screen, visual, colormap));
    176:   } else {
    177:     PetscCall(PetscDrawSetUpColormap_Private(display, screen, visual, colormap));
    178:   }
    179:   PetscFunctionReturn(PETSC_SUCCESS);
    180: }

    182: PETSC_INTERN PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X *, Colormap);

    184: PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X *XiWin, Colormap colormap)
    185: {
    186:   PetscBool fast = PETSC_FALSE;

    188:   PetscFunctionBegin;
    189:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-draw_fast", &fast, NULL));
    190:   PetscCheck(XiWin->depth >= 8, PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "PETSc Graphics require monitors with at least 8 bit color (256 colors)");
    191:   if (!gColormap) PetscCall(PetscDrawSetUpColormap_X(XiWin->disp, XiWin->screen, XiWin->vis, colormap));
    192:   XiWin->cmap     = gColormap;
    193:   XiWin->cmapsize = fast ? PETSC_DRAW_BASIC_COLORS : PETSC_DRAW_MAXCOLOR;
    194:   PetscCall(PetscMemcpy(XiWin->cmapping, gCmapping, sizeof(XiWin->cmapping)));
    195:   PetscCall(PetscMemcpy(XiWin->cpalette, gCpalette, sizeof(XiWin->cpalette)));
    196:   XiWin->background = XiWin->cmapping[PETSC_DRAW_WHITE];
    197:   XiWin->foreground = XiWin->cmapping[PETSC_DRAW_BLACK];
    198:   PetscFunctionReturn(PETSC_SUCCESS);
    199: }

    201: PetscErrorCode PetscDrawXiColormap(PetscDraw_X *XiWin)
    202: {
    203:   return PetscDrawSetColormap_X(XiWin, (Colormap)0);
    204: }