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;

 79:   if (colormap) gColormap = colormap;
 80:   else          gColormap = DefaultColormap(display,screen);

 82:   /* set the basic colors into the color map */
 83:   for (i=0; i<PETSC_DRAW_BASIC_COLORS; i++) {
 84:     XAllocNamedColor(display,gColormap,colornames[i],&colordef,&ecolordef);
 85:     gCmapping[i]    = colordef.pixel;
 86:     gCpalette[i][0] = (unsigned char)(colordef.red   >> 8);
 87:     gCpalette[i][1] = (unsigned char)(colordef.green >> 8);
 88:     gCpalette[i][2] = (unsigned char)(colordef.blue  >> 8);
 89:   }

 91:   /* set the contour colors into the colormap */
 92:   PetscOptionsGetBool(NULL,NULL,"-draw_fast",&fast,NULL);
 93:   PetscDrawUtilitySetCmap(NULL,ncolors,R,G,B);
 94:   for (i=0, k=PETSC_DRAW_BASIC_COLORS; i<ncolors; i++, k++) {
 95:     colordef.red   = (unsigned short)(R[i] << 8);
 96:     colordef.green = (unsigned short)(G[i] << 8);
 97:     colordef.blue  = (unsigned short)(B[i] << 8);
 98:     colordef.flags = DoRed|DoGreen|DoBlue;
 99:     colordef.pixel = gCmapping[PETSC_DRAW_BLACK];
100:     if (!fast) XAllocColor(display,gColormap,&colordef);
101:     gCmapping[k]    = colordef.pixel;
102:     gCpalette[k][0] = R[i];
103:     gCpalette[k][1] = G[i];
104:     gCpalette[k][2] = B[i];
105:   }

107:   PetscInfo(NULL,"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[PETSC_DRAW_MAXCOLOR];
117: static int       cmap_base = 0;

119: PetscErrorCode PetscDrawSetUpColormap_Private(Display *display,int screen,Visual *visual,Colormap colormap)
120: {
121:   int            found,i,k,ncolors = PETSC_DRAW_MAXCOLOR-PETSC_DRAW_BASIC_COLORS;
122:   unsigned char  R[PETSC_DRAW_MAXCOLOR-PETSC_DRAW_BASIC_COLORS];
123:   unsigned char  G[PETSC_DRAW_MAXCOLOR-PETSC_DRAW_BASIC_COLORS];
124:   unsigned char  B[PETSC_DRAW_MAXCOLOR-PETSC_DRAW_BASIC_COLORS];
125:   Colormap       defaultmap = DefaultColormap(display,screen);
126:   XColor         colordef;
127:   PetscBool      fast = PETSC_FALSE;

129:   if (colormap) gColormap = colormap;
130:   else          gColormap = XCreateColormap(display,RootWindow(display,screen),visual,AllocAll);

132:   cmap_base = 0;

134:   PetscMemzero(cmap_pixvalues_used,sizeof(cmap_pixvalues_used));

136:   /* set the basic colors into the color map */
137:   for (i=0; i<PETSC_DRAW_BASIC_COLORS; i++) {
138:     XParseColor(display,gColormap,colornames[i],&colordef);
139:     /* try to allocate the color in the default-map */
140:     found = XAllocColor(display,defaultmap,&colordef);
141:     /* use it, if it it exists and is not already used in the new colormap */
142:     if (found && colordef.pixel < PETSC_DRAW_MAXCOLOR  && !cmap_pixvalues_used[colordef.pixel]) {
143:       cmap_pixvalues_used[colordef.pixel] = PETSC_TRUE;
144:       /* otherwise search for the next available slot */
145:     } else {
146:       while (cmap_pixvalues_used[cmap_base]) cmap_base++;
147:       colordef.pixel                   = cmap_base;
148:       cmap_pixvalues_used[cmap_base++] = PETSC_TRUE;
149:     }
150:     XStoreColor(display,gColormap,&colordef);
151:     gCmapping[i]    = colordef.pixel;
152:     gCpalette[i][0] = (unsigned char)(colordef.red   >> 8);
153:     gCpalette[i][1] = (unsigned char)(colordef.green >> 8);
154:     gCpalette[i][2] = (unsigned char)(colordef.blue  >> 8);
155:   }

157:   /* set the contour colors into the colormap */
158:   PetscOptionsGetBool(NULL,NULL,"-draw_fast",&fast,NULL);
159:   PetscDrawUtilitySetCmap(NULL,ncolors,R,G,B);
160:   for (i=0, k=PETSC_DRAW_BASIC_COLORS; i<ncolors; i++, k++) {
161:     colordef.red   = (unsigned short)(R[i] << 8);
162:     colordef.green = (unsigned short)(G[i] << 8);
163:     colordef.blue  = (unsigned short)(B[i] << 8);
164:     colordef.flags = DoRed|DoGreen|DoBlue;
165:     colordef.pixel = gCmapping[PETSC_DRAW_BLACK];
166:     if (!fast) {
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 < PETSC_DRAW_MAXCOLOR  && !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:     }
180:     gCmapping[k]    = colordef.pixel;
181:     gCpalette[k][0] = R[i];
182:     gCpalette[k][1] = G[i];
183:     gCpalette[k][2] = B[i];
184:   }

186:   PetscInfo(NULL,"Successfully allocated colors\n");
187:   return 0;
188: }

190: PetscErrorCode PetscDrawSetUpColormap_X(Display *display,int screen,Visual *visual,Colormap colormap)
191: {
192:   PetscBool      sharedcolormap = PETSC_FALSE;
193:   XVisualInfo    vinfo;

195:   PetscOptionsGetBool(NULL,NULL,"-draw_x_shared_colormap",&sharedcolormap,NULL);
196:   /*
197:      Need to determine if window supports allocating a private colormap,
198:   */
199:   if (XMatchVisualInfo(display,screen,24,StaticColor,&vinfo) ||
200:       XMatchVisualInfo(display,screen,24,TrueColor,&vinfo)   ||
201:       XMatchVisualInfo(display,screen,16,StaticColor,&vinfo) ||
202:       XMatchVisualInfo(display,screen,16,TrueColor,&vinfo)   ||
203:       XMatchVisualInfo(display,screen,15,StaticColor,&vinfo) ||
204:       XMatchVisualInfo(display,screen,15,TrueColor,&vinfo)) sharedcolormap = PETSC_TRUE;
205:   /*
206:      Generate the X colormap object
207:   */
208:   if (sharedcolormap) {
209:     PetscDrawSetUpColormap_Shared(display,screen,visual,colormap);
210:   } else {
211:     PetscDrawSetUpColormap_Private(display,screen,visual,colormap);
212:   }
213:   return 0;
214: }

216: PETSC_INTERN PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X*,Colormap);

