Previous | Contents | Index |
On some systems, a single display can support multiple screens. Each screen can have several different visual types supported at different depths. Xlib provides routines that allow a client to search and choose the appropriate visual type on the system by using the visual info data structure.
The following illustrates the visual info data structure:
typedef struc { Visual *visual; VisualID *visualid; int screen; int depth; int class; unsigned long red_mask; unsigned long green_mask; unsigned long blue_mask; int colormap_size; int bits_per_rgb; }XVisualInfo; |
Table 5-1 describes the members of the visual info data structure.
Member Name | Contents |
---|---|
visual | A pointer to a visual data structure that is returned to the client. |
visualid | The id of the visual that is returned by the server. |
screen | The specified screen of the display. |
depth | The depth in planes of the screen. |
class | The class of the visual (PseudoColor, GrayScale, DirectColor, TrueColor, StaticGray, StaticColor). |
red_mask | Definition of the red mask. 1 |
green_mask | Definition of the green mask. 1 |
blue_mask | Definition of the blue mask. 1 |
colormap_size | Number of available color map entries. |
bits_per_rgb | Number of bits that specifies the number of distinct red, green and blue values. Actual RGB values are unsigned 16-bit numbers. |
Use the GET VISUAL INFO routine to return a list of visual structures that match a specified template.
The GET VISUAL INFO routine has the following format:
XGetVisualInfo(display, vinfo_mask, vinfo_template, num_items_return) |
Example 5-4 illustrates using the GET VISUAL INFO routine.
Use the MATCH VISUAL INFO routine to return the visual information for a visual type that matches the specified depth and class for a screen. Because multiple visual types that match the specified depth and class can exist, the exact visual chosen is undefined.
Note that the MATCH VISUAL INFO routine is a convenience routine that matches one visual of a particular class and depth. The GET VISUAL INFO routine, however, can find any number of visuals that match any combination of characteristics.
Example 5-1 illustrates using the MATCH VISUAL INFO routine to find a pseudocolor visual type on a 24-plane system.
Example 5-1 Matching Visual Information |
---|
. . . (1)#define max_supported_planes 24 (2)XVisualInfo vInfo; . . . screen = XDefaultScreenOfDisplay(dpy); scrNum = XDefaultScreen(dpy); . . . /***** Match the visual *****/ static void doMatchVisual( ) { for (i = 4; (i <= max_supported_planes && !status); i++) (3) status = XMatchVisualInfo(dpy, scrNum, i, PseudoColor, &vInfo); if (!status){ printf ("Could not find a Pseudocolor visual on this system"); exit(1); } } /***** Create the color *****/ static void doCreateColor( ) { (4) if (vInfo.visual != DefaultVisual(dpy,scrNum)) map = XCreateColormap(dpy,RootWindow(dpy,scrNum),vInfo.visual, AllocNone); else map = XDefaultColormapOfScreen(screen); . . . |
XMatchVisualInfo(display, screen_number, depth, class, vinfo_return) |
Xlib provides the following ways to share color resources:
The choice of using a named color or specifying an exact color depends on the needs of the client. For instance, if the client is producing a bar graph, specifying the named VMS DECwindows color "Red" as a color value may be sufficient, regardless of the hue that VMS DECwindows names "Red". However, if the client is reproducing a portrait, specifying an exact red color value might be necessary to produce accurate skin tones. For a list of named colors, see the SYS$MANAGER:DECW$RGB.COM file.
Note that because of differences in hardware, no two monitors display
colors exactly the same, even though the same named colors are
specified.
5.3.1 Using Named Colors
VMS DECwindows includes named colors that clients can share. To use a named color, call the ALLOC NAMED COLOR routine. ALLOC NAMED COLOR determines whether the color map defines a value for the specified color. If the color exists, the server returns the index to the color map. If the color does not exist, the server returns an error.
Example 5-2 illustrates specifying a color using ALLOC NAMED COLOR.
Example 5-2 Using Named VMS DECwindows Colors |
---|
static int doDefineColor(n) { int pixel; (1) XColor exact_color,screen_color; (2) char *colors[ ] = { "dark slate blue", "light grey", "firebrick" }; if ((XDefaultVisualOfScreen(screen))->class == TrueColor || (XDefaultVisualOfScreen(screen))->class == PseudoColor || (XDefaultVisualOfScreen(screen))->class == DirectColor || (XDefaultVisualOfScreen(screen))->class == StaticColor) { (3) if (XAllocNamedColor(dpy, DefaultColormapOfScreen(screen), colors[n-1], &screen_color, &exact_color)) return screen_color.pixel; else printf("Color not allocated!"); } else printf("Not a color device!"); . . . |
XAllocNamedColor(display, colormap_id, color_name, screen_def_return, exact_def_return) |
The client passes the names of VMS DECwindows colors by referring
to the array colors.
To specify exact color values, use the following method:
Xlib provides a color data structure enabling clients to specify exact color values when sharing colors. (Routines that allocate colors for exclusive use and that query available colors also use the color data structure. For information about using the color data structure for these purposes, see Section 5.4.)
The following illustrates the color data structure:
typedef struct { unsigned long pixel; unsigned short red, green, blue; char flags; char pad; } XColor; |
Table 5-2 describes the members of the color data structure.
Member Name | Contents | ||||||
---|---|---|---|---|---|---|---|
pixel | Pixel value | ||||||
red | Specifies the red value of the pixel 1 | ||||||
green | Specifies the green value of the pixel 1 | ||||||
blue | Specifies the blue value of the pixel 1 | ||||||
flags |
Defines which color components are to be changed in the color map.
Possible flags are as follows:
|
||||||
pad | Makes the data structure an even length |
Example 5-3 illustrates how to specify exact color definitions.
Example 5-3 Specifying Exact Color Values |
---|
/***** Create color *****/ static int doDefineColor(n) { int pixel; XColor colors[3]; if ((XDefaultVisualOfScreen(screen))->class == TrueColor || (XDefaultVisualOfScreen(screen))->class == PseudoColor || (XDefaultVisualOfScreen(screen))->class == DirectColor || (XDefaultVisualOfScreen(screen))->class == StaticColor) switch (n){ case 1:{ (1) colors[n - 1].red = 59904; colors[n - 1].green = 44288; colors[n - 1].blue = 59904; (2) if (XAllocColor(dpy, XDefaultColormapOfScreen(screen), &colors[n - 1])) return colors[n - 1].pixel; else printf("Color not allocated!"); return; } case 2:{ colors[n - 1].red = 65280; colors[n - 1].green = 0; colors[n - 1].blue = 32512; if (XAllocColor(dpy, XDefaultColormapOfScreen(screen), &colors[n - 1])) return colors[n - 1].pixel; else printf("Color not allocated!"); return; } case 3:{ colors[n - 1].red = 37632; colors[n - 1].green = 56064; colors[n - 1].blue = 28672; if (XAllocColor(dpy, XDefaultColormapOfScreen(screen), &colors[n - 1])) return colors[n - 1].pixel; else printf("Color not allocated!"); return; } } else switch (n) { case 1: return XBlackPixelOfScreen(screen); break; case 2: return XWhitePixelOfScreen(screen); break; case 3: return XBlackPixelOfScreen(screen); break; } } |
If a client does not need to change color values, it should share colors by using the methods described in Section 5.3. Sharing colors saves resources. However, a client that changes color values must allocate them for its exclusive use.
Xlib provides two methods for allocating colors for a client's exclusive use. First, the client can allocate cells and store color values in the default color map. Second, if the default color map does not contain enough storage, or if the default color map is read-only (such as true color), the client can create its own color map using a writable visual type and store color values in it. In addition, when creating a color map, the client can allocate all entries in the color map for its exclusive use. Refer to the CREATE COLORMAP routine in Section 5.4.1 for more information about allocating all entries in a color map.
This section describes how to specify a color map, how to allocate
cells for exclusive use, and how to store values in the color cells.
5.4.1 Specifying a Color Map
Clients can either use the default color map and allocate its color cells for exclusive use or create their own color maps.
If possible, use the default color map. Although a client can create color maps for its own use, the hardware color map storage is limited. When a client creates its own color map, the map must be installed into the hardware color map before the client map can be used. If the client color map is not installed, the client may use a different color map and possibly display the wrong color. Using the default color map eliminates this problem. See Section 5.1 for information about how Xlib handles color maps.
To specify the default color map, use the DEFAULT COLORMAP routine. DEFAULT COLORMAP returns the identifier of the default color map.
If the default color map does not contain enough resources, the client can create its own color map.
To create a color map, use the following method:
The CREATE COLORMAP routine creates a color map for the specified window and visual type. Note that CREATE COLORMAP can only be used with pseudocolor, gray scale, and direct color visual types.
The CREATE COLORMAP routine has the following format:
XCreateColormap(display, window_id, visual_struc, alloc) |
The alloc argument specifies whether the client creating the color map allocates all of the color map entries for its exclusive use or creates a color map with no defined color map entries. To allocate all entries for exclusive use, specify the constant AllocAll. To allocate no defined map entries, specify the constant AllocNone. The latter is useful when two or more clients are to share the newly created color map.
See Section 5.4.2 for information about allocating colors. See
Example 5-4 for an example of creating a color map.
5.4.2 Allocating Color Cells
After specifying a color map, allocate color cells in it.
Use the ALLOC COLOR CELLS routine or ALLOC COLOR PLANES to allocate color resources. Either routine can be used; however, ALLOC COLOR CELLS allocates colors according to the pseudocolor model. The ALLOC COLOR PLANES routine allocates color resources according to a direct color model. See Section 5.2 for information about these color models.
Example 5-4 illustrates how to allocate colors for exclusive use. The program creates a color wheel that rotates when the user presses MB1.
Example 5-4 Allocating Colors for Exclusive Use |
---|
#include <decw$include/Xlib.h> #include <decw$include/Xutil.h> #include <stdio.h> #include math; #define winW 600 #define winH 600 #define backW 800 #define backH 800 Display *dpy; Window win; Pixmap pixmap; Colormap map; GC gc; Screen *screen; int scrNum; XColor *colors; int offsetX, offsetY; int fullcount; int ButtonIsDown = 0; int n, exposeflag = 0; int ihop=1; int whiteValue; XSetWindowAttributes xswa; XVisualInfo *pVisualInfo; static void doInitialize( ); static void doGetVisual(); static void doCreateWindows( ); static void doCreateGraphicsContext( ); static void doCreatePixmap( ); static void doCreateColor( ); static void doCreateWheel( ); static void doMapWindows( ); static void doHandleEvents( ); static void doExpose( ); static void doButtonPress( ); static void doButtonRelease( ); static void doChangeColors( ); static void doLoadColormap( ); static void doHLS_to_RGB( ); static void doConfigure( ); /***** The main program *****/ static int main() { doInitialize( ); doHandleEvents( ); } /***** doInitialize *****/ static void doInitialize( ) { dpy = XOpenDisplay(0); screen = DefaultScreenOfDisplay(dpy); /* This is the screen structure */ scrNum = DefaultScreen(dpy); /* This is the screen index number*/ doGetVisual(); doCreateColor( ); doCreateWindows( ); doCreateGraphicsContext( ); doCreatePixmap( ); doCreateWheel( ); doMapWindows( ); } /***** doGetVisual *****/ static void doGetVisual( ) { (1) XVisualInfo vInfoTemplate; int usableClasses[3] = {PseudoColor,DirectColor,GrayScale},i,nVis; vInfoTemplate.screen = scrNum; for (i = 0; i < 3; i++) { vInfoTemplate.class = usableClasses[i]; (2) pVisualInfo = XGetVisualInfo(dpy,VisualClassMask|VisualScreenMask, &vInfoTemplate,&nVis); if (pVisualInfo) break; } if (!pVisualInfo) { fprintf(stderr,"Unable to find a dynamic visual class"); exit(1); } } /***** Create the windows *****/ static void doCreateWindows( ) { int winX = 100; int winY = 100; /* Create the win window */ xswa.event_mask = ExposureMask | ButtonPressMask | ButtonReleaseMask | StructureNotifyMask; xswa.background_pixel = whiteValue; xswa.border_pixel = whiteValue; /* Note: you must set this for a non- default depth and class! */ win = XCreateWindow(dpy, RootWindowOfScreen(screen), winX, winY, winW, winH, 0, pVisualInfo->depth, InputOutput,pVisualInfo->visual, CWBorderPixel |CWEventMask | CWBackPixel | CWColormap, &xswa); /* Create the name of the window */ XStoreName(dpy, win, "Color Wheel: Press MB1 to Rotate or MB2 to Exit."); } /***** Create the graphics context *****/ static void doCreateGraphicsContext( ) { gc = XCreateGC(dpy, win, 0, 0); } /***** Create the pixmap *****/ static void doCreatePixmap( ) { (3) pixmap = XCreatePixmap(dpy, XRootWindow(dpy, XDefaultScreen(dpy)), backW, backH, pVisualInfo->depth); XSetForeground(dpy,gc,whiteValue); XFillRectangle(dpy, pixmap, gc, 0, 0, backW, backH); } /***** Create the color ******/ (4)static void doCreateColor( ) { int *pixels; int contig; int *plane_masks; if (pVisualInfo->visual != DefaultVisual(dpy,scrNum)) (5) map=XCreateColormap(dpy,RootWindow(dpy,scrNum),pVisualInfo->visual, AllocNone); else map = XDefaultColormapOfScreen(screen); xswa.colormap = map; fullcount = XDisplayCells(dpy, scrNum)/2; if (fullcount > 128) fullcount = 128; pixels = malloc(sizeof(int)*fullcount); colors = malloc(sizeof(XColor)*fullcount); /* Get a value for white (Use colors[0] temporarily) */ colors[0].red = colors[0].blue = colors[0].green = 0xffff; XAllocColor(dpy,map,&colors[0]); whiteValue = colors[0].pixel; /* Now get writable pixels for the color wheel */ if (!XAllocColorCells(dpy, map, contig, plane_masks, 0, pixels, fullcount)) { sys$exit(1); } doLoadColormap(pixels); } /***** Create the wheel *****/ (6)static void doCreateWheel( ) { int pixel, i, j; XPoint *pgon; int xcent, ycent; /* Now set up wheel. It is really a set of triangles*/ pgon = malloc(sizeof(XPoint)*3*fullcount+1); xcent=backW/2; ycent=backH/2; (7) pgon[0].x = backW; pgon[0].y = backH/2; /* Fill in coordinate for center point in all triangles */ for (i=0;i<fullcount*3;i+=3) { pgon[i+1].x = xcent; pgon[i+1].y = ycent; } /* Calculate the triangle points on the outer circle */ for (pixel=0,i=0;pixel<fullcount;i+=3, pixel++) { double x,y,xcent_f,ycent_f; xcent_f = (double)xcent; ycent_f = (double)ycent; x=cos( (((double)pixel+1.)/(double)fullcount)*2.*3.14159); y=sin( (((double)pixel+1.)/(double)fullcount)*2.*3.14159); pgon[i+2].x = (int)(x*xcent_f)+xcent; pgon[i+2].y = (int)(y*ycent_f)+ycent; pgon[i+3].x = pgon[i+2].x; pgon[i+3].y = pgon[i+2].y; XSetForeground(dpy, gc, colors[i/3].pixel); XFillPolygon(dpy, pixmap, gc, &pgon[i], 3, Convex, CoordModeOrigin); } offsetX = (backW - winW)/2; offsetY = (backH - winH)/2; return; } /***** Map the windows *****/ static void doMapWindows( ) { XMapWindow(dpy, win); } /***** Handle the events *****/ static void doHandleEvents( ) { XEvent event; for ( ; ; ) { XNextEvent(dpy, &event); switch (event.type) { case Expose: doExpose(&event); break; case ButtonPress: doButtonPress(&event); break; case ButtonRelease: doButtonRelease(&event); break; case ConfigureNotify: doConfigure(&event); break; } } } /***** Handle window exposures *****/ static void doExpose(eventP) XEvent *eventP; { (8) XCopyArea(dpy, pixmap, win, gc, offsetX + eventP->xexpose.x, offsetY + eventP->xexpose.y, eventP->xexpose.width, eventP->xexpose.height, eventP->xexpose.x, eventP->xexpose.y); } /***** Button Press ******/ static void doButtonPress(eventP) XEvent *eventP; { if (eventP ->xbutton.button == Button2) { sys$exit (1); } ButtonIsDown = 1; if (ButtonIsDown) doChangeColors( ); return; } /***** Button Release *****/ static void doButtonRelease(eventP) /* Quit rotate when MB1 released */ XEvent *eventP; { ButtonIsDown = 0; return; } /***** Configure notify *****/ static void doConfigure(eventP) XEvent *eventP; { (9) offsetX = (backW - eventP->xconfigure.width)/2; offsetY = (backH - eventP->xconfigure.height)/2; } /***** Change the colors *****/ (10)static void doChangeColors( ) { for (;!(XPending(dpy));){ unsigned int i,temp; double h,r,g,b; temp = colors[0].pixel; for (i=0;i<fullcount-1;i++) colors[i].pixel = colors[i+1].pixel; colors[fullcount-1].pixel = temp; XStoreColors(dpy, map, colors, fullcount); } } /***** Load the colormap *****/ (11)static void doLoadColormap(pPixels) int *pPixels; { unsigned int i,j; double h,r,g,b; for (i=0;i < fullcount;i++) { colors[i].pixel=pPixels[i]; colors[i].flags = DoRed | DoGreen |DoBlue; } for (i=0; i < fullcount ; i++) { (12) h = (double)i*360/((double)fullcount+1); doHLS_to_RGB(&h,&.5,&.5,&r,&g,&b); colors[i].red = r * 65535.0; colors[i].green = g * 65535.0; colors[i].blue = b * 65535.0; } XStoreColors(dpy, map, colors, fullcount); } /***** Convert to RGB *****/ static void doHLS_to_RGB (h,l,s, r,g,b) double *h,*l,*s,*r,*g,*b; { double m1,m2; double value(); m2 = (*l < 0.5) ? (*l)*(1+*s) : *l + *s- (*l)*(*s) ; m1 = 2*(*l) - m2; if ( *s == 0 ) { (*r)=(*g)=(*b)=(*l); } /*Gray shade*/ else { *r=value(m1,m2,(double)(*h+120.)); *g=value(m1,m2,(double)(*h+000.)); *b=value(m1,m2,(double)(*h-120.)); } return; } double value (n1,n2,hue) double n1,n2,hue; { double val; if (hue>360.) hue -= 360.; if (hue<0. ) hue += 360.; if (hue<60) val = n1+(n2-n1)*hue/60.; else if (hue<180.) val = n2; else if (hue<240.) val = n1+(n2-n1)*(240.-hue)/60.; else val = n1; return (val); } |
Previous | Next | Contents | Index |