Actual source code: xcolor.c

petsc-3.5.4 2015-05-23
Report Typos and Errors
  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 a uniform hue of all the colors. But in the contour
  7:   plot we only use from PETSC_DRAW_BASIC_COLORS to 240 since the ones beyond that are too dark.

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

 13: static const char *(colornames[PETSC_DRAW_BASIC_COLORS]) = {"white",
 14:                                                             "black",
 15:                                                             "red",
 16:                                                             "green",
 17:                                                             "cyan",
 18:                                                             "blue",
 19:                                                             "magenta",
 20:                                                             "aquamarine",
 21:                                                             "forestgreen",
 22:                                                             "orange",
 23:                                                             "violet",
 24:                                                             "brown",
 25:                                                             "pink",
 26:                                                             "coral",
 27:                                                             "gray",
 28:                                                             "yellow",
 29:                                                             "gold",
 30:                                                             "lightpink",
 31:                                                             "mediumturquoise",
 32:                                                             "khaki",
 33:                                                             "dimgray",
 34:                                                             "yellowgreen",
 35:                                                             "skyblue",
 36:                                                             "darkgreen",
 37:                                                             "navyblue",
 38:                                                             "sandybrown",
 39:                                                             "cadetblue",
 40:                                                             "powderblue",
 41:                                                             "deeppink",
 42:                                                             "thistle",
 43:                                                             "limegreen",
 44:                                                             "lavenderblush",
 45:                                                             "plum"};

 47: extern PetscErrorCode PetscDrawXiInitCmap(PetscDraw_X*);
 48: extern PetscErrorCode PetscDrawXiGetVisualClass(PetscDraw_X*);

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

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

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

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

 67: */
 68: static Colormap          gColormap = 0;
 69: static PetscDrawXiPixVal gCmapping[256];

 73: PetscErrorCode PetscDrawSetUpColormap_Shared(Display *display,int screen,Visual *visual,Colormap colormap)
 74: {
 75:   XColor         colordef,ecolordef;
 76:   unsigned char  *red,*green,*blue;
 77:   int            i,ncolors;
 79:   PetscBool      fast = PETSC_FALSE;

 82:   if (colormap) gColormap = colormap;
 83:   else          gColormap = DefaultColormap(display,screen);

 85:   /* set the basic colors into the color map */
 86:   for (i=0; i<PETSC_DRAW_BASIC_COLORS; i++) {
 87:     XAllocNamedColor(display,gColormap,colornames[i],&colordef,&ecolordef);
 88:     gCmapping[i] = colordef.pixel;
 89:   }

 91:   /* set the uniform hue colors into the color map */
 92:   ncolors = 256-PETSC_DRAW_BASIC_COLORS;
 93:   PetscMalloc3(ncolors,&red,ncolors,&green,ncolors,&blue);
 94:   PetscDrawUtilitySetCmapHue(red,green,blue,ncolors);
 95:   PetscOptionsGetBool(NULL,"-draw_fast",&fast,NULL);
 96:   if (!fast) {
 97:     for (i=PETSC_DRAW_BASIC_COLORS; i<ncolors+PETSC_DRAW_BASIC_COLORS; i++) {
 98:       colordef.red   = ((int)red[i-PETSC_DRAW_BASIC_COLORS]   * 65535) / 255;
 99:       colordef.green = ((int)green[i-PETSC_DRAW_BASIC_COLORS] * 65535) / 255;
100:       colordef.blue  = ((int)blue[i-PETSC_DRAW_BASIC_COLORS]  * 65535) / 255;
101:       colordef.flags = DoRed | DoGreen | DoBlue;
102:       XAllocColor(display,gColormap,&colordef);
103:       gCmapping[i]   = colordef.pixel;
104:     }
105:   }
106:   PetscFree3(red,green,blue);
107:   PetscInfo(0,"Successfully allocated colors\n");
108:   return(0);
109: }

111: /*
112:     Keep a record of which pixel numbers in the cmap have been
113:   used so far; this is to allow us to try to reuse as much of the current
114:   colormap as possible.
115: */
116: static PetscBool cmap_pixvalues_used[256];
117: static int       cmap_base = 0;

