SWT Color Model

SummaryThe combination of platforms, display devices and color depth makes
providing an easy to use yet powerful and portable color model an interesting
challenge. In this article we will examine the color management models
of Windows® and X/Motif and then dig into the makings of the SWT color model
and its implications for client code.

By James Moody & Carolyn MacLeod OTIApril 24, 2001

Background

Before diving into the SWT color model, let’s examine
the color management support provided by some of the target platforms.

Windows

Color management on Windows depends on the depth
of the display, which can be either low-color (usually 8 bits per pixel
or less) or high-color (typically 15 bits per pixel or higher).
On low-color displays, the concept of a Palette is important. A
palette is simply a logical grouping of colors. When a color is requested,
the system can either put the color in the palette, or, if the palette
is full, do a closest match of the colors in the palette to find a reasonable
facsimile.

Windows allows the user to define and use one palette per graphics
context (GC), or to use the default system palette that is on the display.
The advantage of defining your own palette is space: it is initialized
as empty, and you have the entire capacity to fill with your own colors.
On the other hand, the system palette undoubtedly already has many colors
in it, especially if other applications are using it; the user may not
be able to use the entire capacity for his or her own application. Using
the system palette has its advantages, however. For one, it is easier to
use: simply use your colors normally, and the system will take care of
mapping them to the system palette. Secondly, switching between two applications
that are both using the system palette will be smooth. Switching between
two applications that use different palettes will result in a visible flash
as Windows maps the appropriate palette and takes colors away from the
application that no longer has control.

On high-color displays, colors are effectively free: one can simply
use RGB values without any regard to palettes or color availability.

X/Motif

On X, the color model also depends on whether the
display is palette-based or high-color. X has a palette-based system similar
to that of Windows, using the term colormap instead of palette. The primary
difference between Windows and X, however, is that colors on X must be
allocated with XAllocColor prior to use, and freed with XFreeColor
when no longer required. As well, switching between two applications that
define their own palettes (private colormaps) on X results in all other
applications having their colors altered in such a way that the switch
is visibly more noticeable than on Windows. For this reason, most X applications
do not define a private colormap, but rather share the default colormap.
A limitation of X as compared to Windows is that it will not perform a
closest-match if a color cannot be allocated, but will answer black instead.
Thus if a closest match is desired, it must be performed by your code.

On high-color displays, where the pixel value encodes
the RGB value of the color, colors are free as they are on Windows. Although
the surest way to use colors on a high-color display is still to use XAllocColor,
one can simply encode the RGB values into pixel values and use the pixels
directly, without having to allocate or free the colors.

Options

After taking into account the above platform features
and limitations, a variety of options presented themselves as possible
solutions to SWT's color management story.

1) expose Palette as a class to the SWT
user:

Both Windows and X support the
notion of palettes on low-color displays. One option is to expose Palette
as a class to the SWT user, and allow the Palette to be set into a
GC. One problem with this approach is that X's palette solution is
undesirable due to its flashy behavior. This approach maps better to Windows
due to the platform’s improved palette switching capabilities. On X, however,
given the above limitation, SWT would want to give the illusion of palettes
to the developer, while mapping colors to the default colormap underneath.
Another problem is that of managing the palettes of multiple GCs in
the same window; on Windows, the colors from these palettes would need to
be somehow combined into a single palette when the window is given focus.
Providing user palettes would also require SWT to implement a default palette,
which would add complexity to the palette management code.

2) support only high-color displays:

Windows and X make it very
easy to use high-color displays, and more difficult to use low-color displays.
Another option is simply to support only high-color displays, and make
colors free from the SWT user's perspective, meaning they do not need to
be allocated or disposed. The obvious disadvantage of this approach is
that many low-color displays exist and would be excluded from running SWT-based
applications. (Of course, over time the number of systems that still run
in low-color mode is decreasing, but there are still a significant number
of real-world applications that require this.)

3) allocate a color cube:

A common approach to color
management is to allocate a fixed range of diverse colors, called a color
cube, when the application starts. All requested colors are mapped
to the closest color in the cube. This approach could be used in SWT for
low-color displays, making it very easy for the user to manage colors.
The advantage of this approach is that it is very simple for the user;
the disadvantage is that the user is constrained to a very limited set
of colors defined in the color cube, and will never be able to get an exact
match of the color he or she desires, unless it happens to be in the color
cube. This approach would not be ideal for high-color displays. Colors
in SWT would not be resources in this approach, and thus would not need
to be freed; SWT would take care of allocating the cube on startup and
freeing it on shutdown.

4) allocate colors:

The last option is to make
the user allocate and free colors as if they were platform resources. (i.e.
create with a constructor and free with dispose). This maps well
to X, where colors are a resource, but not well to Windows, where colors
are not a resource. This option is discussed in detail in the next section.

The SWT Color Model

Goals

After examining the platform behavior and possible
solutions, the following three goals for SWT's color model were decided
upon:

SWT must support both palette-based and direct color devices (high-color
displays). Palette-based devices are usually those containing 8 bits per
pixel or less, while direct color devices are typically 15 bits per pixel
and higher. In palette-based devices, the OS maintains a mapping of RGB
values to pixel values, while in direct color devices the RGB values are
encoded into the pixel value.

The model must be portable. The color model supported by Windows, for example,
is fundamentally different than the model supported by X. The SWT model
must accommodate those differences in a way that is transparent to the
SWT user.

It is important that, under normal circumstances, the user be given exactly
the color that was requested. Any scheme that limits the available colors
to those contained in a small, pre-allocated palette will fail to offer
the user exact colors.

