next up previous contents
Next: Glossary Up: Miscellaneous Routines Previous: More On Fonts

More On Color

As well as grabbing the keyboard and mouse you can also hog resources. This behaviour is most graphically displayed when clients create colormaps of their own. When the pointer goes into their window, their colormap gets swopped in and the windows of other clients suddenly have their colormap taken from under their feet, resulting in false colors. If you do have to make your own colormap and manipulate it, use

Colormap XCreateColormap(display,w,visual,alloc)           
   Visual *visual; /* GrayScale, Pseudocolor etc */         
   int alloc;      /* AllocAll or AllocNone. 
                      If visual is StaticGray or TrueColor then pick
                      AllocNone, meaning none of colormap cells are writeable*/

Colormap XCopyColormapAndFree(display,cmap)
                   /* This moves all of the client's existing allocations to
                      a new colormap and frees the old ones. This is useful
                      when the old colormap gets filled up*/

XFreeColormap(display,cmap)

XSetWindowColormap(display,w,cmap)

  figure629
Figure 3: Colors and bit planes

Read/Write Color Cells - Using read/write colour cells is more involved than the read-only cells in the earlier chapter. Allocating colorcells and Storing colors in them involve separate commands. N colors and planes can be allocated simultaneously. The idea is that

Status XAllocColorCells(display,cmap,contig,plane_masks,nplanes,pixels,ncolors);
   Bool contig;   /* True if planes must be contiguous, else False */
   unsigned long  plane_masks[nplanes];     /*RETURN*/
   unsigned int   nplanes;         /*supplies number of planes ( >=0 )*/
   unsigned long  pixels[ncolors];          /*RETURN*/
   unsigned int   ncolors;        /*supplies number of colors ( >0 ) */
allocates a number of pixel values to an client program. If nplanes is zero then the pixel array returned will contain the pixel values. Otherwise you will need to OR each element in the masks array with each element in the pixels array to get all the pixel values. No mask will have any bits in common with other masks or pixel values. If you ask for 3 pixel values and 3 bits in the plane mask, your bit plane mask would be 7 containing the bits 1, 2 and 4 and you would be allocated the pixel values 8, 16 and 24. Thus from the pixel value 8 the values from 8 to 15 can be derived by ORing in one or more of these bits. Similarly 16 gives (16 - 23) and 24 gives (24 - 31). Thus we have in fact been allocated all the pixel values from 8 to 31 inclusive.

By ORing together masks and pixels, tex2html_wrap_inline1028 distinct pixels can be produced, all of which are writeable.

For GrayScale or PseudoColor each mask will have exactly 1 bit; for DirectColor each mask will have 3 bits. The cells you allocate have no defined colors until set with XLookupColor then XStoreColor(s) or XStoreNamedColor.

If no pixels are asked for then as many bit planes as possible are allocated. Such a request can succeed only once. See the example program at the end of this section for further clarification of read/write colour cells.

If you want to vary the number of bits that correspond to each primary color, use

Status XAllocColorPlanes(display,cmap,contig,pixels,ncolors,
                           nreds,ngreens,nblues,rmask,gmask,bmask)
   Bool contig;   /* True if planes must be contiguous, else False */
   unsigned long  pixels[nplanes];     /*RETURN*/
   int   ncolors; /* specifies number of colors needed ( >0 ) */
   int nreds, ngreens, nblues; /* specifies the number of shades you want */
   unsigned long  *rmask, *gmask, *bmask; /*RETURN bit masks for planes*/
No mask will have any bits in common with other masks. By ORing together masks and pixels, tex2html_wrap_inline1030 distinct pixels can be produced, but in the colormap there are only tex2html_wrap_inline1032 red entries, tex2html_wrap_inline1034 green entries and tex2html_wrap_inline1036 blues entries. To set colors, use
XStoreColor(display,cmap,screen_def)
   XColor *screen_def;
XStoreColors(display,cmap,defs,ncolors)
   XColor defs[ncolors];

XStoreNamedColor(display,cmap,color,pixel,flags);
   char *color;
   int flags; /* DoRed, DoGreen,DoBlue */
To free color cells or planes use
XFreeColors(display,cmap,pixels,npixels,planes);
unsigned long pixels[npixels]; /* pixels you want to free */
unsigned long planes;          /* planes you want to free */
This is an example of using read/write colour cells. It is rather long winded in order to illustrate the way in which the pixel values are allocated. It eventually ends up with 24 different colours which it draws in a technicolor stripe across the screen and prints some detail of the pixels is has been given as it goes along.  

