Actual source code: xcolor.c

petsc-3.7.3 2016-08-01
Report Typos and Errors
  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];

 70: PetscErrorCode PetscDrawSetUpColormap_Shared(Display *display,int screen,Visual *visual,Colormap colormap)
 71: {
 72:   int            i,k,ncolors = 256-PETSC_DRAW_BASIC_COLORS;
 73:   unsigned char  R[256-PETSC_DRAW_BASIC_COLORS];
 74:   unsigned char  G[256-PETSC_DRAW_BASIC_COLORS];
 75:   unsigned char  B[256-PETSC_DRAW_BASIC_COLORS];
 76:   XColor         colordef,ecolordef;
 77:   PetscBool      fast = PETSC_FALSE;

 81:   if (colormap) gColormap = colormap;
 82:   else          gColormap = DefaultColormap(display,screen);


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

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

110:   PetscInfo(0,"Successfully allocated colors\n");
111:   return(0);
112: }

114: /*
115:     Keep a record of which pixel numbers in the cmap have been
116:   used so far; this is to allow us to try to reuse as much of the current
117:   colormap as possible.
118: */
119: static PetscBool cmap_pixvalues_used[256];
120: static int       cmap_base = 0;

124: PetscErrorCode PetscDrawSetUpColormap_Private(Display *display,int screen,Visual *visual,Colormap colormap)
125: {
126:   int            found,i,k,ncolors = 256-PETSC_DRAW_BASIC_COLORS;
127:   unsigned char  R[256-PETSC_DRAW_BASIC_COLORS];
128:   unsigned char  G[256-PETSC_DRAW_BASIC_COLORS];
129:   unsigned char  B[256-PETSC_DRAW_BASIC_COLORS];
130:   Colormap       defaultmap = DefaultColormap(display,screen);
131:   XColor         colordef;
132:   PetscBool      fast = PETSC_FALSE;

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

139:   cmap_base = 0;

141:   PetscMemzero(cmap_pixvalues_used,256*sizeof(PetscBool));

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:     gCpalette[i][0] = (unsigned char)(colordef.red   >> 8);
160:     gCpalette[i][1] = (unsigned char)(colordef.green >> 8);
161:     gCpalette[i][2] = (unsigned char)(colordef.blue  >> 8);
162:   }

164:   /* set the contour colors into the colormap */
165:   PetscOptionsGetBool(NULL,NULL,"-draw_fast",&fast,NULL);
166:   PetscDrawUtilitySetCmap(NULL,ncolors,R,G,B);
167:   for (i=0, k=PETSC_DRAW_BASIC_COLORS; i<ncolors; i++, k++) {
168:     colordef.red   = (unsigned short)(R[i] << 8);
169:     colordef.green = (unsigned short)(G[i] << 8);
170:     colordef.blue  = (unsigned short)(B[i] << 8);
171:     colordef.flags = DoRed|DoGreen|DoBlue;
172:     colordef.pixel = gCmapping[PETSC_DRAW_BLACK];
173:     if (!fast) {
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:     }
187:     gCmapping[k]    = colordef.pixel;
188:     gCpalette[k][0] = R[i];
189:     gCpalette[k][1] = G[i];
190:     gCpalette[k][2] = B[i];
191:   }

193:   PetscInfo(0,"Successfully allocated colors\n");
194:   return(0);
195: }

199: PetscErrorCode PetscDrawSetUpColormap_X(Display *display,int screen,Visual *visual,Colormap colormap)
200: {
202:   PetscBool      sharedcolormap = PETSC_FALSE;
203:   XVisualInfo    vinfo;

206:   PetscOptionsGetBool(NULL,NULL,"-draw_x_shared_colormap",&sharedcolormap,NULL);
207:   /*
208:      Need to determine if window supports allocating a private colormap,
209:   */
210:   if (XMatchVisualInfo(display,screen,24,StaticColor,&vinfo) ||
211:       XMatchVisualInfo(display,screen,24,TrueColor,&vinfo)   ||
212:       XMatchVisualInfo(display,screen,16,StaticColor,&vinfo) ||
213:       XMatchVisualInfo(display,screen,16,TrueColor,&vinfo)   ||
214:       XMatchVisualInfo(display,screen,15,StaticColor,&vinfo) ||
215:       XMatchVisualInfo(display,screen,15,TrueColor,&vinfo)) sharedcolormap = PETSC_TRUE;
216:   /*
217:      Generate the X colormap object
218:   */
219:   if (sharedcolormap) {
220:     PetscDrawSetUpColormap_Shared(display,screen,visual,colormap);
221:   } else {
222:     PetscDrawSetUpColormap_Private(display,screen,visual,colormap);
223:   }
224:   return(0);
225: }

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

