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 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"};


 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 PixVal    gCmapping[256];
 70:        int       gNumcolors = 0;

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

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

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

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

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

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


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

136:   cmap_base = 0;
137:   PetscMemzero(cmap_pixvalues_used,256*sizeof(PetscBool));

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

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

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

197:   /* 
198:      This is wrong; it needs to take the value from the visual 
199:   */
200:   gNumcolors = 1 << DefaultDepth(display,screen);

202:   PetscOptionsGetBool(PETSC_NULL,"-draw_x_shared_colormap",&sharedcolormap,PETSC_NULL);
203:   /*
204:         Need to determine if window supports allocating a private colormap,
205:   */
206:   if (XMatchVisualInfo(display,screen,24,StaticColor,&vinfo) ||
207:       XMatchVisualInfo(display,screen,24,TrueColor,&vinfo)   ||
208:       XMatchVisualInfo(display,screen,16,StaticColor,&vinfo) ||
209:       XMatchVisualInfo(display,screen,16,TrueColor,&vinfo)   ||
210:       XMatchVisualInfo(display,screen,15,StaticColor,&vinfo) ||
211:       XMatchVisualInfo(display,screen,15,TrueColor,&vinfo)) {
212:     sharedcolormap = PETSC_TRUE;
213:   }

215:   /* generate the X color map object */
216:   if (sharedcolormap) {
217:     PetscDrawSetUpColormap_Shared(display,screen,visual,colormap);
218:   } else {
219:     PetscDrawSetUpColormap_Private(display,screen,visual,colormap);
220:   }
221:   return(0);
222: }

226: PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X* XiWin,char *host,Colormap colormap)
227: {

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

237:     display = XOpenDisplay(host);
238:     screen  = DefaultScreen(display);
239:     vis     = DefaultVisual(display,screen);

241:     PetscDrawSetUpColormap_X(display,screen,vis,colormap);
242:   }
243:   XiWin->cmap = gColormap;
244:   PetscMemcpy(XiWin->cmapping,gCmapping,256*sizeof(PixVal));
245:   XiWin->background = XiWin->cmapping[PETSC_DRAW_WHITE];
246:   XiWin->foreground = XiWin->cmapping[PETSC_DRAW_BLACK];
247:   return(0);
248: }

250: /*
251:     Color in X is many-layered.  The first layer is the "visual",a
252:     immutable attribute of a window set when the window is
253:     created.

255:     The next layer is the colormap.  The installation of colormaps is
256:     the buisness of the window manager (in some distant later release).
257: */

259: /*
260:     This routine gets the visual class (PseudoColor, etc) and returns
261:     it.  It finds the default visual.  Possible returns are
262:         PseudoColor
263:         StaticColor
264:         DirectColor
265:         TrueColor
266:         GrayScale
267:         StaticGray
268:  */
271: PetscErrorCode XiSetVisualClass(PetscDraw_X* XiWin)
272: {
273:   XVisualInfo vinfo;

276:   if (XMatchVisualInfo(XiWin->disp,XiWin->screen,24,DirectColor,&vinfo)) {
277:     XiWin->vis    = vinfo.visual;
278:   } else if (XMatchVisualInfo(XiWin->disp,XiWin->screen,8,PseudoColor,&vinfo)) {
279:     XiWin->vis    = vinfo.visual;
280:   } else if (XMatchVisualInfo(XiWin->disp,XiWin->screen,
281:     DefaultDepth(XiWin->disp,XiWin->screen),PseudoColor,&vinfo)) {
282:     XiWin->vis    = vinfo.visual;
283:   } else {
284:     XiWin->vis    = DefaultVisual(XiWin->disp,XiWin->screen);
285:   }
286:   return(0);
287: }

291: PetscErrorCode XiGetVisualClass(PetscDraw_X* XiWin)
292: {
294: #if defined(__cplusplus)
295:   PetscFunctionReturn(XiWin->vis->c_class);
296: #else
297:   PetscFunctionReturn(XiWin->vis->class);
298: #endif
299: }


304: PetscErrorCode XiSetColormap(PetscDraw_X* XiWin)
305: {
307:   XSetWindowColormap(XiWin->disp,XiWin->win,XiWin->cmap);
308:   return(0);
309: }

313: PetscErrorCode XiGetBaseColor(PetscDraw_X* XiWin,PixVal* white_pix,PixVal* black_pix)
314: {
316:   *white_pix  = XiWin->cmapping[PETSC_DRAW_WHITE];
317:   *black_pix  = XiWin->cmapping[PETSC_DRAW_BLACK];
318:   return(0);
319: }

321: /*
322:     This routine returns the pixel value for the specified color
323:     Returns 0 on failure,<>0 otherwise.
324:  */
327: PetscErrorCode XiFindColor(PetscDraw_X *XiWin,char *name,PixVal *pixval)
328: {
329:   XColor   colordef;
330:   int      st;

333:   st = XParseColor(XiWin->disp,XiWin->cmap,name,&colordef);
334:   if (st) {
335:     st  = XAllocColor(XiWin->disp,XiWin->cmap,&colordef);
336:     if (st)  *pixval = colordef.pixel;
337:   }
338:   PetscFunctionReturn(st);
339: }

341: /*
342:     Another real need is to assign "colors" that make sense for
343:     a monochrome display,without unduely penalizing color displays.
344:     This routine takes a color name,a window, and a flag that
345:     indicates whether this is "background" or "foreground".
346:     In the monchrome case (or if the color is otherwise unavailable),
347:     the "background" or "foreground" colors will be chosen
348:  */
351: PixVal XiGetColor(PetscDraw_X* XiWin,char *name,int is_fore)
352: {
353:   PixVal pixval;

356:   if (XiWin->numcolors == 2 || !XiFindColor(XiWin,name,&pixval)) {
357:     pixval  = is_fore ? XiWin->cmapping[PETSC_DRAW_WHITE] : XiWin->cmapping[PETSC_DRAW_BLACK];
358:   }
359:   PetscFunctionReturn(pixval);
360: }