Decisions

Our requirement of supporting palette-based displays rules out the second
of the above options (“support only high-color displays”). The requirement
to provide exact colors upon request means that allocating a color-cube
and matching all requests to that cube (the third option – “allocate a
color cube”) is also not acceptable.

Providing the user with palettes that they can manage (as described in
the first option – “expose palette as a class”) sounds like a good solution,
but in practice, it makes client code very complex and hard to manage. Given
the simple color requirements of typical applications, this option was ruled
out.

Thus, the only remaining option (the last one listed above), allocating
and disposing of colors independently, forms the basis of SWT's color model.

Palette Per Display using Allocate & Dispose

On palette-based displays under Windows, SWT creates and manages one palette
per Display. Colors used in a GC are taken from this palette.
When the user allocates a Color, SWT checks if the palette is full.
If it is not, the color is added to the palette and the user will get the
exact color requested. If it is, the Color is allocated to be the
closest match in the palette. In both cases, the reference count for that
color is incremented. When a Color is disposed on Windows, SWT decrements
the reference count. When the reference count reaches zero, SWT will remove
the color from the palette. As with other SWT resources, clients must allocate
colors, and free them only when the color is no longer needed.

On palette-based displays under X, SWT does not create a private colormap
(palette), but instead uses the default colormap to avoid flashing and
undesirable behavior. When the user allocates a Color, SWT tries
to allocate the color with XAllocColor. If this succeeds, the user
gets exactly the color they asked for, and that color is remembered by
the Display. If it does not succeed, SWT finds the closest available
color and uses that instead. In both cases, the reference count for that
Color
is incremented.

When a Color is disposed on X, SWT will call XFreeColor,
which decrements the reference count on the X Server. As well, SWT will
decrement its internal reference count for that Color, and remove
it from the Display if the reference count is zero.

On high-color displays on both Windows and X, the SWT display does not maintain
a palette. Colors are still allocated and freed on X, but this operation
simply calculates the pixel value and nothing else. On 24-bit and higher displays,
the user is guaranteed to get exactly the color requested. On 16-bit displays,
the user will get a very close approximation, but not necessarily the exact
color, due to the fact that 16-bit pixel values cannot encode 8-bit red, green
and blue values with 100% accuracy. Low-color displays that use a lot of colors
may still flash.

Standard Colors

SWT provides access to the standard colors through Display.getSystemColor(int).
The following snipet returns the standard color for green.

display.getSystemColor(SWT.COLOR_GREEN)

The creator of an SWT Color is responsible for disposing of
the color when it is no longer required. In the above snipet we did not actually
create the color, consequently we must not dispose of the color.

Image Loading

When an SWT image is loaded, code similar to the following is usually used:

Image image = new Image(display, "filename");

Image loading is actually a two-step process. In the first
step, SWT loads the image into a device-independent, format-independent
object, called
ImageData. The second step involves creating the
actual device-dependent
Image from the ImageData. Before
this can happen, the colors that the image desires must be mapped to colors
that are actually available on the device. On a true-color display (high-color
display with at least 24-bit color), the colors are always available.

On a low-color display the RGB values contained in the ImageData's
palette are mapped to the closest match available in the SWT palette. The
colors that are available depend on which colors the user has already allocated.
If the user has not allocated many colors, then there may not be many colors
in the SWT palette for SWT to do a closest match to. SWT does not allocate
application colors. For this reason, it may be desirable to pre-allocate the
colors needed for the image. In the example above, however, there is no place
to allocate the colors; the user doesn't know what colors the image needs
before it is created. In situations like these, code such as the following
may be useful:

In this example, the two-step process is revealed to the user, giving
an opportunity to construct colors before the image is created, resulting
in a more realistic image. In practice, this is not needed, since most
displays are high-color.

The way SWT does image loading presents one possible difficulty. What if
the user allocates some colors, loads an image, and subsequently frees some
colors? There is a possibility that the image has chosen some of the colors
that the user freed. In this case, unpredictable results can occur after the
colors have been freed. Fortunately, this is very easy to work around: always
allocate your colors in a static fashion, and free them when you are finished
with them. This model is described in the section "Tips for Color Management
in SWT".

Tips for Color Management in SWT

Color management in SWT is very simple from the
user's perspective. There are 3 basic rules to help you manage your application's
color needs:

Colors contain OS resources that must be allocated and freed. For this
reason, it is necessary to dispose every color that you have created.

On high-color displays (16 bpp and higher), every Color allocation
is guaranteed to succeed. On low-color displays (8 bpp and lower), you
will either receive a Color with the exact RGB values that you asked
for or a reasonable facsimile (in other words, the closest match that could
be made). In this case, if you query the new Color, it will report
the actual RGB values, which are not necessarily the RGB values that you
asked for.

The envisioned usage of the
color model in SWT is fairly typical among plug-ins: a certain number of
fixed colors are decided upon for usage in the plug-in. The user allocates
these colors on plug-in startup, by creating Color objects. The plug-in
runs, and on shutdown, the user will call the dispose method for
these colors. This leads to a solution with minimal hassles in terms of
palettes being full and other color contention problems associated with
dynamically allocating and freeing colors while the plug-in is running.

Summary

We
have seen that SWT's portable color model supports a color palette per
display. Clients of SWT must explicitly create their color resources and
dispose of them when they are no longer required. SWT also provides access
to standard colors through Display.getSystemColor(int).

Microsoft, Windows, Windows NT, and the Windows logo are trademarks of Microsoft Corporation in the United States, other countries, or both.