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