Unfortunately, not all hardware is created equal. The most
primitive X servers support only two colors; each pixel is
either on or off. This is referred to as a "one bit per
pixel (bpp)" display. A display with one bit per pixel is
said to have a depth of one. More
advanced X servers support 24 or 32 bits per pixel, and
allow you to specify a different depth on a
window-by-window basis. 24 bits per pixel allows 2^24
different pixels, which includes more colors than the human
eye can differentiate.
Conceptually, a bitmap display consists of a rectangular
grid of pixels. Each pixel consists of some fixed number of
bits; pixels are mapped to visible colors in a
hardware-dependent way. One way to think about this is to
imagine a two-dimensional array of integers, where the
integer size is chosen to hold the required number of bits.
Alternatively, you can think of a display like this as a
stack of bit planes, or
two-dimensional arrays of bits. If all the planes are
parallel to one another, a pixel is a perpendicular line
passing through the same coordinates on each plane, taking
a single bit from each one. This is the origin of the term
depth, since the number of bits
per pixel is equal to the depth of the stack of bit planes.
In the X Window System, pixels represent entries in a color
lookup table. A color is a red,
green, blue (RGB) value---monitors mix red, green, and blue
light in some ratio to display each pixel. Take an eight
bit display, for example: eight bits are not enough to
encode a color in-place; only a few arbitrary RGB values
would be possible. Instead, the bits are interpreted as an
integer and used to index an array of RGB color values.
This table of colors is called the
colormap; it can sometimes be modified to contain the
colors you plan to use, though this is
hardware-dependent---some colormaps are read-only.
A visual is required to determine
how a pixel's bit pattern is converted into a visible
color. Thus, a visual also defines how colormaps work. On
an 8-bit display, the X server might interpret each pixel
as an index into a single colormap containing the 256
possible colors. 24-bit visuals typically have three
colormaps: one for shades of red, one for shades of green,
and one for shades of blue. Each colormap is indexed with
an eight-bit value; the three eight-bit values are packed
into a 24-bit pixel. The visual defines the meaning of the
pixel contents. Visuals also define whether the colormap is
read-only or modifiable.
In short, a visual is a description of the color
capabilities of a particular X server. In Xlib, you have to
do a lot of fooling around with visuals; GDK and GTK+
shield you from most of the mess.
Xlib can report a list of all available visuals and
information about each; GDK keeps a client-side copy of
this information in a struct called GdkVisual. GDK can report the
available visuals, and rank them in different ways. Most
of the time you will only use
gdk_visual_get_system(), which returns a pointer to
the default visual (Figure 2). (If
you're writing a GtkWidget,
gtk_widget_get_visual() returns
the visual you should use; more on this in the chapter called Writing a GtkWidget.) The returned
visual is not a copy, so there is no need to free it; GDK
keeps visuals around permanently.
For reference, here are the contents of GdkVisual; most of the members are
used to calculate pixel values from colors. Since this is
fairly involved and rarely used, this book glosses over
the topic. The depth
member is convenient sometimes. the section called
Types of Visual has more to say about the
type member.
typedef struct _GdkVisual GdkVisual;
struct _GdkVisual
{
GdkVisualType type;
gint depth;
GdkByteOrder byte_order;
gint colormap_size;
gint bits_per_rgb;
guint32 red_mask;
gint red_shift;
gint red_prec;
guint32 green_mask;
gint green_shift;
gint green_prec;
guint32 blue_mask;
gint blue_shift;
gint blue_prec;
};
|