Actual source code: xcolor.c

      1: #define PETSC_DLL

      3: /*
      4:     Code for managing color the X implementation of the PetscDraw routines.

      6:     Currently we default to using cmapping[0 to PETSC_DRAW_BASIC_COLORS-1] for the basic colors and
      7:   cmapping[DRAW_BASIC_COLORS to 255] for a uniform hue of all the colors. But in the contour
      8:   plot we only use from PETSC_DRAW_BASIC_COLORS to 240 since the ones beyond that are too dark.

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

     14: static const char *(colornames[PETSC_DRAW_BASIC_COLORS]) = { "white",
     15:                                                  "black",
     16:                                                  "red",
     17:                                                  "green",
     18:                                                  "cyan",
     19:                                                  "blue",
     20:                                                  "magenta",
     21:                                                  "aquamarine",
     22:                                                  "forestgreen",
     23:                                                  "orange",
     24:                                                  "violet",
     25:                                                  "brown",
     26:                                                  "pink",
     27:                                                  "coral",
     28:                                                  "gray",
     29:                                                  "yellow",
     30:                                                  "gold",
     31:                                                  "lightpink",
     32:                                                  "mediumturquoise",
     33:                                                  "khaki",
     34:                                                  "dimgray",
     35:                                                  "yellowgreen",
     36:                                                  "skyblue",
     37:                                                  "darkgreen",
     38:                                                  "navyblue",
     39:                                                  "sandybrown",
     40:                                                  "cadetblue",
     41:                                                  "powderblue",
     42:                                                  "deeppink",
     43:                                                  "thistle",
     44:                                                  "limegreen",
     45:                                                  "lavenderblush",
     46:                                                  "plum"};

     48: EXTERN PetscErrorCode XiInitCmap(PetscDraw_X*);
     49: EXTERN PetscErrorCode XiGetVisualClass(PetscDraw_X *);

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

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

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

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

     68: */
     69: static Colormap  gColormap  = 0;
     70: static PixVal    gCmapping[256];
     71:        int       gNumcolors = 0;

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

     84:   if (colormap) {
     85:     gColormap = colormap;
     86:   } else {
     87:     gColormap   = DefaultColormap(display,screen);
     88:   }

     90:   /* set the basic colors into the color map */
     91:   for (i=0; i<PETSC_DRAW_BASIC_COLORS; i++) {
     92:     XAllocNamedColor(display,gColormap,colornames[i],&colordef,&ecolordef);
     93:     gCmapping[i] = colordef.pixel;
     94:   }

     96:   /* set the uniform hue colors into the color map */
     97:   ncolors = 256-PETSC_DRAW_BASIC_COLORS;
     98:   PetscMalloc(3*ncolors*sizeof(unsigned char),&red);
     99:   green   = red   + ncolors;
    100:   blue    = green + ncolors;
    101:   PetscDrawUtilitySetCmapHue(red,green,blue,ncolors);
    102:   PetscOptionsHasName(PETSC_NULL,"-draw_fast",&fast);
    103:   if (!fast) {
    104:     for (i=PETSC_DRAW_BASIC_COLORS; i<ncolors+PETSC_DRAW_BASIC_COLORS; i++) {
    105:       colordef.red    = ((int)red[i-PETSC_DRAW_BASIC_COLORS]   * 65535) / 255;
    106:       colordef.green  = ((int)green[i-PETSC_DRAW_BASIC_COLORS] * 65535) / 255;
    107:       colordef.blue   = ((int)blue[i-PETSC_DRAW_BASIC_COLORS]  * 65535) / 255;
    108:       colordef.flags  = DoRed | DoGreen | DoBlue;
    109:       XAllocColor(display,gColormap,&colordef);
    110:       gCmapping[i]   = colordef.pixel;
    111:     }
    112:   }
    113:   PetscFree(red);
    114:   PetscLogInfo((0,"PetscDrawSetUpColormap_Shared:Successfully allocated colors\n"));

    116:   return(0);
    117: }

    119: /*
    120:     Keep a record of which pixel numbers in the cmap have been
    121:   used so far; this is to allow us to try to reuse as much of the current
    122:   colormap as possible.
    123: */
    124: static PetscTruth cmap_pixvalues_used[256];
    125: static int        cmap_base = 0;

    129: PetscErrorCode PetscDrawSetUpColormap_Private(Display *display,int screen,Visual *visual,Colormap colormap)
    130: {
    131:   Colormap      defaultmap = DefaultColormap(display,screen);
    133:   int           found,i,ncolors;
    134:   XColor        colordef;
    135:   unsigned char *red,*green,*blue;
    136:   PetscTruth    fast;

    140:   if (colormap) {
    141:     gColormap = colormap;
    142:   } else {
    143:     gColormap = XCreateColormap(display,RootWindow(display,screen),visual,AllocAll);
    144:   }

    146:   cmap_base = 0;
    147:   PetscMemzero(cmap_pixvalues_used,256*sizeof(PetscTruth));

    149:   /* set the basic colors into the color map */
    150:   for (i=0; i<PETSC_DRAW_BASIC_COLORS; i++) {
    151:     XParseColor(display,gColormap,colornames[i],&colordef);
    152:       /* try to allocate the color in the default-map */
    153:     found = XAllocColor(display,defaultmap,&colordef);
    154:     /* use it, if it it exists and is not already used in the new colormap */
    155:     if (found && colordef.pixel < 256  && !cmap_pixvalues_used[colordef.pixel]) {
    156:       cmap_pixvalues_used[colordef.pixel] = PETSC_TRUE;
    157:     /* otherwise search for the next available slot */
    158:     } else {
    159:       while (cmap_pixvalues_used[cmap_base]) cmap_base++;
    160:       colordef.pixel                   = cmap_base;
    161:       cmap_pixvalues_used[cmap_base++] = PETSC_TRUE;
    162:     }
    163:     XStoreColor(display,gColormap,&colordef);
    164:     gCmapping[i] = colordef.pixel;
    165:   }

    167:   /* set the uniform hue colors into the color map */
    168:   ncolors = 256-PETSC_DRAW_BASIC_COLORS;
    169:   PetscMalloc(3*ncolors*sizeof(unsigned char),&red);
    170:   green   = red   + ncolors;
    171:   blue    = green + ncolors;
    172:   PetscDrawUtilitySetCmapHue(red,green,blue,ncolors);
    173:   PetscOptionsHasName(PETSC_NULL,"-draw_fast",&fast);
    174:   if (!fast) {
    175:     for (i=PETSC_DRAW_BASIC_COLORS; i<ncolors+PETSC_DRAW_BASIC_COLORS; i++) {
    176:       colordef.red    = ((int)red[i-PETSC_DRAW_BASIC_COLORS]   * 65535) / 255;
    177:       colordef.green  = ((int)green[i-PETSC_DRAW_BASIC_COLORS] * 65535) / 255;
    178:       colordef.blue   = ((int)blue[i-PETSC_DRAW_BASIC_COLORS]  * 65535) / 255;
    179:       colordef.flags  = DoRed | DoGreen | DoBlue;
    180:       /* try to allocate the color in the default-map */
    181:       found = XAllocColor(display,defaultmap,&colordef);
    182:       /* use it, if it it exists and is not already used in the new colormap */
    183:       if (found && colordef.pixel < 256  && !cmap_pixvalues_used[colordef.pixel]) {
    184:         cmap_pixvalues_used[colordef.pixel] = PETSC_TRUE;
    185:         /* otherwise search for the next available slot */
    186:       } else {
    187:         while (cmap_pixvalues_used[cmap_base]) cmap_base++;
    188:         colordef.pixel                   = cmap_base;
    189:         cmap_pixvalues_used[cmap_base++] = PETSC_TRUE;
    190:       }
    191:       XStoreColor(display,gColormap,&colordef);
    192:       gCmapping[i]   = colordef.pixel;
    193:     }
    194:   }
    195:   PetscFree(red);
    196:   PetscLogInfo((0,"PetscDrawSetUpColormap_Private:Successfully allocated colors\n"));
    197:   return(0);
    198: }

    202: PetscErrorCode PetscDrawSetUpColormap_X(Display *display,int screen,Visual *visual,Colormap colormap)
    203: {
    205:   PetscTruth  sharedcolormap;
    206:   XVisualInfo vinfo;

    210:   /*
    211:      This is wrong; it needs to take the value from the visual
    212:   */
    213:   gNumcolors = 1 << DefaultDepth(display,screen);

    215:   PetscOptionsHasName(PETSC_NULL,"-draw_x_shared_colormap",&sharedcolormap);
    216:   /*
    217:         Need to determine if window supports allocating a private colormap,
    218:     if not, set flag to 1
    219:   */
    220:   if (XMatchVisualInfo(display,screen,24,StaticColor,&vinfo) ||
    221:       XMatchVisualInfo(display,screen,24,TrueColor,&vinfo)   ||
    222:       XMatchVisualInfo(display,screen,16,StaticColor,&vinfo) ||
    223:       XMatchVisualInfo(display,screen,16,TrueColor,&vinfo)   ||
    224:       XMatchVisualInfo(display,screen,15,StaticColor,&vinfo) ||
    225:       XMatchVisualInfo(display,screen,15,TrueColor,&vinfo)) {
    226:     sharedcolormap = PETSC_TRUE;
    227:   }

    229:   /* generate the X color map object */
    230:   if (sharedcolormap) {
    231:     PetscDrawSetUpColormap_Shared(display,screen,visual,colormap);
    232:   } else {
    233:     PetscDrawSetUpColormap_Private(display,screen,visual,colormap);
    234:   }
    235:
    236:   return(0);
    237: }

    241: PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X* XiWin,char *host,Colormap colormap)
    242: {

    246:   if (XiWin->depth < 8) {
    247:     SETERRQ(PETSC_ERR_SUP_SYS,"PETSc Graphics require monitors with at least 8 bit color (256 colors)");
    248:   }
    249:   if (!gColormap){
    250:     Display  *display;  /* Private display will exist forever contains colormap shared by all windows */
    251:     int      screen;
    252:     Visual*  vis;

    254:     display = XOpenDisplay(host);
    255:     screen  = DefaultScreen(display);
    256:     vis     = DefaultVisual(display,screen);

    258:     PetscDrawSetUpColormap_X(display,screen,vis,colormap);
    259:   }
    260:   XiWin->cmap = gColormap;
    261:   PetscMemcpy(XiWin->cmapping,gCmapping,256*sizeof(PixVal));
    262:   XiWin->background = XiWin->cmapping[PETSC_DRAW_WHITE];
    263:   XiWin->foreground = XiWin->cmapping[PETSC_DRAW_BLACK];
    264:   return(0);
    265: }

    267: /*
    268:     Color in X is many-layered.  The first layer is the "visual",a
    269:     immutable attribute of a window set when the window is
    270:     created.

    272:     The next layer is the colormap.  The installation of colormaps is
    273:     the buisness of the window manager (in some distant later release).
    274: */

    276: /*
    277:     This routine gets the visual class (PseudoColor, etc) and returns
    278:     it.  It finds the default visual.  Possible returns are
    279:         PseudoColor
    280:         StaticColor
    281:         DirectColor
    282:         TrueColor
    283:         GrayScale
    284:         StaticGray
    285:  */
    288: PetscErrorCode XiSetVisualClass(PetscDraw_X* XiWin)
    289: {
    290:   XVisualInfo vinfo;

    293:   if (XMatchVisualInfo(XiWin->disp,XiWin->screen,24,DirectColor,&vinfo)) {
    294:     XiWin->vis    = vinfo.visual;
    295:     return(0);
    296:   }
    297:   if (XMatchVisualInfo(XiWin->disp,XiWin->screen,8,PseudoColor,&vinfo)) {
    298:     XiWin->vis    = vinfo.visual;
    299:     return(0);
    300:   }
    301:   if (XMatchVisualInfo(XiWin->disp,XiWin->screen,
    302:     DefaultDepth(XiWin->disp,XiWin->screen),PseudoColor,&vinfo)) {
    303:     XiWin->vis    = vinfo.visual;
    304:     return(0);
    305:   }
    306:   XiWin->vis    = DefaultVisual(XiWin->disp,XiWin->screen);
    307:   return(0);
    308: }

    312: PetscErrorCode XiGetVisualClass(PetscDraw_X* XiWin)
    313: {
    315: #if defined(__cplusplus)
    316:   PetscFunctionReturn(XiWin->vis->c_class);
    317: #else
    318:   PetscFunctionReturn(XiWin->vis->class);
    319: #endif
    320: }

    325: PetscErrorCode XiSetColormap(PetscDraw_X* XiWin)
    326: {
    328:   XSetWindowColormap(XiWin->disp,XiWin->win,XiWin->cmap);
    329:   return(0);
    330: }

    334: PetscErrorCode XiGetBaseColor(PetscDraw_X* XiWin,PixVal* white_pix,PixVal* black_pix)
    335: {
    337:   *white_pix  = XiWin->cmapping[PETSC_DRAW_WHITE];
    338:   *black_pix  = XiWin->cmapping[PETSC_DRAW_BLACK];
    339:   return(0);
    340: }

    344: /*
    345:     This routine returns the pixel value for the specified color
    346:     Returns 0 on failure,<>0 otherwise.
    347:  */
    350: PetscErrorCode XiFindColor(PetscDraw_X *XiWin,char *name,PixVal *pixval)
    351: {
    352:   XColor   colordef;
    353:   int      st;

    356:   st = XParseColor(XiWin->disp,XiWin->cmap,name,&colordef);
    357:   if (st) {
    358:     st  = XAllocColor(XiWin->disp,XiWin->cmap,&colordef);
    359:     if (st)  *pixval = colordef.pixel;
    360:   }
    361:   PetscFunctionReturn(st);
    362: }

    364: /*
    365:     Another real need is to assign "colors" that make sense for
    366:     a monochrome display,without unduely penalizing color displays.
    367:     This routine takes a color name,a window, and a flag that
    368:     indicates whether this is "background" or "foreground".
    369:     In the monchrome case (or if the color is otherwise unavailable),
    370:     the "background" or "foreground" colors will be chosen
    371:  */
    374: PixVal XiGetColor(PetscDraw_X* XiWin,char *name,int is_fore)
    375: {
    376:   PixVal pixval;

    379:   if (XiWin->numcolors == 2 || !XiFindColor(XiWin,name,&pixval)) {
    380:     pixval  = is_fore ? XiWin->cmapping[PETSC_DRAW_WHITE] : XiWin->cmapping[PETSC_DRAW_BLACK];
    381:   }
    382:   PetscFunctionReturn(pixval);
    383: }

    385: /*
    386:    This routine takes a named color and returns a color that is either
    387:    lighter or darker
    388:  */
    391: PixVal XiSimColor(PetscDraw_X *XiWin,PixVal pixel,int intensity,int is_fore)
    392: {
    393:   XColor   colordef,colorsdef;
    394:   char     RGBcolor[20];
    395:   PixVal   red,green,blue;

    398:   colordef.pixel = pixel;
    399:   XQueryColor(XiWin->disp,XiWin->cmap,&colordef);
    400:   /* Adjust the color value up or down.  Get the RGB values for the color */
    401:   red   = colordef.red;
    402:   green = colordef.green;
    403:   blue  = colordef.blue;
    404: #define WHITE_AMOUNT 5000
    405:   if (intensity > 0) {
    406:     /* Add white to the color */
    407:     red   = PetscMin(65535,red + WHITE_AMOUNT);
    408:     green = PetscMin(65535,green + WHITE_AMOUNT);
    409:     blue  = PetscMin(65535,blue + WHITE_AMOUNT);
    410:   } else {
    411:     /* Subtract white from the color */
    412:     red   = (red   < WHITE_AMOUNT) ? 0 : red - WHITE_AMOUNT;
    413:     green = (green < WHITE_AMOUNT) ? 0 : green - WHITE_AMOUNT;
    414:     blue  = (blue  < WHITE_AMOUNT) ? 0 : blue - WHITE_AMOUNT;
    415:   }
    416:   sprintf(RGBcolor,"rgb:%4.4x/%4.4x/%4.4x",(unsigned int)red,
    417:                      (unsigned int)green,(unsigned int)blue);
    418:   XLookupColor(XiWin->disp,XiWin->cmap,RGBcolor,&colordef,&colorsdef);
    419:   PetscFunctionReturn(colorsdef.pixel);
    420: }

    422: /*
    423:   XiSetCmapLight - Create rgb values from a single color by adding white
    424:
    425:   The initial color is (red[0],green[0],blue[0]).
    426: */
    429: PetscErrorCode XiSetCmapLight(unsigned char *red,unsigned char *green,unsigned char *blue,int mapsize)
    430: {
    431:   int     i ;

    434:   for (i=1; i<mapsize-1; i++) {
    435:       blue[i]  = i*(255-(int)blue[0])/(mapsize-2)+blue[0] ;
    436:       green[i] = i*(255-(int)green[0])/(mapsize-2)+green[0] ;
    437:       red[i]   = i*(255-(int)red[0])/(mapsize-2)+red[0] ;
    438:   }
    439:   red[mapsize-1] = green[mapsize-1] = blue[mapsize-1] = 255;
    440:   return(0);
    441: }