121: PetscErrorCode PetscDrawSetUpColormap_Private(Display *display,int screen,Visual *visual,Colormap colormap)
122: {
123:   Colormap       defaultmap = DefaultColormap(display,screen);
125:   int            found,i,ncolors;
126:   XColor         colordef;
127:   unsigned char  *red,*green,*blue;
128:   PetscBool      fast = PETSC_FALSE;

131:   if (colormap) gColormap = colormap;
132:   else          gColormap = XCreateColormap(display,RootWindow(display,screen),visual,AllocAll);

134:   cmap_base = 0;

136:   PetscMemzero(cmap_pixvalues_used,256*sizeof(PetscBool));

138:   /* set the basic colors into the color map */
139:   for (i=0; i<PETSC_DRAW_BASIC_COLORS; i++) {
140:     XParseColor(display,gColormap,colornames[i],&colordef);
141:     /* try to allocate the color in the default-map */
142:     found = XAllocColor(display,defaultmap,&colordef);
143:     /* use it, if it it exists and is not already used in the new colormap */
144:     if (found && colordef.pixel < 256  && !cmap_pixvalues_used[colordef.pixel]) {
145:       cmap_pixvalues_used[colordef.pixel] = PETSC_TRUE;
146:       /* otherwise search for the next available slot */
147:     } else {
148:       while (cmap_pixvalues_used[cmap_base]) cmap_base++;
149:       colordef.pixel                   = cmap_base;
150:       cmap_pixvalues_used[cmap_base++] = PETSC_TRUE;
151:     }
152:     XStoreColor(display,gColormap,&colordef);
153:     gCmapping[i] = colordef.pixel;
154:   }

156:   /* set the uniform hue colors into the color map */
157:   ncolors = 256-PETSC_DRAW_BASIC_COLORS;
158:   PetscMalloc3(ncolors,&red,ncolors,&green,ncolors,&blue);
159:   PetscDrawUtilitySetCmapHue(red,green,blue,ncolors);
160:   PetscOptionsGetBool(NULL,"-draw_fast",&fast,NULL);
161:   if (!fast) {
162:     for (i=PETSC_DRAW_BASIC_COLORS; i<ncolors+PETSC_DRAW_BASIC_COLORS; i++) {
163:       colordef.red   = ((int)red[i-PETSC_DRAW_BASIC_COLORS]   * 65535) / 255;
164:       colordef.green = ((int)green[i-PETSC_DRAW_BASIC_COLORS] * 65535) / 255;
165:       colordef.blue  = ((int)blue[i-PETSC_DRAW_BASIC_COLORS]  * 65535) / 255;
166:       colordef.flags = DoRed | DoGreen | DoBlue;
167:       /* try to allocate the color in the default-map */
168:       found = XAllocColor(display,defaultmap,&colordef);
169:       /* use it, if it it exists and is not already used in the new colormap */
170:       if (found && colordef.pixel < 256  && !cmap_pixvalues_used[colordef.pixel]) {
171:         cmap_pixvalues_used[colordef.pixel] = PETSC_TRUE;
172:         /* otherwise search for the next available slot */
173:       } else {
174:         while (cmap_pixvalues_used[cmap_base]) cmap_base++;
175:         colordef.pixel                   = cmap_base;
176:         cmap_pixvalues_used[cmap_base++] = PETSC_TRUE;
177:       }
178:       XStoreColor(display,gColormap,&colordef);
179:       gCmapping[i] = colordef.pixel;
180:     }
181:   }
182:   PetscFree3(red,green,blue);
183:   PetscInfo(0,"Successfully allocated colors\n");
184:   return(0);
185: }

189: PetscErrorCode PetscDrawSetUpColormap_X(Display *display,int screen,Visual *visual,Colormap colormap)
190: {
192:   PetscBool      sharedcolormap = PETSC_FALSE;
193:   XVisualInfo    vinfo;

196:   PetscOptionsGetBool(NULL,"-draw_x_shared_colormap",&sharedcolormap,NULL);
197:   /*
198:         Need to determine if window supports allocating a private colormap,
199:   */
200:   if (XMatchVisualInfo(display,screen,24,StaticColor,&vinfo) ||
201:       XMatchVisualInfo(display,screen,24,TrueColor,&vinfo)   ||
202:       XMatchVisualInfo(display,screen,16,StaticColor,&vinfo) ||
203:       XMatchVisualInfo(display,screen,16,TrueColor,&vinfo)   ||
204:       XMatchVisualInfo(display,screen,15,StaticColor,&vinfo) ||
205:       XMatchVisualInfo(display,screen,15,TrueColor,&vinfo)) sharedcolormap = PETSC_TRUE;

207:   /* generate the X color map object */
208:   if (sharedcolormap) {
209:     PetscDrawSetUpColormap_Shared(display,screen,visual,colormap);
210:   } else {
211:     PetscDrawSetUpColormap_Private(display,screen,visual,colormap);
212:   }
213:   return(0);
214: }

