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]) = {"white",
13: "black",
14: "red",
15: "green",
16: "cyan",
17: "blue",
18: "magenta",
19: "aquamarine",
20: "forestgreen",
21: "orange",
22: "violet",
23: "brown",
24: "pink",
25: "coral",
26: "gray",
27: "yellow",
28: "gold",
29: "lightpink",
30: "mediumturquoise",
31: "khaki",
32: "dimgray",
33: "yellowgreen",
34: "skyblue",
35: "darkgreen",
36: "navyblue",
37: "sandybrown",
38: "cadetblue",
39: "powderblue",
40: "deeppink",
41: "thistle",
42: "limegreen",
43: "lavenderblush",
44: "plum"};
46: /*
47: Sets up a color map for a display. This is shared by all the windows
48: opened on that display; this is to save time when windows are open so
49: each one does not have to create its own color map which can take 15 to 20 seconds
51: This is new code written 2/26/1999 Barry Smith,I hope it can replace
52: some older,rather confusing code.
54: The calls to XAllocNamedColor() and XAllocColor() are very slow
55: because we have to request from the X server for each
56: color. Could not figure out a way to request a large number at the
57: same time.
59: IMPORTANT: this code will fail if user opens windows on two different
60: displays: should add error checking to detect this. This is because all windows
61: share the same gColormap and gCmapping.
63: */
64: static Colormap gColormap = 0;
65: static PetscDrawXiPixVal gCmapping[256];
66: static unsigned char gCpalette[256][3];
68: PetscErrorCode PetscDrawSetUpColormap_Shared(Display *display,int screen,Visual *visual,Colormap colormap) 69: {
70: int i,k,ncolors = 256-PETSC_DRAW_BASIC_COLORS;
71: unsigned char R[256-PETSC_DRAW_BASIC_COLORS];
72: unsigned char G[256-PETSC_DRAW_BASIC_COLORS];
73: unsigned char B[256-PETSC_DRAW_BASIC_COLORS];
74: XColor colordef,ecolordef;
75: PetscBool fast = PETSC_FALSE;
79: if (colormap) gColormap = colormap;
80: else gColormap = DefaultColormap(display,screen);
83: /* set the basic colors into the color map */
84: for (i=0; i<PETSC_DRAW_BASIC_COLORS; i++) {
85: XAllocNamedColor(display,gColormap,colornames[i],&colordef,&ecolordef);
86: gCmapping[i] = colordef.pixel;
87: gCpalette[i][0] = (unsigned char)(colordef.red >> 8);
88: gCpalette[i][1] = (unsigned char)(colordef.green >> 8);
89: gCpalette[i][2] = (unsigned char)(colordef.blue >> 8);
90: }
92: /* set the contour colors into the colormap */
93: PetscOptionsGetBool(NULL,NULL,"-draw_fast",&fast,NULL);
94: PetscDrawUtilitySetCmap(NULL,ncolors,R,G,B);
95: for (i=0, k=PETSC_DRAW_BASIC_COLORS; i<ncolors; i++, k++) {
96: colordef.red = (unsigned short)(R[i] << 8);
97: colordef.green = (unsigned short)(G[i] << 8);
98: colordef.blue = (unsigned short)(B[i] << 8);
99: colordef.flags = DoRed|DoGreen|DoBlue;
100: colordef.pixel = gCmapping[PETSC_DRAW_BLACK];
101: if (!fast) XAllocColor(display,gColormap,&colordef);
102: gCmapping[k] = colordef.pixel;
103: gCpalette[k][0] = R[i];
104: gCpalette[k][1] = G[i];
105: gCpalette[k][2] = B[i];
106: }
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;
120: PetscErrorCode PetscDrawSetUpColormap_Private(Display *display,int screen,Visual *visual,Colormap colormap)121: {
122: int found,i,k,ncolors = 256-PETSC_DRAW_BASIC_COLORS;
123: unsigned char R[256-PETSC_DRAW_BASIC_COLORS];
124: unsigned char G[256-PETSC_DRAW_BASIC_COLORS];
125: unsigned char B[256-PETSC_DRAW_BASIC_COLORS];
126: Colormap defaultmap = DefaultColormap(display,screen);
127: XColor colordef;
128: PetscBool fast = PETSC_FALSE;
132: if (colormap) gColormap = colormap;
133: else gColormap = XCreateColormap(display,RootWindow(display,screen),visual,AllocAll);
135: 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: gCpalette[i][0] = (unsigned char)(colordef.red >> 8);
156: gCpalette[i][1] = (unsigned char)(colordef.green >> 8);
157: gCpalette[i][2] = (unsigned char)(colordef.blue >> 8);
158: }
160: /* set the contour colors into the colormap */
161: PetscOptionsGetBool(NULL,NULL,"-draw_fast",&fast,NULL);
162: PetscDrawUtilitySetCmap(NULL,ncolors,R,G,B);
163: for (i=0, k=PETSC_DRAW_BASIC_COLORS; i<ncolors; i++, k++) {
164: colordef.red = (unsigned short)(R[i] << 8);
165: colordef.green = (unsigned short)(G[i] << 8);
166: colordef.blue = (unsigned short)(B[i] << 8);
167: colordef.flags = DoRed|DoGreen|DoBlue;
168: colordef.pixel = gCmapping[PETSC_DRAW_BLACK];
169: if (!fast) {
170: /* try to allocate the color in the default-map */
171: found = XAllocColor(display,defaultmap,&colordef);
172: /* use it, if it it exists and is not already used in the new colormap */
173: if (found && colordef.pixel < 256 && !cmap_pixvalues_used[colordef.pixel]) {
174: cmap_pixvalues_used[colordef.pixel] = PETSC_TRUE;
175: /* otherwise search for the next available slot */
176: } else {
177: while (cmap_pixvalues_used[cmap_base]) cmap_base++;
178: colordef.pixel = cmap_base;
179: cmap_pixvalues_used[cmap_base++] = PETSC_TRUE;
180: }
181: XStoreColor(display,gColormap,&colordef);
182: }
183: gCmapping[k] = colordef.pixel;
184: gCpalette[k][0] = R[i];
185: gCpalette[k][1] = G[i];
186: gCpalette[k][2] = B[i];
187: }
189: PetscInfo(0,"Successfully allocated colors\n");
190: return(0);
191: }
193: PetscErrorCode PetscDrawSetUpColormap_X(Display *display,int screen,Visual *visual,Colormap colormap)194: {
196: PetscBool sharedcolormap = PETSC_FALSE;
197: XVisualInfo vinfo;
200: PetscOptionsGetBool(NULL,NULL,"-draw_x_shared_colormap",&sharedcolormap,NULL);
201: /*
202: Need to determine if window supports allocating a private colormap,
203: */
204: if (XMatchVisualInfo(display,screen,24,StaticColor,&vinfo) ||
205: XMatchVisualInfo(display,screen,24,TrueColor,&vinfo) ||
206: XMatchVisualInfo(display,screen,16,StaticColor,&vinfo) ||
207: XMatchVisualInfo(display,screen,16,TrueColor,&vinfo) ||
208: XMatchVisualInfo(display,screen,15,StaticColor,&vinfo) ||
209: XMatchVisualInfo(display,screen,15,TrueColor,&vinfo)) sharedcolormap = PETSC_TRUE;
210: /*
211: Generate the X colormap object
212: */
213: if (sharedcolormap) {
214: PetscDrawSetUpColormap_Shared(display,screen,visual,colormap);
215: } else {
216: PetscDrawSetUpColormap_Private(display,screen,visual,colormap);
217: }
218: return(0);
219: }
221: PETSC_INTERN PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X*,Colormap);
223: PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X *XiWin,Colormap colormap)224: {
225: PetscBool fast = PETSC_FALSE;
229: PetscOptionsGetBool(NULL,NULL,"-draw_fast",&fast,NULL);
230: if (XiWin->depth < 8) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"PETSc Graphics require monitors with at least 8 bit color (256 colors)");
231: if (!gColormap) {
232: PetscDrawSetUpColormap_X(XiWin->disp,XiWin->screen,XiWin->vis,colormap);
233: }
234: XiWin->cmap = gColormap;
235: XiWin->cmapsize = fast ? PETSC_DRAW_BASIC_COLORS : 256;
236: PetscMemcpy(XiWin->cmapping,gCmapping,sizeof(XiWin->cmapping));
237: PetscMemcpy(XiWin->cpalette,gCpalette,sizeof(XiWin->cpalette));
238: XiWin->background = XiWin->cmapping[PETSC_DRAW_WHITE];
239: XiWin->foreground = XiWin->cmapping[PETSC_DRAW_BLACK];
240: return(0);
241: }
243: PetscErrorCode PetscDrawXiColormap(PetscDraw_X *XiWin)244: { return PetscDrawSetColormap_X(XiWin,(Colormap)0); }
246: /*
247: Color in X is many-layered. The first layer is the "visual",a
248: immutable attribute of a window set when the window is
249: created.
251: The next layer is the colormap. The installation of colormaps is
252: the buisness of the window manager (in some distant later release).
253: */
255: /*
256: This routine gets the visual class (PseudoColor, etc) and returns
257: it. It finds the default visual. Possible returns are
258: PseudoColor
259: StaticColor
260: DirectColor
261: TrueColor
262: GrayScale
263: StaticGray
264: */
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,DefaultDepth(XiWin->disp,XiWin->screen),PseudoColor,&vinfo)) {
275: XiWin->vis = vinfo.visual;
276: } else {
277: XiWin->vis = DefaultVisual(XiWin->disp,XiWin->screen);
278: }
279: return(0);
280: }
282: PetscErrorCode PetscDrawXiSetColormap(PetscDraw_X *XiWin)283: {
285: XSetWindowColormap(XiWin->disp,XiWin->win,XiWin->cmap);
286: return(0);
287: }
289: /*
290: Get RGB color entries out of the X colormap
291: */
292: PetscErrorCode PetscDrawXiGetPalette(PetscDraw_X *XiWin,unsigned char palette[256][3])
293: {
294: int k;
295: XColor colordef[256];
298: for (k=0; k<256; k++) {
299: colordef[k].pixel = XiWin->cmapping[k];
300: colordef[k].flags = DoRed|DoGreen|DoBlue;
301: }
302: XQueryColors(XiWin->disp,XiWin->cmap,colordef,256);
303: for (k=0; k<256; k++) {
304: palette[k][0] = (unsigned char)(colordef[k].red >> 8);
305: palette[k][1] = (unsigned char)(colordef[k].green >> 8);
306: palette[k][2] = (unsigned char)(colordef[k].blue >> 8);
307: }
308: return(0);
309: }