#include  <X11/cursorfont.h> 
#include <stdio.h> 
#include <X11/X.h>
#include <X11/Xlib.h> 
#include <X11/Xutil.h> 
#define TRUE 1 
#define FALSE 0 
#define PLANELIM  65536 
#define NUMPLANES     3             /* number of bit planes asked for */ 
#define NUMCOLS    3                /* number of colours asked for    */ 
#define PLNUM     (1 << NUMPLANES)  /* pixel value factor from planes */ 
#define PIXNUM    NUMCOLS * PLNUM   /* total pixel values obtained    */ 
 main (argc, argv) 
 char   *argv[]; 
 int     argc; 
 { 
     XColor   color_cell[PIXNUM];    /* must have room for pixnum */ 
     XSetWindowAttributes attributes; 
     int     Red = 60000; 
     int     Green = 40000; 
     int     Blue = 20000; 
     int     i,j; 
     int     mask; 
     Visual *visual; 
     int depth; 
     int which_color,which_cell,which_plane; 
     Display *display; 
     Visual *v; 
     Window  win; 
     GC gc; 
     Colormap cmap; 
     XEvent event; 
     int     stat; 
     long     plane_masks[NUMPLANES]; 
     long     pixar[NUMCOLS]; 
     char str0[50],str1[50],str2[50],str3[50], str4[50];
     int ret;

     setbuf (stdout, NULL); 
     setbuf (stderr, NULL); 

     display = XOpenDisplay(NULL); 
     visual = DefaultVisual(display,0); 
     depth  = DefaultDepth(display,0); 
     attributes.background_pixel      = XWhitePixel(display,0); 
     attributes.border_pixel          = XBlackPixel(display,0); 
     attributes.override_redirect     = 0; 
  
     win = XCreateWindow(display,XRootWindow(display,0),0,0,507,426,5, 
        depth,  InputOutput,visual ,CWBackPixel+CWBorderPixel+CWOverrideRedirect,
        &attributes); 
  
     XSelectInput(display,win,ExposureMask + ButtonPressMask+ KeyPressMask) ; 
  
  
     gc=XCreateGC(display,win,NULL,NULL); 
  
     XMapWindow(display,win); 
     cmap= XDefaultColormap(display,0); 
     stat = XAllocColorCells(display,cmap,FALSE,plane_masks, NUMPLANES,
            pixar, NUMCOLS); /* claim some colorcells */ 
     
     do{ 
       XNextEvent(display,&event); 
       switch(event.type){

       case Expose: 
              sprintf(str0,"depth is = %d", depth);
              sprintf(str1,"there are %d colorcells", DisplayCells(display,0));
              switch(XDoesBackingStore(display)){
                case WhenMapped : sprintf(str2,"when mapped");
                                break;
                case NotUseful :  sprintf(str2,"not useful");
                                break;
                case Always :     sprintf(str2,"always");
                                break;
                default :         sprintf (str2,"error in DoesBackingStore");
              }
              XDrawImageString(display,win,gc,20,15,str0,strlen(str0)); 
              XDrawImageString(display,win,gc,20,30,str1,strlen(str1)); 
              XDrawImageString(display,win,gc,20,45,str2,strlen(str2)); 

              sprintf(str2,"planes = %d, %d, %d", plane_masks[0],
                          plane_masks[1],plane_masks[2]); 
              sprintf(str3,"pixels = %d, %d, %d.", 
                          pixar[0], pixar[1], pixar[2]); 

              XDrawImageString(display,win,gc,20,60,str2,strlen(str2)); 
              XDrawImageString(display,win,gc,20,75,str3,strlen(str3)); 
              v=DefaultVisual(display,0); 
              switch(v->class){ 
 	        case StaticGray:sprintf(str0,"static gray"); break; 
 	        case GrayScale:sprintf(str0," gray scale"); break; 
                case StaticColor:sprintf(str0,"static color"); break; 
                case PseudoColor:sprintf(str0,"pseudocolor"); break; 
                case TrueColor:sprintf(str0,"true color"); break; 
                case DirectColor:sprintf(str0,"direct color"); break; 
              } 
              XDrawImageString(display,win,gc,250,20,str0,strlen(str0)); 
              XDrawImageString(display,win,gc,400,30,"pix vals used",13); 

  
              for(which_color = 0, which_cell = 0; which_color < NUMCOLS; 
                  which_color++){ 
                 color_cell[ which_cell++].pixel = pixar[which_color]; 
                 for(which_plane = 0; which_plane < PLNUM; which_plane++){
                         /* permute the bits to generate all the */ 
 	            mask = 0;      /* possible pixel values */ 
                    for(i = 1, j = 0; i < PLNUM; i <<= 1, j++) 
           	       if(i & which_plane) 
 		          mask |= plane_masks[j]; 
 	            color_cell[ which_cell++].pixel = pixar[which_color] |  mask; 
                    sprintf(str1," %d",(pixar[which_color]  | mask)); 
                    XDrawImageString(display,win,gc,430,30+12*which_cell,
                       str1,strlen(str1)); 
                 } 
              } 
              for(i = 0; i < PIXNUM; i++){
                 /* generate some arbitrary colours */ 
                 color_cell[i].flags= DoRed | DoGreen | DoBlue; 
                 color_cell[i].red = Red; 
                 color_cell[i].green = Green; 
                 color_cell[i].blue = Blue; 
                 Red = ((Red + 3000) % 65536); 
                 Green = ((Green + 3000) % 65536); 
                 Blue = ((Blue + 3000) % 65536); 
              } 
              XStoreColors(display,cmap, color_cell,PIXNUM); 

              for(i = 0; i < PIXNUM; i++){   
                 /* draw a multi-coloured stripe    */ 
                 XSetForeground(display,gc, color_cell[i].pixel); 
                 XFillRectangle(display,win,gc,10 * i, 100, 10, 200); 
              } 
              XFlush(display); 

              printf("now press button: \n"); 
              break;

       case ButtonPress:
              printf("closing display\n"); 
              XCloseDisplay(display); 
              exit(0); 
       }
   }while(1); 
}

XAllocColorCells allows you to do quick overlays. By drawing into one plane, you can change the displayed output without affecting the other planes and restore the original quickly.


next up previous contents
Next: Glossary Up: Miscellaneous Routines Previous: More On Fonts

Tim Love
Mon Mar 11 17:03:18 GMT 1996