218: PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X *XiWin,char *host,Colormap colormap)
219: {

223:   if (XiWin->depth < 8) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"PETSc Graphics require monitors with at least 8 bit color (256 colors)");
224:   if (!gColormap) {
225:     Display *display;   /* Private display will exist forever contains colormap shared by all windows */
226:     int     screen;
227:     Visual  *vis;

229:     display = XOpenDisplay(host);
230:     screen  = DefaultScreen(display);
231:     vis     = DefaultVisual(display,screen);

233:     PetscDrawSetUpColormap_X(display,screen,vis,colormap);
234:   }
235:   XiWin->cmap       = gColormap;
236:   PetscMemcpy(XiWin->cmapping,gCmapping,256*sizeof(PetscDrawXiPixVal));
237:   XiWin->background = XiWin->cmapping[PETSC_DRAW_WHITE];
238:   XiWin->foreground = XiWin->cmapping[PETSC_DRAW_BLACK];
239:   return(0);
240: }

242: /*
243:     Color in X is many-layered.  The first layer is the "visual",a
244:     immutable attribute of a window set when the window is
245:     created.

247:     The next layer is the colormap.  The installation of colormaps is
248:     the buisness of the window manager (in some distant later release).
249: */

251: /*
252:     This routine gets the visual class (PseudoColor, etc) and returns
253:     it.  It finds the default visual.  Possible returns are
254:         PseudoColor
255:         StaticColor
256:         DirectColor
257:         TrueColor
258:         GrayScale
259:         StaticGray
260:  */
263: PetscErrorCode PetscDrawXiSetVisualClass(PetscDraw_X *XiWin)
264: {
265:   XVisualInfo vinfo;

268:   if (XMatchVisualInfo(XiWin->disp,XiWin->screen,24,DirectColor,&vinfo)) {
269:     XiWin->vis = vinfo.visual;
270:   } else if (XMatchVisualInfo(XiWin->disp,XiWin->screen,8,PseudoColor,&vinfo)) {
271:     XiWin->vis = vinfo.visual;
272:   } else if (XMatchVisualInfo(XiWin->disp,XiWin->screen,DefaultDepth(XiWin->disp,XiWin->screen),PseudoColor,&vinfo)) {
273:     XiWin->vis = vinfo.visual;
274:   } else {
275:     XiWin->vis = DefaultVisual(XiWin->disp,XiWin->screen);
276:   }
277:   return(0);
278: }

282: PetscErrorCode PetscDrawXiGetVisualClass(PetscDraw_X *XiWin)
283: {
285: #if defined(__cplusplus)
286:   PetscFunctionReturn(XiWin->vis->c_class);
287: #else
288:   PetscFunctionReturn(XiWin->vis->class);
289: #endif
290: }


295: PetscErrorCode PetscDrawXiSetColormap(PetscDraw_X *XiWin)
296: {
298:   XSetWindowColormap(XiWin->disp,XiWin->win,XiWin->cmap);
299:   return(0);
300: }

304: PetscErrorCode PetscDrawXiGetBaseColor(PetscDraw_X *XiWin,PetscDrawXiPixVal *white_pix,PetscDrawXiPixVal *black_pix)
305: {
307:   *white_pix = XiWin->cmapping[PETSC_DRAW_WHITE];
308:   *black_pix = XiWin->cmapping[PETSC_DRAW_BLACK];
309:   return(0);
310: }

312: /*
313:     This routine returns the pixel value for the specified color
314:     Returns 0 on failure,<>0 otherwise.
315:  */
318: PetscErrorCode PetscDrawXiFindColor(PetscDraw_X *XiWin,char *name,PetscDrawXiPixVal *pixval)
319: {
320:   XColor colordef;
321:   int    st;

324:   st = XParseColor(XiWin->disp,XiWin->cmap,name,&colordef);
325:   if (st) {
326:     st = XAllocColor(XiWin->disp,XiWin->cmap,&colordef);
327:     if (st) *pixval = colordef.pixel;
328:   }
329:   PetscFunctionReturn(st);
330: }

332: /*
333:     Another real need is to assign "colors" that make sense for
334:     a monochrome display,without unduely penalizing color displays.
335:     This routine takes a color name,a window, and a flag that
336:     indicates whether this is "background" or "foreground".
337:     In the monchrome case (or if the color is otherwise unavailable),
338:     the "background" or "foreground" colors will be chosen
339:  */
342: PetscDrawXiPixVal PetscDrawXiGetColor(PetscDraw_X* XiWin,char *name,int is_fore)
343: {
344:   PetscDrawXiPixVal pixval;

347:   if (XiWin->numcolors == 2 || !PetscDrawXiFindColor(XiWin,name,&pixval)) {
348:     pixval = is_fore ? XiWin->cmapping[PETSC_DRAW_WHITE] : XiWin->cmapping[PETSC_DRAW_BLACK];
349:   }
350:   PetscFunctionReturn(pixval);
351: }