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);

     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(NULL,"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(NULL,"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: }