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 countour plots.
8: */
9: #include <../src/sys/classes/draw/impls/x/ximpl.h>
10: #include <X11/Xatom.h>
12: static const char *colornames[PETSC_DRAW_BASIC_COLORS] = {
13: "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"
46: };
48: /*
49: Sets up a color map for a display. This is shared by all the windows
50: opened on that display; this is to save time when windows are open so
51: each one does not have to create its own color map which can take 15 to 20 seconds
53: This is new code written 2/26/1999 Barry Smith,I hope it can replace
54: some older,rather confusing code.
56: The calls to XAllocNamedColor() and XAllocColor() are very slow
57: because we have to request from the X server for each
58: color. Could not figure out a way to request a large number at the
59: same time.
61: IMPORTANT: this code will fail if user opens windows on two different
62: displays: should add error checking to detect this. This is because all windows
63: share the same gColormap and gCmapping.
65: */
66: static Colormap gColormap = 0;
67: static PetscDrawXiPixVal gCmapping[PETSC_DRAW_MAXCOLOR];
68: static unsigned char gCpalette[PETSC_DRAW_MAXCOLOR][3];
70: PetscErrorCode PetscDrawSetUpColormap_Shared(Display *display,int screen,Visual *visual,Colormap colormap)
71: {
72: int i,k,ncolors = PETSC_DRAW_MAXCOLOR - PETSC_DRAW_BASIC_COLORS;
73: unsigned char R[PETSC_DRAW_MAXCOLOR-PETSC_DRAW_BASIC_COLORS];
74: unsigned char G[PETSC_DRAW_MAXCOLOR-PETSC_DRAW_BASIC_COLORS];
75: unsigned char B[PETSC_DRAW_MAXCOLOR-PETSC_DRAW_BASIC_COLORS];
76: XColor colordef,ecolordef;
77: PetscBool fast = PETSC_FALSE;
81: if (colormap) gColormap = colormap;
82: else gColormap = DefaultColormap(display,screen);
84: /* set the basic colors into the color map */
85: for (i=0; i<PETSC_DRAW_BASIC_COLORS; i++) {
86: XAllocNamedColor(display,gColormap,colornames[i],&colordef,&ecolordef);
87: gCmapping[i] = colordef.pixel;
88: gCpalette[i][0] = (unsigned char)(colordef.red >> 8);
89: gCpalette[i][1] = (unsigned char)(colordef.green >> 8);
90: gCpalette[i][2] = (unsigned char)(colordef.blue >> 8);
91: }
93: /* set the contour colors into the colormap */
94: PetscOptionsGetBool(NULL,NULL,"-draw_fast",&fast,NULL);
95: PetscDrawUtilitySetCmap(NULL,ncolors,R,G,B);
96: for (i=0, k=PETSC_DRAW_BASIC_COLORS; i<ncolors; i++, k++) {
97: colordef.red = (unsigned short)(R[i] << 8);
98: colordef.green = (unsigned short)(G[i] << 8);
99: colordef.blue = (unsigned short)(B[i] << 8);
100: colordef.flags = DoRed|DoGreen|DoBlue;
101: colordef.pixel = gCmapping[PETSC_DRAW_BLACK];
102: if (!fast) XAllocColor(display,gColormap,&colordef);
103: gCmapping[k] = colordef.pixel;
104: gCpalette[k][0] = R[i];
105: gCpalette[k][1] = G[i];
106: gCpalette[k][2] = B[i];
107: }
109: PetscInfo(NULL,"Successfully allocated colors\n");
110: return(0);
111: }
113: /*
114: Keep a record of which pixel numbers in the cmap have been
115: used so far; this is to allow us to try to reuse as much of the current
116: colormap as possible.
117: */
118: static PetscBool cmap_pixvalues_used[PETSC_DRAW_MAXCOLOR];
119: static int cmap_base = 0;
121: PetscErrorCode PetscDrawSetUpColormap_Private(Display *display,int screen,Visual *visual,Colormap colormap)
122: {
123: int found,i,k,ncolors = PETSC_DRAW_MAXCOLOR-PETSC_DRAW_BASIC_COLORS;
124: unsigned char R[PETSC_DRAW_MAXCOLOR-PETSC_DRAW_BASIC_COLORS];
125: unsigned char G[PETSC_DRAW_MAXCOLOR-PETSC_DRAW_BASIC_COLORS];
126: unsigned char B[PETSC_DRAW_MAXCOLOR-PETSC_DRAW_BASIC_COLORS];
127: Colormap defaultmap = DefaultColormap(display,screen);
128: XColor colordef;
129: PetscBool fast = PETSC_FALSE;
133: if (colormap) gColormap = colormap;
134: else gColormap = XCreateColormap(display,RootWindow(display,screen),visual,AllocAll);
136: cmap_base = 0;
138: PetscMemzero(cmap_pixvalues_used,sizeof(cmap_pixvalues_used));
140: /* set the basic colors into the color map */
141: for (i=0; i<PETSC_DRAW_BASIC_COLORS; i++) {
142: XParseColor(display,gColormap,colornames[i],&colordef);
143: /* try to allocate the color in the default-map */
144: found = XAllocColor(display,defaultmap,&colordef);
145: /* use it, if it it exists and is not already used in the new colormap */
146: if (found && colordef.pixel < PETSC_DRAW_MAXCOLOR && !cmap_pixvalues_used[colordef.pixel]) {
147: cmap_pixvalues_used[colordef.pixel] = PETSC_TRUE;
148: /* otherwise search for the next available slot */
149: } else {
150: while (cmap_pixvalues_used[cmap_base]) cmap_base++;
151: colordef.pixel = cmap_base;
152: cmap_pixvalues_used[cmap_base++] = PETSC_TRUE;
153: }
154: XStoreColor(display,gColormap,&colordef);
155: gCmapping[i] = colordef.pixel;
156: gCpalette[i][0] = (unsigned char)(colordef.red >> 8);
157: gCpalette[i][1] = (unsigned char)(colordef.green >> 8);
158: gCpalette[i][2] = (unsigned char)(colordef.blue >> 8);
159: }
161: /* set the contour colors into the colormap */
162: PetscOptionsGetBool(NULL,NULL,"-draw_fast",&fast,NULL);
163: PetscDrawUtilitySetCmap(NULL,ncolors,R,G,B);
164: for (i=0, k=PETSC_DRAW_BASIC_COLORS; i<ncolors; i++, k++) {
165: colordef.red = (unsigned short)(R[i] << 8);
166: colordef.green = (unsigned short)(G[i] << 8);
167: colordef.blue = (unsigned short)(B[i] << 8);
168: colordef.flags = DoRed|DoGreen|DoBlue;
169: colordef.pixel = gCmapping[PETSC_DRAW_BLACK];
170: if (!fast) {
171: /* try to allocate the color in the default-map */
172: found = XAllocColor(display,defaultmap,&colordef);
173: /* use it, if it it exists and is not already used in the new colormap */
174: if (found && colordef.pixel < PETSC_DRAW_MAXCOLOR && !cmap_pixvalues_used[colordef.pixel]) {
175: cmap_pixvalues_used[colordef.pixel] = PETSC_TRUE;
176: /* otherwise search for the next available slot */
177: } else {
178: while (cmap_pixvalues_used[cmap_base]) cmap_base++;
179: colordef.pixel = cmap_base;
180: cmap_pixvalues_used[cmap_base++] = PETSC_TRUE;
181: }
182: XStoreColor(display,gColormap,&colordef);
183: }
184: gCmapping[k] = colordef.pixel;
185: gCpalette[k][0] = R[i];
186: gCpalette[k][1] = G[i];
187: gCpalette[k][2] = B[i];
188: }
190: PetscInfo(NULL,"Successfully allocated colors\n");
191: return(0);
192: }
194: PetscErrorCode PetscDrawSetUpColormap_X(Display *display,int screen,Visual *visual,Colormap colormap)
195: {
197: PetscBool sharedcolormap = PETSC_FALSE;
198: XVisualInfo vinfo;
201: PetscOptionsGetBool(NULL,NULL,"-draw_x_shared_colormap",&sharedcolormap,NULL);
202: /*
203: Need to determine if window supports allocating a private colormap,
204: */
205: if (XMatchVisualInfo(display,screen,24,StaticColor,&vinfo) ||
206: XMatchVisualInfo(display,screen,24,TrueColor,&vinfo) ||
207: XMatchVisualInfo(display,screen,16,StaticColor,&vinfo) ||
208: XMatchVisualInfo(display,screen,16,TrueColor,&vinfo) ||
209: XMatchVisualInfo(display,screen,15,StaticColor,&vinfo) ||
210: XMatchVisualInfo(display,screen,15,TrueColor,&vinfo)) sharedcolormap = PETSC_TRUE;
211: /*
212: Generate the X colormap object
213: */
214: if (sharedcolormap) {
215: PetscDrawSetUpColormap_Shared(display,screen,visual,colormap);
216: } else {
217: PetscDrawSetUpColormap_Private(display,screen,visual,colormap);
218: }
219: return(0);
220: }
222: PETSC_INTERN PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X*,Colormap);
224: PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X *XiWin,Colormap colormap)
225: {
226: PetscBool fast = PETSC_FALSE;
230: PetscOptionsGetBool(NULL,NULL,"-draw_fast",&fast,NULL);
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: PetscDrawSetUpColormap_X(XiWin->disp,XiWin->screen,XiWin->vis,colormap);
234: }
235: XiWin->cmap = gColormap;
236: XiWin->cmapsize = fast ? PETSC_DRAW_BASIC_COLORS : PETSC_DRAW_MAXCOLOR;
237: PetscMemcpy(XiWin->cmapping,gCmapping,sizeof(XiWin->cmapping));
238: PetscMemcpy(XiWin->cpalette,gCpalette,sizeof(XiWin->cpalette));
239: XiWin->background = XiWin->cmapping[PETSC_DRAW_WHITE];
240: XiWin->foreground = XiWin->cmapping[PETSC_DRAW_BLACK];
241: return(0);
242: }
244: PetscErrorCode PetscDrawXiColormap(PetscDraw_X *XiWin)
245: { return PetscDrawSetColormap_X(XiWin,(Colormap)0); }
247: /*
248: Color in X is many-layered. The first layer is the "visual",a
249: immutable attribute of a window set when the window is
250: created.
252: The next layer is the colormap. The installation of colormaps is
253: the buisness of the window manager (in some distant later release).
254: */
256: /*
257: This routine gets the visual class (PseudoColor, etc) and returns
258: it. It finds the default visual. Possible returns are
259: PseudoColor
260: StaticColor
261: DirectColor
262: TrueColor
263: GrayScale
264: StaticGray
265: */
266: PetscErrorCode PetscDrawXiSetVisualClass(PetscDraw_X *XiWin)
267: {
268: XVisualInfo vinfo;
271: if (XMatchVisualInfo(XiWin->disp,XiWin->screen,24,DirectColor,&vinfo)) {
272: XiWin->vis = vinfo.visual;
273: } else if (XMatchVisualInfo(XiWin->disp,XiWin->screen,8,PseudoColor,&vinfo)) {
274: XiWin->vis = vinfo.visual;
275: } else if (XMatchVisualInfo(XiWin->disp,XiWin->screen,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: }
283: PetscErrorCode PetscDrawXiSetColormap(PetscDraw_X *XiWin)
284: {
286: XSetWindowColormap(XiWin->disp,XiWin->win,XiWin->cmap);
287: return(0);
288: }
290: /*
291: Get RGB color entries out of the X colormap
292: */
293: PetscErrorCode PetscDrawXiGetPalette(PetscDraw_X *XiWin,unsigned char palette[PETSC_DRAW_MAXCOLOR][3])
294: {
295: int k;
296: XColor colordef[PETSC_DRAW_MAXCOLOR];
299: for (k=0; k<PETSC_DRAW_MAXCOLOR; k++) {
300: colordef[k].pixel = XiWin->cmapping[k];
301: colordef[k].flags = DoRed|DoGreen|DoBlue;
302: }
303: XQueryColors(XiWin->disp,XiWin->cmap,colordef,PETSC_DRAW_MAXCOLOR);
304: for (k=0; k<PETSC_DRAW_MAXCOLOR; k++) {
305: palette[k][0] = (unsigned char)(colordef[k].red >> 8);
306: palette[k][1] = (unsigned char)(colordef[k].green >> 8);
307: palette[k][2] = (unsigned char)(colordef[k].blue >> 8);
308: }
309: return(0);
310: }