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: }