Actual source code: xcolor.c
1: /*$Id: xcolor.c,v 1.72 2001/03/23 23:20:15 balay Exp $*/
3: /*
4: Code for managing color the X implementation of the PetscDraw routines.
6: Currently we default to using cmapping[0 to PETSC_DRAW_BASIC_COLORS-1] for the basic colors and
7: cmapping[DRAW_BASIC_COLORS to 255] for a uniform hue of all the colors. But in the contour
8: plot we only use from PETSC_DRAW_BASIC_COLORS to 240 since the ones beyond that are too dark.
10: */
11: #include src/sys/src/draw/impls/x/ximpl.h
12: #include <X11/Xatom.h>
14: static char *(colornames[PETSC_DRAW_BASIC_COLORS]) = { "white",
15: "black",
16: "red",
17: "green",
18: "cyan",
19: "blue",
20: "magenta",
21: "aquamarine",
22: "forestgreen",
23: "orange",
24: "violet",
25: "brown",
26: "pink",
27: "coral",
28: "gray",
29: "yellow",
30: "gold",
31: "lightpink",
32: "mediumturquoise",
33: "khaki",
34: "dimgray",
35: "yellowgreen",
36: "skyblue",
37: "darkgreen",
38: "navyblue",
39: "sandybrown",
40: "cadetblue",
41: "powderblue",
42: "deeppink",
43: "thistle",
44: "limegreen",
45: "lavenderblush",
46: "plum"};
48: EXTERN int XiInitCmap(PetscDraw_X*);
49: EXTERN int XiGetVisualClass(PetscDraw_X *);
51: /*
52: Sets up a color map for a display. This is shared by all the windows
53: opened on that display; this is to save time when windows are open so
54: each one does not have to create its own color map which can take 15 to 20 seconds
56: This is new code written 2/26/1999 Barry Smith,I hope it can replace
57: some older,rather confusing code.
59: The calls to XAllocNamedColor() and XAllocColor() are very slow
60: because we have to request from the X server for each
61: color. Could not figure out a way to request a large number at the
62: same time.
64: IMPORTANT: this code will fail if user opens windows on two different
65: displays: should add error checking to detect this. This is because all windows
66: share the same gColormap and gCmapping.
68: */
69: static Colormap gColormap = 0;
70: static PixVal gCmapping[256];
71: int gNumcolors = 0;
73: int PetscDrawSetUpColormap_Shared(Display *display,int screen,Visual *visual,Colormap colormap)
74: {
75: XColor colordef,ecolordef;
76: unsigned char *red,*green,*blue;
77: int i,ierr,ncolors;
78: PetscTruth fast;
81: if (colormap) {
82: gColormap = colormap;
83: } else {
84: gColormap = DefaultColormap(display,screen);
85: }
87: /* set the basic colors into the color map */
88: for (i=0; i<PETSC_DRAW_BASIC_COLORS; i++) {
89: XAllocNamedColor(display,gColormap,colornames[i],&colordef,&ecolordef);
90: gCmapping[i] = colordef.pixel;
91: }
93: /* set the uniform hue colors into the color map */
94: ncolors = 256-PETSC_DRAW_BASIC_COLORS;
95: ierr = PetscMalloc(3*ncolors*sizeof(unsigned char),&red);
96: green = red + ncolors;
97: blue = green + ncolors;
98: ierr = PetscDrawUtilitySetCmapHue(red,green,blue,ncolors);
99: ierr = PetscOptionsHasName(PETSC_NULL,"-draw_fast",&fast);
100: if (!fast) {
101: for (i=PETSC_DRAW_BASIC_COLORS; i<ncolors+PETSC_DRAW_BASIC_COLORS; i++) {
102: colordef.red = ((int)red[i-PETSC_DRAW_BASIC_COLORS] * 65535) / 255;
103: colordef.green = ((int)green[i-PETSC_DRAW_BASIC_COLORS] * 65535) / 255;
104: colordef.blue = ((int)blue[i-PETSC_DRAW_BASIC_COLORS] * 65535) / 255;
105: colordef.flags = DoRed | DoGreen | DoBlue;
106: XAllocColor(display,gColormap,&colordef);
107: gCmapping[i] = colordef.pixel;
108: }
109: }
110: PetscFree(red);
111: PetscLogInfo(0,"PetscDrawSetUpColormap_Shared:Successfully allocated colorsn");
113: return(0);
114: }
116: /*
117: Keep a record of which pixel numbers in the cmap have been
118: used so far; this is to allow us to try to reuse as much of the current
119: colormap as possible.
120: */
121: static PetscTruth cmap_pixvalues_used[256];
122: static int cmap_base = 0;
124: int PetscDrawSetUpColormap_Private(Display *display,int screen,Visual *visual,Colormap colormap)
125: {
126: Colormap defaultmap = DefaultColormap(display,screen);
127: int ierr,found,i,ncolors;
128: XColor colordef;
129: unsigned char *red,*green,*blue;
130: PetscTruth fast;
134: if (colormap) {
135: gColormap = colormap;
136: } else {
137: gColormap = XCreateColormap(display,RootWindow(display,screen),visual,AllocAll);
138: }
140: cmap_base = 0;
141: PetscMemzero(cmap_pixvalues_used,256*sizeof(PetscTruth));
143: /* set the basic colors into the color map */
144: for (i=0; i<PETSC_DRAW_BASIC_COLORS; i++) {
145: XParseColor(display,gColormap,colornames[i],&colordef);
146: /* try to allocate the color in the default-map */
147: found = XAllocColor(display,defaultmap,&colordef);
148: /* use it, if it it exists and is not already used in the new colormap */
149: if (found && colordef.pixel < 256 && !cmap_pixvalues_used[colordef.pixel]) {
150: cmap_pixvalues_used[colordef.pixel] = PETSC_TRUE;
151: /* otherwise search for the next available slot */
152: } else {
153: while (cmap_pixvalues_used[cmap_base]) cmap_base++;
154: colordef.pixel = cmap_base;
155: cmap_pixvalues_used[cmap_base++] = PETSC_TRUE;
156: }
157: XStoreColor(display,gColormap,&colordef);
158: gCmapping[i] = colordef.pixel;
159: }
161: /* set the uniform hue colors into the color map */
162: ncolors = 256-PETSC_DRAW_BASIC_COLORS;
163: ierr = PetscMalloc(3*ncolors*sizeof(unsigned char),&red);
164: green = red + ncolors;
165: blue = green + ncolors;
166: ierr = PetscDrawUtilitySetCmapHue(red,green,blue,ncolors);
167: ierr = PetscOptionsHasName(PETSC_NULL,"-draw_fast",&fast);
168: if (!fast) {
169: for (i=PETSC_DRAW_BASIC_COLORS; i<ncolors+PETSC_DRAW_BASIC_COLORS; i++) {
170: colordef.red = ((int)red[i-PETSC_DRAW_BASIC_COLORS] * 65535) / 255;
171: colordef.green = ((int)green[i-PETSC_DRAW_BASIC_COLORS] * 65535) / 255;
172: colordef.blue = ((int)blue[i-PETSC_DRAW_BASIC_COLORS] * 65535) / 255;
173: colordef.flags = DoRed | DoGreen | DoBlue;
174: /* try to allocate the color in the default-map */
175: found = XAllocColor(display,defaultmap,&colordef);
176: /* use it, if it it exists and is not already used in the new colormap */
177: if (found && colordef.pixel < 256 && !cmap_pixvalues_used[colordef.pixel]) {
178: cmap_pixvalues_used[colordef.pixel] = PETSC_TRUE;
179: /* otherwise search for the next available slot */
180: } else {
181: while (cmap_pixvalues_used[cmap_base]) cmap_base++;
182: colordef.pixel = cmap_base;
183: cmap_pixvalues_used[cmap_base++] = PETSC_TRUE;
184: }
185: XStoreColor(display,gColormap,&colordef);
186: gCmapping[i] = colordef.pixel;
187: }
188: }
189: PetscFree(red);
190: PetscLogInfo(0,"PetscDrawSetUpColormap_Private:Successfully allocated colorsn");
191: return(0);
192: }
194: int PetscDrawSetUpColormap_X(Display *display,int screen,Visual *visual,Colormap colormap)
195: {
196: int ierr;
197: PetscTruth sharedcolormap;
198: XVisualInfo vinfo;
202: /*
203: This is wrong; it needs to take the value from the visual
204: */
205: gNumcolors = 1 << DefaultDepth(display,screen);
207: PetscOptionsHasName(PETSC_NULL,"-draw_x_shared_colormap",&sharedcolormap);
208: /*
209: Need to determine if window supports allocating a private colormap,
210: if not, set flag to 1
211: */
212: if (XMatchVisualInfo(display,screen,24,StaticColor,&vinfo) ||
213: XMatchVisualInfo(display,screen,24,TrueColor,&vinfo) ||
214: XMatchVisualInfo(display,screen,16,StaticColor,&vinfo) ||
215: XMatchVisualInfo(display,screen,16,TrueColor,&vinfo) ||
216: XMatchVisualInfo(display,screen,15,StaticColor,&vinfo) ||
217: XMatchVisualInfo(display,screen,15,TrueColor,&vinfo)) {
218: sharedcolormap = PETSC_TRUE;
219: }
221: /* generate the X color map object */
222: if (sharedcolormap) {
223: PetscDrawSetUpColormap_Shared(display,screen,visual,colormap);
224: } else {
225: PetscDrawSetUpColormap_Private(display,screen,visual,colormap);
226: }
227:
228: return(0);
229: }
231: int PetscDrawSetColormap_X(PetscDraw_X* XiWin,char *host,Colormap colormap)
232: {
236: if (XiWin->depth < 8) {
237: SETERRQ(1,"PETSc Graphics require monitors with at least 8 bit color (256 colors)");
238: }
239: if (!gColormap){
240: Display *display; /* Private display will exist forever contains colormap shared by all windows */
241: int screen;
242: Visual* vis;
244: display = XOpenDisplay(host);
245: screen = DefaultScreen(display);
246: vis = DefaultVisual(display,screen);
248: PetscDrawSetUpColormap_X(display,screen,vis,colormap);
249: }
250: XiWin->cmap = gColormap;
251: PetscMemcpy(XiWin->cmapping,gCmapping,256*sizeof(PixVal));
252: XiWin->background = XiWin->cmapping[PETSC_DRAW_WHITE];
253: XiWin->foreground = XiWin->cmapping[PETSC_DRAW_BLACK];
254: return(0);
255: }
257: /*
258: Color in X is many-layered. The first layer is the "visual",a
259: immutable attribute of a window set when the window is
260: created.
262: The next layer is the colormap. The installation of colormaps is
263: the buisness of the window manager (in some distant later release).
264: */
266: /*
267: This routine gets the visual class (PseudoColor, etc) and returns
268: it. It finds the default visual. Possible returns are
269: PseudoColor
270: StaticColor
271: DirectColor
272: TrueColor
273: GrayScale
274: StaticGray
275: */
276: int XiSetVisualClass(PetscDraw_X* XiWin)
277: {
278: XVisualInfo vinfo;
281: if (XMatchVisualInfo(XiWin->disp,XiWin->screen,24,DirectColor,&vinfo)) {
282: XiWin->vis = vinfo.visual;
283: return(0);
284: }
285: if (XMatchVisualInfo(XiWin->disp,XiWin->screen,8,PseudoColor,&vinfo)) {
286: XiWin->vis = vinfo.visual;
287: return(0);
288: }
289: if (XMatchVisualInfo(XiWin->disp,XiWin->screen,
290: DefaultDepth(XiWin->disp,XiWin->screen),PseudoColor,&vinfo)) {
291: XiWin->vis = vinfo.visual;
292: return(0);
293: }
294: XiWin->vis = DefaultVisual(XiWin->disp,XiWin->screen);
295: return(0);
296: }
298: int XiGetVisualClass(PetscDraw_X* XiWin)
299: {
301: #if defined(__cplusplus)
302: PetscFunctionReturn(XiWin->vis->c_class);
303: #else
304: PetscFunctionReturn(XiWin->vis->class);
305: #endif
306: }
309: int XiSetColormap(PetscDraw_X* XiWin)
310: {
312: XSetWindowColormap(XiWin->disp,XiWin->win,XiWin->cmap);
313: return(0);
314: }
316: int XiGetBaseColor(PetscDraw_X* XiWin,PixVal* white_pix,PixVal* black_pix)
317: {
319: *white_pix = XiWin->cmapping[PETSC_DRAW_WHITE];
320: *black_pix = XiWin->cmapping[PETSC_DRAW_BLACK];
321: return(0);
322: }
326: /*
327: This routine returns the pixel value for the specified color
328: Returns 0 on failure,<>0 otherwise.
329: */
330: int XiFindColor(PetscDraw_X *XiWin,char *name,PixVal *pixval)
331: {
332: XColor colordef;
333: int st;
336: st = XParseColor(XiWin->disp,XiWin->cmap,name,&colordef);
337: if (st) {
338: st = XAllocColor(XiWin->disp,XiWin->cmap,&colordef);
339: if (st) *pixval = colordef.pixel;
340: }
341: PetscFunctionReturn(st);
342: }
344: /*
345: Another real need is to assign "colors" that make sense for
346: a monochrome display,without unduely penalizing color displays.
347: This routine takes a color name,a window, and a flag that
348: indicates whether this is "background" or "foreground".
349: In the monchrome case (or if the color is otherwise unavailable),
350: the "background" or "foreground" colors will be chosen
351: */
352: PixVal XiGetColor(PetscDraw_X* XiWin,char *name,int is_fore)
353: {
354: PixVal pixval;
357: if (XiWin->numcolors == 2 || !XiFindColor(XiWin,name,&pixval)) {
358: pixval = is_fore ? XiWin->cmapping[PETSC_DRAW_WHITE] : XiWin->cmapping[PETSC_DRAW_BLACK];
359: }
360: PetscFunctionReturn(pixval);
361: }
363: /*
364: This routine takes a named color and returns a color that is either
365: lighter or darker
366: */
367: PixVal XiSimColor(PetscDraw_X *XiWin,PixVal pixel,int intensity,int is_fore)
368: {
369: XColor colordef,colorsdef;
370: char RGBcolor[20];
371: PixVal red,green,blue;
374: colordef.pixel = pixel;
375: XQueryColor(XiWin->disp,XiWin->cmap,&colordef);
376: /* Adjust the color value up or down. Get the RGB values for the color */
377: red = colordef.red;
378: green = colordef.green;
379: blue = colordef.blue;
380: #define WHITE_AMOUNT 5000
381: if (intensity > 0) {
382: /* Add white to the color */
383: red = PetscMin(65535,red + WHITE_AMOUNT);
384: green = PetscMin(65535,green + WHITE_AMOUNT);
385: blue = PetscMin(65535,blue + WHITE_AMOUNT);
386: } else {
387: /* Subtract white from the color */
388: red = (red < WHITE_AMOUNT) ? 0 : red - WHITE_AMOUNT;
389: green = (green < WHITE_AMOUNT) ? 0 : green - WHITE_AMOUNT;
390: blue = (blue < WHITE_AMOUNT) ? 0 : blue - WHITE_AMOUNT;
391: }
392: sprintf(RGBcolor,"rgb:%4.4x/%4.4x/%4.4x",(unsigned int)red,
393: (unsigned int)green,(unsigned int)blue);
394: XLookupColor(XiWin->disp,XiWin->cmap,RGBcolor,&colordef,&colorsdef);
395: PetscFunctionReturn(colorsdef.pixel);
396: }
398: /*
399: XiSetCmapLight - Create rgb values from a single color by adding white
400:
401: The initial color is (red[0],green[0],blue[0]).
402: */
403: int XiSetCmapLight(unsigned char *red,unsigned char *green,unsigned char *blue,int mapsize)
404: {
405: int i ;
408: for (i=1; i<mapsize-1; i++) {
409: blue[i] = i*(255-(int)blue[0])/(mapsize-2)+blue[0] ;
410: green[i] = i*(255-(int)green[0])/(mapsize-2)+green[0] ;
411: red[i] = i*(255-(int)red[0])/(mapsize-2)+red[0] ;
412: }
413: red[mapsize-1] = green[mapsize-1] = blue[mapsize-1] = 255;
414: return(0);
415: }