站内搜索: 请输入搜索关键词

当前页面: 开发资料首页Eclipse 英文资料SWT Color Model

SWT Color Model

摘要: The 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 OTI


Background

Before diving into the SWT color model, lets 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 platforms 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:
  1. 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.
  2. 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.
  3. 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:

ImageDate imageData = new ImageData("filename"); rgbs = imageData.getRGBs(); colors = new Color[rgbs.length]; for (int i = 0; i < colors.length; i++) { colors[i] = new Color(display, rgbs[i]); } image = new Image(display, imageData); ... // dispose the image and colors when no longer needed

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:
  1. Colors contain OS resources that must be allocated and freed. For this reason, it is necessary to dispose every color that you have created.
  2. 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.
  3. 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.


↑返回目录
前一篇: API Rules of Engagement
后一篇: Mark My Words