 |
VMS DECwindows Guide to Xlib (Release 4)
Programming: MIT C Binding
5.2.3 Determining Multiple Visual Types
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.
Table 5-1 Visual Info Data Structure Members
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.
|
1The red mask, green mask, and blue mask are defined only
for the direct color and true color visual types.
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);
.
.
.
|
- The client defines the maximum number of
planes, or depth, supported on the system.
- Storage is assigned for the visual info data
structure.
- The MATCH VISUAL INFO routine searches for a
pseudocolor visual type beginning at the fourth plane. If a match is
found, MATCH VISUAL INFO returns the visual information to the visual
info data structure. If a match is not found, the next depth is checked
for a pseudocolor visual.
The MATCH VISUAL INFO routine has the
following format:
XMatchVisualInfo(display, screen_number, depth, class,
vinfo_return)
|
- The client compares the visual member of the
visual info data structure returned by the MATCH VISUAL INFO routine
with the default visual. If the default visual is a pseudocolor type,
then the client uses the default color map. If the visual is not the
default visual, the client creates a color map.
Refer to
Section 5.4.1 for more information about creating color maps.
5.3 Sharing Color Resources
Xlib provides the following ways to share color resources:
- Using named VMS DECwindows colors
- Specifying exact color values
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!");
.
.
.
|
- The client allocates storage for two color
data structures: exact_color defines the RGB values specified
by the VMS DECwindows named color. Screen_color defines the
closest RGB values supported by the hardware.
For an illustration
of the color data structure, see Section 5.3.2.
- An array of characters stores the names of
the predefined VMS DECwindows colors that the client uses.
- The ALLOC NAMED COLOR routine has the
following format:
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.
5.3.2 Specifying Exact Color Values
To specify exact color values, use the following method:
- Assign values to a color data structure.
- Call the ALLOC COLOR routine, specifying the color map from which
the client allocates the definition. ALLOC COLOR returns a pixel value
and changes the RGB
values to indicate the closest color supported by the hardware.
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.
Table 5-2 Color Data Structure Members
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:
DoRed
|
Sets red values
|
DoGreen
|
Sets green values
|
DoBlue
|
Sets blue values
|
|
pad
|
Makes the data structure an even length
|
1Color values are scaled between 0 and 65535. "On
full" in a color is a value of 65535, independent of the number of
planes of the display. Half brightness in a color is a value of 32767;
off is a value of 0. This representation gives uniform results for
color values across displays with different color resolution.
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;
}
}
|
- Define color values in the first of three
color data structures.
- After defining RGB values, call the ALLOC
COLOR routine. ALLOC COLOR allocates shared color cells on the default
color map and returns a pixel value for the color that matches the
specified color most closely.
5.4 Allocating Colors for Exclusive Use
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:
- Using one of the methods described in Section 5.2, determine the
visual type of a specified screen.
- Call the CREATE COLORMAP routine.
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);
}
|
|