21
Color
The X Window System has various ways of allocating, specifying, and using colors. While
all of these methods are available to applications without XView intervening, XView pro-
vides its own model for color specification that may be used as an alternative. It does not
provide anything more than what is already available, but it may provide a simpler interface
to request and specify colors. This model is especially useful when specifying colors for
XView objects, such as panel buttons and scrollbars.
This chapter does not directly discuss how to use colormaps and related Xlib color-specific
functions. For a discussion of them, see Volume One, Xlib Programming Manual, Chapter 7,
Color. This chapter discusses only the XView color model.
Obviously, the user cannot view colors in an application without having a color display. But
you cannot tell at the time your application is written whether the user’s display is going to
be able to support color. You can use the DisplayDepth() macro to determine whether
the user’s display can handle color:
Display *dpy = (Display *)xv_get(frame, XV_DISPLAY);
extern use_color;
if (DefaultDepth(dpy, DefaultScreen(dpy)) < 2)
use_color = False;
21.1 XView Color Model
XView applications deal with color by using colormap segments. Use the CMS package to
create a colormap segment. Figure 21-1 shows the class hierarchy for the CMS package.
As a simple introduction, the following code fragment creates a colormap segment with the
specified colors and returns a handle to it:
cms = (Cms)xv_create(NULL, CMS,
CMS_SIZE, 4,
CMS_NAMED_COLORS, "white", "red", "green", "blue", NULL,
NULL);
Color
Color 513
Generic
Object
CMS
Figure 21-1. CMS package class hierarchy
Window-based objects (canvases, panels, textsw, etc.) use colormap segments to get their
colors. These objects get a default colormap segment when they are created, but you can as-
sign a new one using the WIN_CMS attribute:
canvas = (Canvas)xv_create(frame, CANVAS,
WIN_CMS, cms,
NULL);
Colormap segments must be applied to windows to assure that the window can access the
color you are attempting to draw into. However, there is much to understand about colors,
colormaps, colormap segments, visuals, servers, and X11 to be able to use colors in an effi-
cient and robust way. Unless done correctly, you may produce code that only works on spe-
cific machines or in specific environments.
21.1.0.1 What is a colormap segment?
A colormap segment (cms), is a subset of the available cells in a colormap on the X server.
These are XView entities (i.e., not Xlib) that provide a veneer over the Xlib color mecha-
nism. Colormap segments can be created as either static or dynamic and are derived from an
underlying colormap of the same type.
Any object subclassed from the window object may allocate and use colormap segments.
You can use Xlib routines to do all your color and colormap manipulation within canvas win-
dows, pixmaps, and other X-related objects, but you must use the colormap segment API for
XView objects.
More than one XView object may reference the same colormap segment. However, a color-
map segment does not keep track of the objects that are using it. The application is required
to keep track of changes in colors and update its objects accordingly.
The internals to XView attempt to create colormap segments that are as small as possible so
that numerous segments can share the same underlying colormap. If a colormap segment
requires more colors than the current colormap has space for, a new colormap must be
created.
514 XView Programming Manual
21.1.1 Colormap Segment Types
You can create static or dynamic colormap segments. The type is set with the CMS_TYPE
attribute. Its value can be either XV_STATIC_CMS or XV_DYNAMIC_CMS. A colormap seg-
ment’s type cannot change, so the CMS_TYPE attribute is for xv_create() only.
The X11 Protocol specifies that the Visual type of a window must be declared at the time it
is created. Therefore, XView objects that allocate colormap segments are required, at cre-
ation time, to specify the type of visual they propose to use. The default visual is determined
by the default visual of the screen.
21.1.1.1 Static colormap segments
Applications must always use static colormap segments unless they require read-write colors.
Colors allocated from a static colormap segment are shared among all applications. In static
colormap segments, when a new color is asked for, the XView library will try to return the
closest (or exact) matching color from the server (using XAllocColor()) if the default
colormap on the server is StaticColor.
Whenever possible, a colormap segment is derived from the default colormap obtained from
the screen in which the window resides (e.g., DefaultColormap()). Only when the
colors on that colormap have been exhausted is a new colormap allocated. If XView needs to
allocate a new colormap for a new cms, it does this internally. It is impossible for the appli-
cation to specify a colormap for a colormap segment.
The cells in a static cms are initialized once and are read-only from then on. Static colormap
segments, by sharing color cells across applications, use the shared hardware colormap
resources more efficiently and reduce flashing. Flashing is a blinking effect you sometimes
get when moving the cursor in and out of various windows on the screen. This is caused by
the server popping different colormaps in and out as you move from one window to the next.
21.1.1.2 Dynamic colormap segments
When you ask for a dynamic cms, XView sends a request to the server to allocate read-write
colors. When colors are requested from this cms, the color returned is the exact color; the
closest match is not returned as it is with static colors.
Color
Color 515
21.2 Creating Colormap Segments
Applications that use color must include the file <xview/cms.h>. A cms can be created using
the standard call to xv_create() with the package name CMS.
Cms cms;
cms = (Cms)xv_create(parent, CMS, attrs, NULL);
The parent of a colormap segment is the XView screen object with which the colormap is
associated. If a parent is not specified, the default screen of the default server is used as the
parent.
21.2.0.1 Cms size
A cms may contain as many colors as you like as long as they fit within the largest colormap
you can create. Having more than one colormap segment reference the same color value is
perfectly legal and reasonable. Data is frequently shared among segments for optimal effi-
ciency.
When creating a colormap segment, you must specify its size (i.e., the number of colors it
has) using the
CMS_SIZE attribute. If you don’t set the size, it defaults to the macro,
XV_DEFAULT_CMS_SIZE, which is 2. CMS_SIZE is a create-only and get-only attribute; once
a colormap is created, its size cannot be changed, although you can query a colormap’s size
using xv_get().
If all the colors in a colormap segment are not initialized, the uninitialized colors are unde-
fined and should not be used. You can change colors within a dynamic cms at any time.
Uninitialized colors of a static cms can be initialized using xv_set(), but once initialized,
they may not be changed.
You might want to create a segment of a larger size than the number of colors you assign it
because you may not have all the colors you know you’ll need right away. For example, you
create a colormap segment of size n, but initialize it with only n-4 colors. When the rest of
the colors are ready to be loaded into the segment, you do so at the location of the uninitial-
ized colors, namely, at index n-4. The CMS_INDEX attribute is used to specify this location.
CAUTION
All the colors in a static cms must be specified at the time of creation to avoid
race conditions in the associated X11 colormap. Because static colormaps are
shared with other applications, if you request n colors but do not initialize all of
them, another application could request and initialize enough colors to fill up the
colormap before you get a chance to set the rest of your colors.
When creating a cms or setting new colors, you may specify CMS_COLOR_COUNT to indicate
the number of colors to load. Again, if you want to load these colors at a position other than
the beginning of the segment, use CMS_INDEX. This is typically used only when you are
creating a colormap segment and not initializing each color right away. Or, if you have
516 XView Programming Manual
already done this, you are adding more colors to a prebuilt colormap segment that hasn’t had
all of its colors initialized. Therefore, this is a create-only and set-only attribute.
21.2.1 Specifying Colors
You can specify actual colors by name or by RGB values. When using RGB values, you can
use XView or Xlib data structures. In each case, we are going to create a colormap segment
with the same four colors: white, red, green, and blue.
21.2.1.1 Specifying colors by name
The attribute
CMS_NAMED_COLORS takes as its value a NULL-terminated list of strings repre-
senting color names:
cms = (Cms)xv_create(parent, CMS,
CMS_SIZE, 4,
CMS_NAMED_COLORS, "white", "red", "green", "blue", NULL,
NULL);
The colors specified by the names are converted into actual values using XParseColor()*
and allocated into the colormap segment using XAllocColor() (for static colormaps) or
XStoreColor() (for dynamic colormaps). The example shown probably works because
the colors used are common colors found on most X servers’ color databases. However, you
should be careful when requesting named colors in this fashion because the database may not
contain the color name you specify. If any of the colors requested fails, then no change to the
cms is affected and xv_set() returns
XV_ERROR. If a cms is being created via xv_cre-
ate() and an error occurs, no cms is created and xv_create() returns NULL.
CMS_NAMED_COLORS cannot be used by xv_get().
21.2.1.2 Specifying colors by RGB values
You can request colors more directly by specifying the actual red, green, and blue (RGB) val-
ues using one of two attributes. CMS_COLORS takes as a value an array of
Xv_singlecolor objects. This XView-defined type is declared as:
typedef struct xv_singlecolor {
unsigned char red, green, blue;
} Xv_singlecolor;
*XParseColor() is an Xlib call that maps char * color names into RGB values.
Color
Color 517
Get Volume 7A: XView Programming Manual now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.