Actual source code: xcolor.c

petsc-3.8.4 2018-03-24
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];

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