Date: 2013-07-02T14:38:21+00:00

Actual source code: xcolor.c
petsc-3.4.2 2013-07-02

      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 a uniform hue of all the colors. But in the contour
      7:   plot we only use from PETSC_DRAW_BASIC_COLORS to 240 since the ones beyond that are too dark.

      9: */
     10: #include <../src/sys/classes/draw/impls/x/ximpl.h>
     11: #include <X11/Xatom.h>

     13: static const char *(colornames[PETSC_DRAW_BASIC_COLORS]) = {"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"};

     47: extern PetscErrorCode PetscDrawXiInitCmap(PetscDraw_X*);
     48: extern PetscErrorCode PetscDrawXiGetVisualClass(PetscDraw_X*);

     50: /*
     51:    Sets up a color map for a display. This is shared by all the windows
     52:   opened on that display; this is to save time when windows are open so
     53:   each one does not have to create its own color map which can take 15 to 20 seconds

     55:      This is new code written 2/26/1999 Barry Smith,I hope it can replace
     56:   some older,rather confusing code.

     58:      The calls to XAllocNamedColor() and XAllocColor() are very slow
     59:      because we have to request from the X server for each
     60:      color. Could not figure out a way to request a large number at the
     61:      same time.

     63:    IMPORTANT: this code will fail if user opens windows on two different
     64:   displays: should add error checking to detect this. This is because all windows
     65:   share the same gColormap and gCmapping.

     67: */
     68: static Colormap          gColormap = 0;
     69: static PetscDrawXiPixVal gCmapping[256];

     73: PetscErrorCode PetscDrawSetUpColormap_Shared(Display *display,int screen,Visual *visual,Colormap colormap)
     74: {
     75:   XColor         colordef,ecolordef;
     76:   unsigned char  *red,*green,*blue;
     77:   int            i,ncolors;
     79:   PetscBool      fast = PETSC_FALSE;

     82:   if (colormap) gColormap = colormap;
     83:   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:   }

     91:   /* set the uniform hue colors into the color map */
     92:   ncolors = 256-PETSC_DRAW_BASIC_COLORS;
     93:   PetscMalloc3(ncolors,unsigned char,&red,ncolors,unsigned char,&green,ncolors,unsigned char,&blue);
     94:   PetscDrawUtilitySetCmapHue(red,green,blue,ncolors);
     95:   PetscOptionsGetBool(NULL,"-draw_fast",&fast,NULL);
     96:   if (!fast) {
     97:     for (i=PETSC_DRAW_BASIC_COLORS; i<ncolors+PETSC_DRAW_BASIC_COLORS; i++) {
     98:       colordef.red   = ((int)red[i-PETSC_DRAW_BASIC_COLORS]   * 65535) / 255;
     99:       colordef.green = ((int)green[i-PETSC_DRAW_BASIC_COLORS] * 65535) / 255;
    100:       colordef.blue  = ((int)blue[i-PETSC_DRAW_BASIC_COLORS]  * 65535) / 255;
    101:       colordef.flags = DoRed | DoGreen | DoBlue;
    102:       XAllocColor(display,gColormap,&colordef);
    103:       gCmapping[i]   = colordef.pixel;
    104:     }
    105:   }
    106:   PetscFree3(red,green,blue);
    107:   PetscInfo(0,"Successfully allocated colors\n");
    108:   return(0);
    109: }

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

    121: PetscErrorCode PetscDrawSetUpColormap_Private(Display *display,int screen,Visual *visual,Colormap colormap)
    122: {
    123:   Colormap       defaultmap = DefaultColormap(display,screen);
    125:   int            found,i,ncolors;
    126:   XColor         colordef;
    127:   unsigned char  *red,*green,*blue;
    128:   PetscBool      fast = PETSC_FALSE;

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

    134:   cmap_base = 0;

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

    138:   /* set the basic colors into the color map */
    139:   for (i=0; i<PETSC_DRAW_BASIC_COLORS; i++) {
    140:     XParseColor(display,gColormap,colornames[i],&colordef);
    141:     /* try to allocate the color in the default-map */
    142:     found = XAllocColor(display,defaultmap,&colordef);
    143:     /* use it, if it it exists and is not already used in the new colormap */
    144:     if (found && colordef.pixel < 256  && !cmap_pixvalues_used[colordef.pixel]) {
    145:       cmap_pixvalues_used[colordef.pixel] = PETSC_TRUE;
    146:       /* otherwise search for the next available slot */
    147:     } else {
    148:       while (cmap_pixvalues_used[cmap_base]) cmap_base++;
    149:       colordef.pixel                   = cmap_base;
    150:       cmap_pixvalues_used[cmap_base++] = PETSC_TRUE;
    151:     }
    152:     XStoreColor(display,gColormap,&colordef);
    153:     gCmapping[i] = colordef.pixel;
    154:   }

    156:   /* set the uniform hue colors into the color map */
    157:   ncolors = 256-PETSC_DRAW_BASIC_COLORS;
    158:   PetscMalloc3(ncolors,unsigned char,&red,ncolors,unsigned char,&green,ncolors,unsigned char,&blue);
    159:   PetscDrawUtilitySetCmapHue(red,green,blue,ncolors);
    160:   PetscOptionsGetBool(NULL,"-draw_fast",&fast,NULL);
    161:   if (!fast) {
    162:     for (i=PETSC_DRAW_BASIC_COLORS; i<ncolors+PETSC_DRAW_BASIC_COLORS; i++) {
    163:       colordef.red   = ((int)red[i-PETSC_DRAW_BASIC_COLORS]   * 65535) / 255;
    164:       colordef.green = ((int)green[i-PETSC_DRAW_BASIC_COLORS] * 65535) / 255;
    165:       colordef.blue  = ((int)blue[i-PETSC_DRAW_BASIC_COLORS]  * 65535) / 255;
    166:       colordef.flags = DoRed | DoGreen | DoBlue;
    167:       /* try to allocate the color in the default-map */
    168:       found = XAllocColor(display,defaultmap,&colordef);
    169:       /* use it, if it it exists and is not already used in the new colormap */
    170:       if (found && colordef.pixel < 256  && !cmap_pixvalues_used[colordef.pixel]) {
    171:         cmap_pixvalues_used[colordef.pixel] = PETSC_TRUE;
    172:         /* otherwise search for the next available slot */
    173:       } else {
    174:         while (cmap_pixvalues_used[cmap_base]) cmap_base++;
    175:         colordef.pixel                   = cmap_base;
    176:         cmap_pixvalues_used[cmap_base++] = PETSC_TRUE;
    177:       }
    178:       XStoreColor(display,gColormap,&colordef);
    179:       gCmapping[i] = colordef.pixel;
    180:     }
    181:   }
    182:   PetscFree3(red,green,blue);
    183:   PetscInfo(0,"Successfully allocated colors\n");
    184:   return(0);
    185: }

    189: PetscErrorCode PetscDrawSetUpColormap_X(Display *display,int screen,Visual *visual,Colormap colormap)
    190: {
    192:   PetscBool      sharedcolormap = PETSC_FALSE;
    193:   XVisualInfo    vinfo;

    196:   PetscOptionsGetBool(NULL,"-draw_x_shared_colormap",&sharedcolormap,NULL);
    197:   /*
    198:         Need to determine if window supports allocating a private colormap,
    199:   */
    200:   if (XMatchVisualInfo(display,screen,24,StaticColor,&vinfo) ||
    201:       XMatchVisualInfo(display,screen,24,TrueColor,&vinfo)   ||
    202:       XMatchVisualInfo(display,screen,16,StaticColor,&vinfo) ||
    203:       XMatchVisualInfo(display,screen,16,TrueColor,&vinfo)   ||
    204:       XMatchVisualInfo(display,screen,15,StaticColor,&vinfo) ||
    205:       XMatchVisualInfo(display,screen,15,TrueColor,&vinfo)) sharedcolormap = PETSC_TRUE;

    207:   /* generate the X color map object */
    208:   if (sharedcolormap) {
    209:     PetscDrawSetUpColormap_Shared(display,screen,visual,colormap);
    210:   } else {
    211:     PetscDrawSetUpColormap_Private(display,screen,visual,colormap);
    212:   }
    213:   return(0);
    214: }

    218: PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X *XiWin,char *host,Colormap colormap)
    219: {

    223:   if (XiWin->depth < 8) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"PETSc Graphics require monitors with at least 8 bit color (256 colors)");
    224:   if (!gColormap) {
    225:     Display *display;   /* Private display will exist forever contains colormap shared by all windows */
    226:     int     screen;
    227:     Visual  *vis;

    229:     display = XOpenDisplay(host);
    230:     screen  = DefaultScreen(display);
    231:     vis     = DefaultVisual(display,screen);

    233:     PetscDrawSetUpColormap_X(display,screen,vis,colormap);
    234:   }
    235:   XiWin->cmap       = gColormap;
    236:   PetscMemcpy(XiWin->cmapping,gCmapping,256*sizeof(PetscDrawXiPixVal));
    237:   XiWin->background = XiWin->cmapping[PETSC_DRAW_WHITE];
    238:   XiWin->foreground = XiWin->cmapping[PETSC_DRAW_BLACK];
    239:   return(0);
    240: }

    242: /*
    243:     Color in X is many-layered.  The first layer is the "visual",a
    244:     immutable attribute of a window set when the window is
    245:     created.

    247:     The next layer is the colormap.  The installation of colormaps is
    248:     the buisness of the window manager (in some distant later release).
    249: */

    251: /*
    252:     This routine gets the visual class (PseudoColor, etc) and returns
    253:     it.  It finds the default visual.  Possible returns are
    254:         PseudoColor
    255:         StaticColor
    256:         DirectColor
    257:         TrueColor
    258:         GrayScale
    259:         StaticGray
    260:  */
    263: PetscErrorCode PetscDrawXiSetVisualClass(PetscDraw_X *XiWin)
    264: {
    265:   XVisualInfo vinfo;

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

    282: PetscErrorCode PetscDrawXiGetVisualClass(PetscDraw_X *XiWin)
    283: {
    285: #if defined(__cplusplus)
    286:   PetscFunctionReturn(XiWin->vis->c_class);
    287: #else
    288:   PetscFunctionReturn(XiWin->vis->class);
    289: #endif
    290: }

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

    304: PetscErrorCode PetscDrawXiGetBaseColor(PetscDraw_X *XiWin,PetscDrawXiPixVal *white_pix,PetscDrawXiPixVal *black_pix)
    305: {
    307:   *white_pix = XiWin->cmapping[PETSC_DRAW_WHITE];
    308:   *black_pix = XiWin->cmapping[PETSC_DRAW_BLACK];
    309:   return(0);
    310: }

    312: /*
    313:     This routine returns the pixel value for the specified color
    314:     Returns 0 on failure,<>0 otherwise.
    315:  */
    318: PetscErrorCode PetscDrawXiFindColor(PetscDraw_X *XiWin,char *name,PetscDrawXiPixVal *pixval)
    319: {
    320:   XColor colordef;
    321:   int    st;

    324:   st = XParseColor(XiWin->disp,XiWin->cmap,name,&colordef);
    325:   if (st) {
    326:     st = XAllocColor(XiWin->disp,XiWin->cmap,&colordef);
    327:     if (st) *pixval = colordef.pixel;
    328:   }
    329:   PetscFunctionReturn(st);
    330: }

    332: /*
    333:     Another real need is to assign "colors" that make sense for
    334:     a monochrome display,without unduely penalizing color displays.
    335:     This routine takes a color name,a window, and a flag that
    336:     indicates whether this is "background" or "foreground".
    337:     In the monchrome case (or if the color is otherwise unavailable),
    338:     the "background" or "foreground" colors will be chosen
    339:  */
    342: PetscDrawXiPixVal PetscDrawXiGetColor(PetscDraw_X* XiWin,char *name,int is_fore)
    343: {
    344:   PetscDrawXiPixVal pixval;

    347:   if (XiWin->numcolors == 2 || !PetscDrawXiFindColor(XiWin,name,&pixval)) {
    348:     pixval = is_fore ? XiWin->cmapping[PETSC_DRAW_WHITE] : XiWin->cmapping[PETSC_DRAW_BLACK];
    349:   }
    350:   PetscFunctionReturn(pixval);
    351: }