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