Actual source code: xcolor.c


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

102:   cmap_base = 0;

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

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

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

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

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

165:   PetscFunctionBegin;
166:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-draw_x_shared_colormap", &sharedcolormap, NULL));
167:   /*
168:      Need to determine if window supports allocating a private colormap,
169:   */
170:   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))
171:     sharedcolormap = PETSC_TRUE;
172:   /*
173:      Generate the X colormap object
174:   */
175:   if (sharedcolormap) {
176:     PetscCall(PetscDrawSetUpColormap_Shared(display, screen, visual, colormap));
177:   } else {
178:     PetscCall(PetscDrawSetUpColormap_Private(display, screen, visual, colormap));
179:   }
180:   PetscFunctionReturn(PETSC_SUCCESS);
181: }

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

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

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

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

207: /*
208:     Color in X is many-layered.  The first layer is the "visual",a
209:     immutable attribute of a window set when the window is
210:     created.

212:     The next layer is the colormap.  The installation of colormaps is
213:     the business of the window manager (in some distant later release).
214: */

216: /*
217:     This routine gets the visual class (PseudoColor, etc) and returns
218:     it.  It finds the default visual.  Possible returns are
219:         PseudoColor
220:         StaticColor
221:         DirectColor
222:         TrueColor
223:         GrayScale
224:         StaticGray
225:  */
226: PetscErrorCode PetscDrawXiSetVisualClass(PetscDraw_X *XiWin)
227: {
228:   XVisualInfo vinfo;

230:   PetscFunctionBegin;
231:   if (XMatchVisualInfo(XiWin->disp, XiWin->screen, 24, DirectColor, &vinfo)) {
232:     XiWin->vis = vinfo.visual;
233:   } else if (XMatchVisualInfo(XiWin->disp, XiWin->screen, 8, PseudoColor, &vinfo)) {
234:     XiWin->vis = vinfo.visual;
235:   } else if (XMatchVisualInfo(XiWin->disp, XiWin->screen, DefaultDepth(XiWin->disp, XiWin->screen), PseudoColor, &vinfo)) {
236:     XiWin->vis = vinfo.visual;
237:   } else {
238:     XiWin->vis = DefaultVisual(XiWin->disp, XiWin->screen);
239:   }
240:   PetscFunctionReturn(PETSC_SUCCESS);
241: }

243: PetscErrorCode PetscDrawXiSetColormap(PetscDraw_X *XiWin)
244: {
245:   PetscFunctionBegin;
246:   XSetWindowColormap(XiWin->disp, XiWin->win, XiWin->cmap);
247:   PetscFunctionReturn(PETSC_SUCCESS);
248: }

250: /*
251:    Get RGB color entries out of the X colormap
252: */
253: PetscErrorCode PetscDrawXiGetPalette(PetscDraw_X *XiWin, unsigned char palette[PETSC_DRAW_MAXCOLOR][3])
254: {
255:   int    k;
256:   XColor colordef[PETSC_DRAW_MAXCOLOR];

258:   PetscFunctionBegin;
259:   for (k = 0; k < PETSC_DRAW_MAXCOLOR; k++) {
260:     colordef[k].pixel = XiWin->cmapping[k];
261:     colordef[k].flags = DoRed | DoGreen | DoBlue;
262:   }
263:   XQueryColors(XiWin->disp, XiWin->cmap, colordef, PETSC_DRAW_MAXCOLOR);
264:   for (k = 0; k < PETSC_DRAW_MAXCOLOR; k++) {
265:     palette[k][0] = (unsigned char)(colordef[k].red >> 8);
266:     palette[k][1] = (unsigned char)(colordef[k].green >> 8);
267:     palette[k][2] = (unsigned char)(colordef[k].blue >> 8);
268:   }
269:   PetscFunctionReturn(PETSC_SUCCESS);
270: }