Actual source code: xcolor.c

petsc-3.10.5 2019-03-28
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] = {
 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);


 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[PETSC_DRAW_MAXCOLOR];
120: static int       cmap_base = 0;

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

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

137:   cmap_base = 0;

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

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

162:   /* set the contour colors into the colormap */
163:   PetscOptionsGetBool(NULL,NULL,"-draw_fast",&fast,NULL);
164:   PetscDrawUtilitySetCmap(NULL,ncolors,R,G,B);
165:   for (i=0, k=PETSC_DRAW_BASIC_COLORS; i<ncolors; i++, k++) {
166:     colordef.red   = (unsigned short)(R[i] << 8);
167:     colordef.green = (unsigned short)(G[i] << 8);
168:     colordef.blue  = (unsigned short)(B[i] << 8);
169:     colordef.flags = DoRed|DoGreen|DoBlue;
170:     colordef.pixel = gCmapping[PETSC_DRAW_BLACK];
171:     if (!fast) {
172:       /* try to allocate the color in the default-map */
173:       found = XAllocColor(display,defaultmap,&colordef);
174:       /* use it, if it it exists and is not already used in the new colormap */
175:       if (found && colordef.pixel < PETSC_DRAW_MAXCOLOR  && !cmap_pixvalues_used[colordef.pixel]) {
176:         cmap_pixvalues_used[colordef.pixel] = PETSC_TRUE;
177:         /* otherwise search for the next available slot */
178:       } else {
179:         while (cmap_pixvalues_used[cmap_base]) cmap_base++;
180:         colordef.pixel                   = cmap_base;
181:         cmap_pixvalues_used[cmap_base++] = PETSC_TRUE;
182:       }
183:       XStoreColor(display,gColormap,&colordef);
184:     }
185:     gCmapping[k]    = colordef.pixel;
186:     gCpalette[k][0] = R[i];
187:     gCpalette[k][1] = G[i];
188:     gCpalette[k][2] = B[i];
189:   }

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

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

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

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

225: PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X *XiWin,Colormap colormap)
226: {
227:   PetscBool      fast = PETSC_FALSE;

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

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

248: /*
249:     Color in X is many-layered.  The first layer is the "visual",a
250:     immutable attribute of a window set when the window is
251:     created.

253:     The next layer is the colormap.  The installation of colormaps is
254:     the buisness of the window manager (in some distant later release).
255: */

257: /*
258:     This routine gets the visual class (PseudoColor, etc) and returns
259:     it.  It finds the default visual.  Possible returns are
260:         PseudoColor
261:         StaticColor
262:         DirectColor
263:         TrueColor
264:         GrayScale
265:         StaticGray
266:  */
267: PetscErrorCode PetscDrawXiSetVisualClass(PetscDraw_X *XiWin)
268: {
269:   XVisualInfo vinfo;

272:   if (XMatchVisualInfo(XiWin->disp,XiWin->screen,24,DirectColor,&vinfo)) {
273:     XiWin->vis = vinfo.visual;
274:   } else if (XMatchVisualInfo(XiWin->disp,XiWin->screen,8,PseudoColor,&vinfo)) {
275:     XiWin->vis = vinfo.visual;
276:   } else if (XMatchVisualInfo(XiWin->disp,XiWin->screen,DefaultDepth(XiWin->disp,XiWin->screen),PseudoColor,&vinfo)) {
277:     XiWin->vis = vinfo.visual;
278:   } else {
279:     XiWin->vis = DefaultVisual(XiWin->disp,XiWin->screen);
280:   }
281:   return(0);
282: }

284: PetscErrorCode PetscDrawXiSetColormap(PetscDraw_X *XiWin)
285: {
287:   XSetWindowColormap(XiWin->disp,XiWin->win,XiWin->cmap);
288:   return(0);
289: }

291: /*
292:    Get RGB color entries out of the X colormap
293: */
294: PetscErrorCode PetscDrawXiGetPalette(PetscDraw_X *XiWin,unsigned char palette[PETSC_DRAW_MAXCOLOR][3])
295: {
296:   int    k;
297:   XColor colordef[PETSC_DRAW_MAXCOLOR];

300:   for (k=0; k<PETSC_DRAW_MAXCOLOR; k++) {
301:     colordef[k].pixel = XiWin->cmapping[k];
302:     colordef[k].flags = DoRed|DoGreen|DoBlue;
303:   }
304:   XQueryColors(XiWin->disp,XiWin->cmap,colordef,PETSC_DRAW_MAXCOLOR);
305:   for (k=0; k<PETSC_DRAW_MAXCOLOR; k++) {
306:     palette[k][0] = (unsigned char)(colordef[k].red   >> 8);
307:     palette[k][1] = (unsigned char)(colordef[k].green >> 8);
308:     palette[k][2] = (unsigned char)(colordef[k].blue  >> 8);
309:   }
310:   return(0);
311: }