231: PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X *XiWin,Colormap colormap)
232: {
233:   PetscBool      fast = PETSC_FALSE;

237:   PetscOptionsGetBool(NULL,NULL,"-draw_fast",&fast,NULL);
238:   if (XiWin->depth < 8) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"PETSc Graphics require monitors with at least 8 bit color (256 colors)");
239:   if (!gColormap) {
240:     PetscDrawSetUpColormap_X(XiWin->disp,XiWin->screen,XiWin->vis,colormap);
241:   }
242:   XiWin->cmap     = gColormap;
243:   XiWin->cmapsize = fast ? PETSC_DRAW_BASIC_COLORS : 256;
244:   PetscMemcpy(XiWin->cmapping,gCmapping,sizeof(XiWin->cmapping));
245:   PetscMemcpy(XiWin->cpalette,gCpalette,sizeof(XiWin->cpalette));
246:   XiWin->background = XiWin->cmapping[PETSC_DRAW_WHITE];
247:   XiWin->foreground = XiWin->cmapping[PETSC_DRAW_BLACK];
248:   return(0);
249: }

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

256: /*
257:     Color in X is many-layered.  The first layer is the "visual",a
258:     immutable attribute of a window set when the window is
259:     created.

261:     The next layer is the colormap.  The installation of colormaps is
262:     the buisness of the window manager (in some distant later release).
263: */

265: /*
266:     This routine gets the visual class (PseudoColor, etc) and returns
267:     it.  It finds the default visual.  Possible returns are
268:         PseudoColor
269:         StaticColor
270:         DirectColor
271:         TrueColor
272:         GrayScale
273:         StaticGray
274:  */
277: PetscErrorCode PetscDrawXiSetVisualClass(PetscDraw_X *XiWin)
278: {
279:   XVisualInfo vinfo;

282:   if (XMatchVisualInfo(XiWin->disp,XiWin->screen,24,DirectColor,&vinfo)) {
283:     XiWin->vis = vinfo.visual;
284:   } else if (XMatchVisualInfo(XiWin->disp,XiWin->screen,8,PseudoColor,&vinfo)) {
285:     XiWin->vis = vinfo.visual;
286:   } else if (XMatchVisualInfo(XiWin->disp,XiWin->screen,DefaultDepth(XiWin->disp,XiWin->screen),PseudoColor,&vinfo)) {
287:     XiWin->vis = vinfo.visual;
288:   } else {
289:     XiWin->vis = DefaultVisual(XiWin->disp,XiWin->screen);
290:   }
291:   return(0);
292: }

296: PetscErrorCode PetscDrawXiSetColormap(PetscDraw_X *XiWin)
297: {
299:   XSetWindowColormap(XiWin->disp,XiWin->win,XiWin->cmap);
300:   return(0);
301: }

303: /*
304:    Get RGB color entries out of the X colormap
305: */
308: PetscErrorCode PetscDrawXiGetPalette(PetscDraw_X *XiWin,unsigned char palette[256][3])
309: {
310:   int    k;
311:   XColor colordef[256];

314:   for (k=0; k<256; k++) {
315:     colordef[k].pixel = XiWin->cmapping[k];
316:     colordef[k].flags = DoRed|DoGreen|DoBlue;
317:   }
318:   XQueryColors(XiWin->disp,XiWin->cmap,colordef,256);
319:   for (k=0; k<256; k++) {
320:     palette[k][0] = (unsigned char)(colordef[k].red   >> 8);
321:     palette[k][1] = (unsigned char)(colordef[k].green >> 8);
322:     palette[k][2] = (unsigned char)(colordef[k].blue  >> 8);
323:   }
324:   return(0);
325: }