5.10. Colour and Visuals   

The objective of maintaining device independence in X can become a little stretched when we start to talk about colour. Typical hardware configurations can have monochrome, 16 colour (eg PCs), 256 colour or full 24 bit colour (16 million colours) displays.

Providing your application with colour can sometimes be the difference between selling a system or not selling a system. Colour hardware does cost more than monochrome hardware, but the difference is constantly reducing.

For example, a local company has purchased approximately 550 personal computers. About twenty of these machines were purchased with only monochrome screens. Approximately 80 machines were portable pcs, capable of driving an external colour monitor, and seven systems were CADAD pcs equipped with one mono and one colour monitor. Of the 54 Unix workstations that the comapny owns, 50 are colour systems (46 Intergraph, 3 Sun and the RS6000), 3 are monochrome systems (HP LM/X servers) and one has mono text only (the IBM RT/PC).

The above data is intended to illustrate that many (but not all) machines capable of running X are likely to be running colour of some sort. My own opinion is that if you are spending $15000 + on a Unix workstation then management expect it to look fancier than a PC which costs $4000.

My own recommendation would be to develop your X applications under the assumption that you have a small number of colours available (16-20). This permits you to run your system on pcs, colour Macs, and of course colour workstations. However, you should write your application so that it does not die in black and white.

Johnson and Reichard in their book X Windows Application Programming (MIS Press, 1992) offer the following advice:

Before requiring colour for your applications think carefully whether the colour is actually needed. Adding even low end colour to a workstation typically adds $1000 to $2000 to the cost of the hardware....In addition a significant number of people are partially or fully colour blind.

Design the original interface in monochrome (black and white). That way, you can still provide a monochrome version. One worthwhile piece of advice (from Apple Computer's Inside Macintosh series) is to colour the black bits only. That way the interface will still work in black and white.

5.10.1. Visuals   

The X Window System provides the concept of visuals to abstract the differences between hardware. There are six visual classes -


PseudoColor : Allows for read/write colormaps.
Silicon Graphics workstations are set to use the PseudoColor
visual as the default visual class
(Pipeline 2:6, 1991).
Many X applications assume that PseudoColor is the default visual.
This is not a good practice in general.
StaticColor : A PseudoColor system with a read only colour map.
GrayScale : Essentially a PseudoColor system where the red, green
and blue values are always the same.
StaticGray : A GrayScale visual with a read only colour map.
X treats monochrome systems (eg. cain and abel) as two colour
StaticGray systems.
DirectColor : Provides red, green and blue colour lookup tables
(decomposed tables) and a read/write colour map.
TrueColor : A DirectColor system with a read only colour map.

For this course we will only use the PseudoColor visual class as it is the easiest to use and it is supported by most X servers running on colour systems. You can verify what visuals are supported by your X server by running the xdpyinfo program.

You will remember that visuals are used when creating windows. Previously we played safe and used the constant CopyFromParent when specifying the visual.

If the default visual is PseudoColor, then we would normally prefer to use the default visual and colour map. If the default is not PseudoColor, then we can search for one that is of type PseudoColor.

     Display        * display;

int screen;
Visual * visual;
Colormap colourmap;
int depth;
visual = DefaultVisual( display, screen );
if (visual->class == PseudoColor )
{
colourmap = DefaultColormap( display, screen );
depth = DefaultDepth( display, screen );
}
else
{
/**********************************************************
Unexpected circumstance. May be unable to find a PseudoColor
visual, or the hardware may just not support PseudoColor.
For an algorithm to handle this refer to p96 of Johnson and
Reichard (X Windows Application Programming, MIS Press 1992).
************************************************************/
}

Note that the tutorials assume that the default visual is PseudoColor. In fact the tutorials tend to avoid visuals altogether. This can be achieved by using the macro DefaultColormap, which takes the screen (rather than a visual id) as a parameter. The X server knows what visual is associated with that screen (typically CopyFromParent in the tutorial programs). Visuals are being used, but the details are being hidden from us.

We attempt to justify the use of this practice the fact that the tutorials were specifically written for the Personal Iris workstations.

5.10.2. Using Colour   

Each X server has a database of colours. Refer to /usr/lib/X11/rgb.txt on the Iris for a human readable version of this. You will see that it specifies each colour in terms of an 8-bit number for each of red, green and blue (that is a 24 bit RGB colour model). In X11 rel 3 there were only 66 colours specified. In release 4 this grew to over 600 colours.

Given the name of a colour, you can look up the RGB values via the XLookupColor function. You then put these values into the colour map using the XAllocColor function (or you can combine the two by just using the XAllocNamedColor function). We can then use this colour for drawing.

Sample code is shown below (for brevity no error handling is included). For a complete implementation refer to the setcolourvianame function in the tutorials.

     #include <X11/Xlib.h>

Display * display;
GC gc;
Colormap colourmap;
XColor req_rgb; /* The RGB specified in rgb.txt */
XColor hw_rgb; /* Closest hardware match to the above */
char * colourname = blue;
int status;
/******* If the colour map has not yet been obtained, get it using
colourmap = DefaultColormap( display, screen );
********************************************************/
status = XLookupColor ( display, colourmap, colourname,
&req_rgb, &hw_rgb );
if ( status == 0 ) /* Something went wrong */;
status = XAllocColor( display, colourmap, &hw_rgb );
if ( status == 0 ) /* Something went wrong */;
XSetForeground( display, gc, hw_rgb.pixel );