Actual source code: xcolor.c
1: #define PETSC_DLL
3: /*
4: Code for managing color the X implementation of the PetscDraw routines.
6: Currently we default to using cmapping[0 to PETSC_DRAW_BASIC_COLORS-1] for the basic colors and
7: cmapping[DRAW_BASIC_COLORS to 255] for a uniform hue of all the colors. But in the contour
8: plot we only use from PETSC_DRAW_BASIC_COLORS to 240 since the ones beyond that are too dark.
10: */
11: #include ../src/sys/draw/impls/x/ximpl.h
12: #include <X11/Xatom.h>
14: static const char *(colornames[PETSC_DRAW_BASIC_COLORS]) = { "white",
15: "black",
16: "red",
17: "green",
18: "cyan",
19: "blue",
20: "magenta",
21: "aquamarine",
22: "forestgreen",
23: "orange",
24: "violet",
25: "brown",
26: "pink",
27: "coral",
28: "gray",
29: "yellow",
30: "gold",
31: "lightpink",
32: "mediumturquoise",
33: "khaki",
34: "dimgray",
35: "yellowgreen",
36: "skyblue",
37: "darkgreen",
38: "navyblue",
39: "sandybrown",
40: "cadetblue",
41: "powderblue",
42: "deeppink",
43: "thistle",
44: "limegreen",
45: "lavenderblush",
46: "plum"};
48: EXTERN PetscErrorCode XiInitCmap(PetscDraw_X*);
49: EXTERN PetscErrorCode XiGetVisualClass(PetscDraw_X *);
51: /*
52: Sets up a color map for a display. This is shared by all the windows
53: opened on that display; this is to save time when windows are open so
54: each one does not have to create its own color map which can take 15 to 20 seconds
56: This is new code written 2/26/1999 Barry Smith,I hope it can replace
57: some older,rather confusing code.
59: The calls to XAllocNamedColor() and XAllocColor() are very slow
60: because we have to request from the X server for each
61: color. Could not figure out a way to request a large number at the
62: same time.
64: IMPORTANT: this code will fail if user opens windows on two different
65: displays: should add error checking to detect this. This is because all windows
66: share the same gColormap and gCmapping.
68: */
69: static Colormap gColormap = 0;
70: static PixVal gCmapping[256];
71: int gNumcolors = 0;
75: PetscErrorCode PetscDrawSetUpColormap_Shared(Display *display,int screen,Visual *visual,Colormap colormap)
76: {
77: XColor colordef,ecolordef;
78: unsigned char *red,*green,*blue;
79: int i,ncolors;
81: PetscTruth fast = PETSC_FALSE;
84: if (colormap) {
85: gColormap = colormap;
86: } else {
87: gColormap = DefaultColormap(display,screen);
88: }
90: /* set the basic colors into the color map */
91: for (i=0; i<PETSC_DRAW_BASIC_COLORS; i++) {
92: XAllocNamedColor(display,gColormap,colornames[i],&colordef,&ecolordef);
93: gCmapping[i] = colordef.pixel;
94: }
96: /* set the uniform hue colors into the color map */
97: ncolors = 256-PETSC_DRAW_BASIC_COLORS;
98: PetscMalloc3(ncolors,unsigned char,&red,ncolors,unsigned char,&green,ncolors,unsigned char,&blue);
99: PetscDrawUtilitySetCmapHue(red,green,blue,ncolors);
100: PetscOptionsGetTruth(PETSC_NULL,"-draw_fast",&fast,PETSC_NULL);
101: if (!fast) {
102: for (i=PETSC_DRAW_BASIC_COLORS; i<ncolors+PETSC_DRAW_BASIC_COLORS; i++) {
103: colordef.red = ((int)red[i-PETSC_DRAW_BASIC_COLORS] * 65535) / 255;
104: colordef.green = ((int)green[i-PETSC_DRAW_BASIC_COLORS] * 65535) / 255;
105: colordef.blue = ((int)blue[i-PETSC_DRAW_BASIC_COLORS] * 65535) / 255;
106: colordef.flags = DoRed | DoGreen | DoBlue;
107: XAllocColor(display,gColormap,&colordef);
108: gCmapping[i] = colordef.pixel;
109: }
110: }
111: PetscFree3(red,green,blue);
112: PetscInfo(0,"Successfully allocated colors\n");
113: return(0);
114: }
116: /*
117: Keep a record of which pixel numbers in the cmap have been
118: used so far; this is to allow us to try to reuse as much of the current
119: colormap as possible.
120: */
121: static PetscTruth cmap_pixvalues_used[256];
122: static int cmap_base = 0;
126: PetscErrorCode PetscDrawSetUpColormap_Private(Display *display,int screen,Visual *visual,Colormap colormap)
127: {
128: Colormap defaultmap = DefaultColormap(display,screen);
130: int found,i,ncolors;
131: XColor colordef;
132: unsigned char *red,*green,*blue;
133: PetscTruth fast = PETSC_FALSE;
137: if (colormap) {
138: gColormap = colormap;
139: } else {
140: gColormap = XCreateColormap(display,RootWindow(display,screen),visual,AllocAll);
141: }
143: cmap_base = 0;
144: PetscMemzero(cmap_pixvalues_used,256*sizeof(PetscTruth));
146: /* set the basic colors into the color map */
147: for (i=0; i<PETSC_DRAW_BASIC_COLORS; i++) {
148: XParseColor(display,gColormap,colornames[i],&colordef);
149: /* try to allocate the color in the default-map */
150: found = XAllocColor(display,defaultmap,&colordef);
151: /* use it, if it it exists and is not already used in the new colormap */
152: if (found && colordef.pixel < 256 && !cmap_pixvalues_used[colordef.pixel]) {
153: cmap_pixvalues_used[colordef.pixel] = PETSC_TRUE;
154: /* otherwise search for the next available slot */
155: } else {
156: while (cmap_pixvalues_used[cmap_base]) cmap_base++;
157: colordef.pixel = cmap_base;
158: cmap_pixvalues_used[cmap_base++] = PETSC_TRUE;
159: }
160: XStoreColor(display,gColormap,&colordef);
161: gCmapping[i] = colordef.pixel;
162: }
164: /* set the uniform hue colors into the color map */
165: ncolors = 256-PETSC_DRAW_BASIC_COLORS;
166: PetscMalloc3(ncolors,unsigned char,&red,ncolors,unsigned char,&green,ncolors,unsigned char,&blue);
167: PetscDrawUtilitySetCmapHue(red,green,blue,ncolors);
168: PetscOptionsGetTruth(PETSC_NULL,"-draw_fast",&fast,PETSC_NULL);
169: if (!fast) {
170: for (i=PETSC_DRAW_BASIC_COLORS; i<ncolors+PETSC_DRAW_BASIC_COLORS; i++) {
171: colordef.red = ((int)red[i-PETSC_DRAW_BASIC_COLORS] * 65535) / 255;
172: colordef.green = ((int)green[i-PETSC_DRAW_BASIC_COLORS] * 65535) / 255;
173: colordef.blue = ((int)blue[i-PETSC_DRAW_BASIC_COLORS] * 65535) / 255;
174: colordef.flags = DoRed | DoGreen | DoBlue;
175: /* try to allocate the color in the default-map */
176: found = XAllocColor(display,defaultmap,&colordef);
177: /* use it, if it it exists and is not already used in the new colormap */
178: if (found && colordef.pixel < 256 && !cmap_pixvalues_used[colordef.pixel]) {
179: cmap_pixvalues_used[colordef.pixel] = PETSC_TRUE;
180: /* otherwise search for the next available slot */
181: } else {
182: while (cmap_pixvalues_used[cmap_base]) cmap_base++;
183: colordef.pixel = cmap_base;
184: cmap_pixvalues_used[cmap_base++] = PETSC_TRUE;
185: }
186: XStoreColor(display,gColormap,&colordef);
187: gCmapping[i] = colordef.pixel;
188: }
189: }
190: PetscFree3(red,green,blue);
191: PetscInfo(0,"Successfully allocated colors\n");
192: return(0);
193: }
197: PetscErrorCode PetscDrawSetUpColormap_X(Display *display,int screen,Visual *visual,Colormap colormap)
198: {
200: PetscTruth sharedcolormap = PETSC_FALSE;
201: XVisualInfo vinfo;
205: /*
206: This is wrong; it needs to take the value from the visual
207: */
208: gNumcolors = 1 << DefaultDepth(display,screen);
210: PetscOptionsGetTruth(PETSC_NULL,"-draw_x_shared_colormap",&sharedcolormap,PETSC_NULL);
211: /*
212: Need to determine if window supports allocating a private colormap,
213: if not, set flag to 1
214: */
215: if (XMatchVisualInfo(display,screen,24,StaticColor,&vinfo) ||
216: XMatchVisualInfo(display,screen,24,TrueColor,&vinfo) ||
217: XMatchVisualInfo(display,screen,16,StaticColor,&vinfo) ||
218: XMatchVisualInfo(display,screen,16,TrueColor,&vinfo) ||
219: XMatchVisualInfo(display,screen,15,StaticColor,&vinfo) ||
220: XMatchVisualInfo(display,screen,15,TrueColor,&vinfo)) {
221: sharedcolormap = PETSC_TRUE;
222: }
224: /* generate the X color map object */
225: if (sharedcolormap) {
226: PetscDrawSetUpColormap_Shared(display,screen,visual,colormap);
227: } else {
228: PetscDrawSetUpColormap_Private(display,screen,visual,colormap);
229: }
230:
231: return(0);
232: }
236: PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X* XiWin,char *host,Colormap colormap)
237: {
241: if (XiWin->depth < 8) {
242: SETERRQ(PETSC_ERR_SUP_SYS,"PETSc Graphics require monitors with at least 8 bit color (256 colors)");
243: }
244: if (!gColormap){
245: Display *display; /* Private display will exist forever contains colormap shared by all windows */
246: int screen;
247: Visual* vis;
249: display = XOpenDisplay(host);
250: screen = DefaultScreen(display);
251: vis = DefaultVisual(display,screen);
253: PetscDrawSetUpColormap_X(display,screen,vis,colormap);
254: }
255: XiWin->cmap = gColormap;
256: PetscMemcpy(XiWin->cmapping,gCmapping,256*sizeof(PixVal));
257: XiWin->background = XiWin->cmapping[PETSC_DRAW_WHITE];
258: XiWin->foreground = XiWin->cmapping[PETSC_DRAW_BLACK];
259: return(0);
260: }
262: /*
263: Color in X is many-layered. The first layer is the "visual",a
264: immutable attribute of a window set when the window is
265: created.
267: The next layer is the colormap. The installation of colormaps is
268: the buisness of the window manager (in some distant later release).
269: */
271: /*
272: This routine gets the visual class (PseudoColor, etc) and returns
273: it. It finds the default visual. Possible returns are
274: PseudoColor
275: StaticColor
276: DirectColor
277: TrueColor
278: GrayScale
279: StaticGray
280: */
283: PetscErrorCode XiSetVisualClass(PetscDraw_X* XiWin)
284: {
285: XVisualInfo vinfo;
288: if (XMatchVisualInfo(XiWin->disp,XiWin->screen,24,DirectColor,&vinfo)) {
289: XiWin->vis = vinfo.visual;
290: return(0);
291: }
292: if (XMatchVisualInfo(XiWin->disp,XiWin->screen,8,PseudoColor,&vinfo)) {
293: XiWin->vis = vinfo.visual;
294: return(0);
295: }
296: if (XMatchVisualInfo(XiWin->disp,XiWin->screen,
297: DefaultDepth(XiWin->disp,XiWin->screen),PseudoColor,&vinfo)) {
298: XiWin->vis = vinfo.visual;
299: return(0);
300: }
301: XiWin->vis = DefaultVisual(XiWin->disp,XiWin->screen);
302: return(0);
303: }
307: PetscErrorCode XiGetVisualClass(PetscDraw_X* XiWin)
308: {
310: #if defined(__cplusplus)
311: PetscFunctionReturn(XiWin->vis->c_class);
312: #else
313: PetscFunctionReturn(XiWin->vis->class);
314: #endif
315: }
320: PetscErrorCode XiSetColormap(PetscDraw_X* XiWin)
321: {
323: XSetWindowColormap(XiWin->disp,XiWin->win,XiWin->cmap);
324: return(0);
325: }
329: PetscErrorCode XiGetBaseColor(PetscDraw_X* XiWin,PixVal* white_pix,PixVal* black_pix)
330: {
332: *white_pix = XiWin->cmapping[PETSC_DRAW_WHITE];
333: *black_pix = XiWin->cmapping[PETSC_DRAW_BLACK];
334: return(0);
335: }
339: /*
340: This routine returns the pixel value for the specified color
341: Returns 0 on failure,<>0 otherwise.
342: */
345: PetscErrorCode XiFindColor(PetscDraw_X *XiWin,char *name,PixVal *pixval)
346: {
347: XColor colordef;
348: int st;
351: st = XParseColor(XiWin->disp,XiWin->cmap,name,&colordef);
352: if (st) {
353: st = XAllocColor(XiWin->disp,XiWin->cmap,&colordef);
354: if (st) *pixval = colordef.pixel;
355: }
356: PetscFunctionReturn(st);
357: }
359: /*
360: Another real need is to assign "colors" that make sense for
361: a monochrome display,without unduely penalizing color displays.
362: This routine takes a color name,a window, and a flag that
363: indicates whether this is "background" or "foreground".
364: In the monchrome case (or if the color is otherwise unavailable),
365: the "background" or "foreground" colors will be chosen
366: */
369: PixVal XiGetColor(PetscDraw_X* XiWin,char *name,int is_fore)
370: {
371: PixVal pixval;
374: if (XiWin->numcolors == 2 || !XiFindColor(XiWin,name,&pixval)) {
375: pixval = is_fore ? XiWin->cmapping[PETSC_DRAW_WHITE] : XiWin->cmapping[PETSC_DRAW_BLACK];
376: }
377: PetscFunctionReturn(pixval);
378: }
380: /*
381: This routine takes a named color and returns a color that is either
382: lighter or darker
383: */
386: PixVal XiSimColor(PetscDraw_X *XiWin,PixVal pixel,int intensity,int is_fore)
387: {
388: XColor colordef,colorsdef;
389: char RGBcolor[20];
390: PixVal red,green,blue;
393: colordef.pixel = pixel;
394: XQueryColor(XiWin->disp,XiWin->cmap,&colordef);
395: /* Adjust the color value up or down. Get the RGB values for the color */
396: red = colordef.red;
397: green = colordef.green;
398: blue = colordef.blue;
399: #define WHITE_AMOUNT 5000
400: if (intensity > 0) {
401: /* Add white to the color */
402: red = PetscMin(65535,red + WHITE_AMOUNT);
403: green = PetscMin(65535,green + WHITE_AMOUNT);
404: blue = PetscMin(65535,blue + WHITE_AMOUNT);
405: } else {
406: /* Subtract white from the color */
407: red = (red < WHITE_AMOUNT) ? 0 : red - WHITE_AMOUNT;
408: green = (green < WHITE_AMOUNT) ? 0 : green - WHITE_AMOUNT;
409: blue = (blue < WHITE_AMOUNT) ? 0 : blue - WHITE_AMOUNT;
410: }
411: sprintf(RGBcolor,"rgb:%4.4x/%4.4x/%4.4x",(unsigned int)red,
412: (unsigned int)green,(unsigned int)blue);
413: XLookupColor(XiWin->disp,XiWin->cmap,RGBcolor,&colordef,&colorsdef);
414: PetscFunctionReturn(colorsdef.pixel);
415: }
417: /*
418: XiSetCmapLight - Create rgb values from a single color by adding white
419:
420: The initial color is (red[0],green[0],blue[0]).
421: */
424: PetscErrorCode XiSetCmapLight(unsigned char *red,unsigned char *green,unsigned char *blue,int mapsize)
425: {
426: int i ;
429: for (i=1; i<mapsize-1; i++) {
430: blue[i] = i*(255-(int)blue[0])/(mapsize-2)+blue[0] ;
431: green[i] = i*(255-(int)green[0])/(mapsize-2)+green[0] ;
432: red[i] = i*(255-(int)red[0])/(mapsize-2)+red[0] ;
433: }
434: red[mapsize-1] = green[mapsize-1] = blue[mapsize-1] = 255;
435: return(0);
436: }