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/src/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 XiInitCmap(PetscDraw_X*);
48: EXTERN PetscErrorCode XiGetVisualClass(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 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: PetscTruth fast;
83: if (colormap) {
84: gColormap = colormap;
85: } else {
86: gColormap = DefaultColormap(display,screen);
87: }
89: /* set the basic colors into the color map */
90: for (i=0; i<PETSC_DRAW_BASIC_COLORS; i++) {
91: XAllocNamedColor(display,gColormap,colornames[i],&colordef,&ecolordef);
92: gCmapping[i] = colordef.pixel;
93: }
95: /* set the uniform hue colors into the color map */
96: ncolors = 256-PETSC_DRAW_BASIC_COLORS;
97: PetscMalloc(3*ncolors*sizeof(unsigned char),&red);
98: green = red + ncolors;
99: blue = green + ncolors;
100: PetscDrawUtilitySetCmapHue(red,green,blue,ncolors);
101: PetscOptionsHasName(PETSC_NULL,"-draw_fast",&fast);
102: if (!fast) {
103: for (i=PETSC_DRAW_BASIC_COLORS; i<ncolors+PETSC_DRAW_BASIC_COLORS; i++) {
104: colordef.red = ((int)red[i-PETSC_DRAW_BASIC_COLORS] * 65535) / 255;
105: colordef.green = ((int)green[i-PETSC_DRAW_BASIC_COLORS] * 65535) / 255;
106: colordef.blue = ((int)blue[i-PETSC_DRAW_BASIC_COLORS] * 65535) / 255;
107: colordef.flags = DoRed | DoGreen | DoBlue;
108: XAllocColor(display,gColormap,&colordef);
109: gCmapping[i] = colordef.pixel;
110: }
111: }
112: PetscFree(red);
113: PetscLogInfo(0,"PetscDrawSetUpColormap_Shared:Successfully allocated colors\n");
115: return(0);
116: }
118: /*
119: Keep a record of which pixel numbers in the cmap have been
120: used so far; this is to allow us to try to reuse as much of the current
121: colormap as possible.
122: */
123: static PetscTruth cmap_pixvalues_used[256];
124: static int cmap_base = 0;
128: PetscErrorCode PetscDrawSetUpColormap_Private(Display *display,int screen,Visual *visual,Colormap colormap)
129: {
130: Colormap defaultmap = DefaultColormap(display,screen);
132: int found,i,ncolors;
133: XColor colordef;
134: unsigned char *red,*green,*blue;
135: PetscTruth fast;
139: if (colormap) {
140: gColormap = colormap;
141: } else {
142: gColormap = XCreateColormap(display,RootWindow(display,screen),visual,AllocAll);
143: }
145: cmap_base = 0;
146: PetscMemzero(cmap_pixvalues_used,256*sizeof(PetscTruth));
148: /* set the basic colors into the color map */
149: for (i=0; i<PETSC_DRAW_BASIC_COLORS; i++) {
150: XParseColor(display,gColormap,colornames[i],&colordef);
151: /* try to allocate the color in the default-map */
152: found = XAllocColor(display,defaultmap,&colordef);
153: /* use it, if it it exists and is not already used in the new colormap */
154: if (found && colordef.pixel < 256 && !cmap_pixvalues_used[colordef.pixel]) {
155: cmap_pixvalues_used[colordef.pixel] = PETSC_TRUE;
156: /* otherwise search for the next available slot */
157: } else {
158: while (cmap_pixvalues_used[cmap_base]) cmap_base++;
159: colordef.pixel = cmap_base;
160: cmap_pixvalues_used[cmap_base++] = PETSC_TRUE;
161: }
162: XStoreColor(display,gColormap,&colordef);
163: gCmapping[i] = colordef.pixel;
164: }
166: /* set the uniform hue colors into the color map */
167: ncolors = 256-PETSC_DRAW_BASIC_COLORS;
168: PetscMalloc(3*ncolors*sizeof(unsigned char),&red);
169: green = red + ncolors;
170: blue = green + ncolors;
171: PetscDrawUtilitySetCmapHue(red,green,blue,ncolors);
172: PetscOptionsHasName(PETSC_NULL,"-draw_fast",&fast);
173: if (!fast) {
174: for (i=PETSC_DRAW_BASIC_COLORS; i<ncolors+PETSC_DRAW_BASIC_COLORS; i++) {
175: colordef.red = ((int)red[i-PETSC_DRAW_BASIC_COLORS] * 65535) / 255;
176: colordef.green = ((int)green[i-PETSC_DRAW_BASIC_COLORS] * 65535) / 255;
177: colordef.blue = ((int)blue[i-PETSC_DRAW_BASIC_COLORS] * 65535) / 255;
178: colordef.flags = DoRed | DoGreen | DoBlue;
179: /* try to allocate the color in the default-map */
180: found = XAllocColor(display,defaultmap,&colordef);
181: /* use it, if it it exists and is not already used in the new colormap */
182: if (found && colordef.pixel < 256 && !cmap_pixvalues_used[colordef.pixel]) {
183: cmap_pixvalues_used[colordef.pixel] = PETSC_TRUE;
184: /* otherwise search for the next available slot */
185: } else {
186: while (cmap_pixvalues_used[cmap_base]) cmap_base++;
187: colordef.pixel = cmap_base;
188: cmap_pixvalues_used[cmap_base++] = PETSC_TRUE;
189: }
190: XStoreColor(display,gColormap,&colordef);
191: gCmapping[i] = colordef.pixel;
192: }
193: }
194: PetscFree(red);
195: PetscLogInfo(0,"PetscDrawSetUpColormap_Private:Successfully allocated colors\n");
196: return(0);
197: }
201: PetscErrorCode PetscDrawSetUpColormap_X(Display *display,int screen,Visual *visual,Colormap colormap)
202: {
204: PetscTruth sharedcolormap;
205: XVisualInfo vinfo;
209: /*
210: This is wrong; it needs to take the value from the visual
211: */
212: gNumcolors = 1 << DefaultDepth(display,screen);
214: PetscOptionsHasName(PETSC_NULL,"-draw_x_shared_colormap",&sharedcolormap);
215: /*
216: Need to determine if window supports allocating a private colormap,
217: if not, set flag to 1
218: */
219: if (XMatchVisualInfo(display,screen,24,StaticColor,&vinfo) ||
220: XMatchVisualInfo(display,screen,24,TrueColor,&vinfo) ||
221: XMatchVisualInfo(display,screen,16,StaticColor,&vinfo) ||
222: XMatchVisualInfo(display,screen,16,TrueColor,&vinfo) ||
223: XMatchVisualInfo(display,screen,15,StaticColor,&vinfo) ||
224: XMatchVisualInfo(display,screen,15,TrueColor,&vinfo)) {
225: sharedcolormap = PETSC_TRUE;
226: }
228: /* generate the X color map object */
229: if (sharedcolormap) {
230: PetscDrawSetUpColormap_Shared(display,screen,visual,colormap);
231: } else {
232: PetscDrawSetUpColormap_Private(display,screen,visual,colormap);
233: }
234:
235: return(0);
236: }
240: PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X* XiWin,char *host,Colormap colormap)
241: {
245: if (XiWin->depth < 8) {
246: SETERRQ(PETSC_ERR_SUP_SYS,"PETSc Graphics require monitors with at least 8 bit color (256 colors)");
247: }
248: if (!gColormap){
249: Display *display; /* Private display will exist forever contains colormap shared by all windows */
250: int screen;
251: Visual* vis;
253: display = XOpenDisplay(host);
254: screen = DefaultScreen(display);
255: vis = DefaultVisual(display,screen);
257: PetscDrawSetUpColormap_X(display,screen,vis,colormap);
258: }
259: XiWin->cmap = gColormap;
260: PetscMemcpy(XiWin->cmapping,gCmapping,256*sizeof(PixVal));
261: XiWin->background = XiWin->cmapping[PETSC_DRAW_WHITE];
262: XiWin->foreground = XiWin->cmapping[PETSC_DRAW_BLACK];
263: return(0);
264: }
266: /*
267: Color in X is many-layered. The first layer is the "visual",a
268: immutable attribute of a window set when the window is
269: created.
271: The next layer is the colormap. The installation of colormaps is
272: the buisness of the window manager (in some distant later release).
273: */
275: /*
276: This routine gets the visual class (PseudoColor, etc) and returns
277: it. It finds the default visual. Possible returns are
278: PseudoColor
279: StaticColor
280: DirectColor
281: TrueColor
282: GrayScale
283: StaticGray
284: */
287: PetscErrorCode XiSetVisualClass(PetscDraw_X* XiWin)
288: {
289: XVisualInfo vinfo;
292: if (XMatchVisualInfo(XiWin->disp,XiWin->screen,24,DirectColor,&vinfo)) {
293: XiWin->vis = vinfo.visual;
294: return(0);
295: }
296: if (XMatchVisualInfo(XiWin->disp,XiWin->screen,8,PseudoColor,&vinfo)) {
297: XiWin->vis = vinfo.visual;
298: return(0);
299: }
300: if (XMatchVisualInfo(XiWin->disp,XiWin->screen,
301: DefaultDepth(XiWin->disp,XiWin->screen),PseudoColor,&vinfo)) {
302: XiWin->vis = vinfo.visual;
303: return(0);
304: }
305: XiWin->vis = DefaultVisual(XiWin->disp,XiWin->screen);
306: return(0);
307: }
311: PetscErrorCode XiGetVisualClass(PetscDraw_X* XiWin)
312: {
314: #if defined(__cplusplus)
315: PetscFunctionReturn(XiWin->vis->c_class);
316: #else
317: PetscFunctionReturn(XiWin->vis->class);
318: #endif
319: }
324: PetscErrorCode XiSetColormap(PetscDraw_X* XiWin)
325: {
327: XSetWindowColormap(XiWin->disp,XiWin->win,XiWin->cmap);
328: return(0);
329: }
333: PetscErrorCode XiGetBaseColor(PetscDraw_X* XiWin,PixVal* white_pix,PixVal* black_pix)
334: {
336: *white_pix = XiWin->cmapping[PETSC_DRAW_WHITE];
337: *black_pix = XiWin->cmapping[PETSC_DRAW_BLACK];
338: return(0);
339: }
343: /*
344: This routine returns the pixel value for the specified color
345: Returns 0 on failure,<>0 otherwise.
346: */
349: PetscErrorCode XiFindColor(PetscDraw_X *XiWin,char *name,PixVal *pixval)
350: {
351: XColor colordef;
352: int st;
355: st = XParseColor(XiWin->disp,XiWin->cmap,name,&colordef);
356: if (st) {
357: st = XAllocColor(XiWin->disp,XiWin->cmap,&colordef);
358: if (st) *pixval = colordef.pixel;
359: }
360: PetscFunctionReturn(st);
361: }
363: /*
364: Another real need is to assign "colors" that make sense for
365: a monochrome display,without unduely penalizing color displays.
366: This routine takes a color name,a window, and a flag that
367: indicates whether this is "background" or "foreground".
368: In the monchrome case (or if the color is otherwise unavailable),
369: the "background" or "foreground" colors will be chosen
370: */
373: PixVal XiGetColor(PetscDraw_X* XiWin,char *name,int is_fore)
374: {
375: PixVal pixval;
378: if (XiWin->numcolors == 2 || !XiFindColor(XiWin,name,&pixval)) {
379: pixval = is_fore ? XiWin->cmapping[PETSC_DRAW_WHITE] : XiWin->cmapping[PETSC_DRAW_BLACK];
380: }
381: PetscFunctionReturn(pixval);
382: }
384: /*
385: This routine takes a named color and returns a color that is either
386: lighter or darker
387: */
390: PixVal XiSimColor(PetscDraw_X *XiWin,PixVal pixel,int intensity,int is_fore)
391: {
392: XColor colordef,colorsdef;
393: char RGBcolor[20];
394: PixVal red,green,blue;
397: colordef.pixel = pixel;
398: XQueryColor(XiWin->disp,XiWin->cmap,&colordef);
399: /* Adjust the color value up or down. Get the RGB values for the color */
400: red = colordef.red;
401: green = colordef.green;
402: blue = colordef.blue;
403: #define WHITE_AMOUNT 5000
404: if (intensity > 0) {
405: /* Add white to the color */
406: red = PetscMin(65535,red + WHITE_AMOUNT);
407: green = PetscMin(65535,green + WHITE_AMOUNT);
408: blue = PetscMin(65535,blue + WHITE_AMOUNT);
409: } else {
410: /* Subtract white from the color */
411: red = (red < WHITE_AMOUNT) ? 0 : red - WHITE_AMOUNT;
412: green = (green < WHITE_AMOUNT) ? 0 : green - WHITE_AMOUNT;
413: blue = (blue < WHITE_AMOUNT) ? 0 : blue - WHITE_AMOUNT;
414: }
415: sprintf(RGBcolor,"rgb:%4.4x/%4.4x/%4.4x",(unsigned int)red,
416: (unsigned int)green,(unsigned int)blue);
417: XLookupColor(XiWin->disp,XiWin->cmap,RGBcolor,&colordef,&colorsdef);
418: PetscFunctionReturn(colorsdef.pixel);
419: }
421: /*
422: XiSetCmapLight - Create rgb values from a single color by adding white
423:
424: The initial color is (red[0],green[0],blue[0]).
425: */
428: PetscErrorCode XiSetCmapLight(unsigned char *red,unsigned char *green,unsigned char *blue,int mapsize)
429: {
430: int i ;
433: for (i=1; i<mapsize-1; i++) {
434: blue[i] = i*(255-(int)blue[0])/(mapsize-2)+blue[0] ;
435: green[i] = i*(255-(int)green[0])/(mapsize-2)+green[0] ;
436: red[i] = i*(255-(int)red[0])/(mapsize-2)+red[0] ;
437: }
438: red[mapsize-1] = green[mapsize-1] = blue[mapsize-1] = 255;
439: return(0);
440: }