218: PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X *XiWin,Colormap colormap)
219: {
220:   PetscBool      fast = PETSC_FALSE;

222:   PetscOptionsGetBool(NULL,NULL,"-draw_fast",&fast,NULL);
224:   if (!gColormap) {
225:     PetscDrawSetUpColormap_X(XiWin->disp,XiWin->screen,XiWin->vis,colormap);
226:   }
227:   XiWin->cmap     = gColormap;
228:   XiWin->cmapsize = fast ? PETSC_DRAW_BASIC_COLORS : PETSC_DRAW_MAXCOLOR;
229:   PetscMemcpy(XiWin->cmapping,gCmapping,sizeof(XiWin->cmapping));
230:   PetscMemcpy(XiWin->cpalette,gCpalette,sizeof(XiWin->cpalette));
231:   XiWin->background = XiWin->cmapping[PETSC_DRAW_WHITE];
232:   XiWin->foreground = XiWin->cmapping[PETSC_DRAW_BLACK];
233:   return 0;
234: }

236: PetscErrorCode PetscDrawXiColormap(PetscDraw_X *XiWin)
237: { return PetscDrawSetColormap_X(XiWin,(Colormap)0); }

239: /*
240:     Color in X is many-layered.  The first layer is the "visual",a
241:     immutable attribute of a window set when the window is
242:     created.

244:     The next layer is the colormap.  The installation of colormaps is
245:     the buisness of the window manager (in some distant later release).
246: */

248: /*
249:     This routine gets the visual class (PseudoColor, etc) and returns
250:     it.  It finds the default visual.  Possible returns are
251:         PseudoColor
252:         StaticColor
253:         DirectColor
254:         TrueColor
255:         GrayScale
256:         StaticGray
257:  */
258: PetscErrorCode PetscDrawXiSetVisualClass(PetscDraw_X *XiWin)
259: {
260:   XVisualInfo vinfo;

262:   if (XMatchVisualInfo(XiWin->disp,XiWin->screen,24,DirectColor,&vinfo)) {
263:     XiWin->vis = vinfo.visual;
264:   } else if (XMatchVisualInfo(XiWin->disp,XiWin->screen,8,PseudoColor,&vinfo)) {
265:     XiWin->vis = vinfo.visual;
266:   } else if (XMatchVisualInfo(XiWin->disp,XiWin->screen,DefaultDepth(XiWin->disp,XiWin->screen),PseudoColor,&vinfo)) {
267:     XiWin->vis = vinfo.visual;
268:   } else {
269:     XiWin->vis = DefaultVisual(XiWin->disp,XiWin->screen);
270:   }
271:   return 0;
272: }

274: PetscErrorCode PetscDrawXiSetColormap(PetscDraw_X *XiWin)
275: {
276:   XSetWindowColormap(XiWin->disp,XiWin->win,XiWin->cmap);
277:   return 0;
278: }

280: /*
281:    Get RGB color entries out of the X colormap
282: */
283: PetscErrorCode PetscDrawXiGetPalette(PetscDraw_X *XiWin,unsigned char palette[PETSC_DRAW_MAXCOLOR][3])
284: {
285:   int    k;
286:   XColor colordef[PETSC_DRAW_MAXCOLOR];

288:   for (k=0; k<PETSC_DRAW_MAXCOLOR; k++) {
289:     colordef[k].pixel = XiWin->cmapping[k];
290:     colordef[k].flags = DoRed|DoGreen|DoBlue;
291:   }
292:   XQueryColors(XiWin->disp,XiWin->cmap,colordef,PETSC_DRAW_MAXCOLOR);
293:   for (k=0; k<PETSC_DRAW_MAXCOLOR; k++) {
294:     palette[k][0] = (unsigned char)(colordef[k].red   >> 8);
295:     palette[k][1] = (unsigned char)(colordef[k].green >> 8);
296:     palette[k][2] = (unsigned char)(colordef[k].blue  >> 8);
297:   }
298:   return 0;
299: }