Actual source code: xcolor.c

petsc-3.3-p5 2012-12-01
  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/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,unsigned char,&red,ncolors,unsigned char,&green,ncolors,unsigned char,&blue);
 94:   PetscDrawUtilitySetCmapHue(red,green,blue,ncolors);
 95:   PetscOptionsGetBool(PETSC_NULL,"-draw_fast",&fast,PETSC_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;


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

135:   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,unsigned char,&red,ncolors,unsigned char,&green,ncolors,unsigned char,&blue);
159:   PetscDrawUtilitySetCmapHue(red,green,blue,ncolors);
160:   PetscOptionsGetBool(PETSC_NULL,"-draw_fast",&fast,PETSC_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(PETSC_NULL,"-draw_x_shared_colormap",&sharedcolormap,PETSC_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)) {
206:     sharedcolormap = PETSC_TRUE;
207:   }

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

220: PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X* XiWin,char *host,Colormap colormap)
221: {

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

231:     display = XOpenDisplay(host);
232:     screen  = DefaultScreen(display);
233:     vis     = DefaultVisual(display,screen);

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

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

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

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

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

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


298: PetscErrorCode PetscDrawXiSetColormap(PetscDraw_X* XiWin)
299: {
301:   XSetWindowColormap(XiWin->disp,XiWin->win,XiWin->cmap);
302:   return(0);
303: }

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

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

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

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

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