Drawing Graphics: 3.1 Shape Attributes: Color

Up: GEOS SDK TechDocs| Up | Prev: 3 Shape Attributes | Next: 3.2 Patterns and Hatching

If your geode displays graphics, you can probably make its graphical display more effective by using color. Your geode can have as much control over color as it wants, ranging from saying what colors certain objects should be to choosing which colors should be available.

Most color controllers work with the concept of a palette, a subset of the colors your video device is capable of displaying. Most controllers can only use some of these colors at a time; these colors make up the palette. You can refer to colors by their color index (i.e. their place in the palette). You can also refer to colors by their RGB values.

An RGB value specifies a color by mixing intensities of red, green, and blue. The more of each component color added, the more of that color will show up in the result. If all components are equal, the result will be a shade of gray. If all components are zero, the result will be black. If all components are at the maximum (255), the result will be white.

The data structure used to store color information is known as the ColorQuad , shown in Color Data Structures.

Code Display 24-1 Color Data Structures

typedef struct {
	/* The ColorQuad data structure is used to represents a color. There are
	 * many ways to describe a color. The CQ_info field determines how the
	 * color is being specified, and the other fields will be interpreted
	 * based on CQ_info's value. Colors may be referenced by palette index,
	 * RGB value, or grey scale value. */
		/* CQ_redOrIndex
		 * If CQ_info is CF_INDEX, then this is the palette index.
		 * If CQ_info is CF_RGB, then this is the Red component.
		 * If CQ_info is CF_GRAY, then this is the Gray scale */
	byte 	CQ_redOrIndex;
		/* CQ_info:
		 * This ColorFlag determines how the other three fields of the
		 * ColorQuad will be interpreted. The ColorFlag type is shown 
		 * below. */
	ColorFlag 	CQ_info;
		/* CQ_green:
		 * If CF_RGB, then these fields are the Green and Blue components.
		 * Otherwise, these fields are ignored. */
	byte 	CQ_green;
	byte 	CQ_blue;
} ColorQuad;
 typedef dword ColorQuadAsDWord;
    typedef ByteEnum 	ColorFlag;
	CF_INDEX,	
		/* Color specified by palette index. The values of the first
		 * 16 entries of the system palette are specified by Color values */
	CF_GRAY,
		/* Color specified by gray value; this is like CF_RGB, but the
		 * value in CQ_redOrIndex will be used for the Green and Blue 
		 * fields as well. */
	CF_SAME,
		/* Used with hatch patterns, if this flag is set, hatches will draw
		 * using the default color (the one set using GrSetXXXXColor()) */
	CF_RGB
		/* Color Set using RGB values */
/* Sample Colors:
 * To use the system palette's light green:						{ C_LIGHT_GREEN, CF_INDEX, 0, 0}
 * To use the 40th color in the palette:						{ 40, CF_INDEX, 0, 0}
 * To use a custom brown:						{ 150, CF_RGB, 90, 0}
 * To use a 75% Gray (75% *256 = 192):						{ 192, CF_GRAY, 0, 0}
 */

Using Available Colors

GrGetAreaColor(), GrSetAreaColor(), GrGetLineColor(), GrSetLineColor(), GrGetTextColor(), GrSetTextColor()

If a geode is to draw something in color, it first calls a routine to set which color to use, then calls the appropriate drawing routine. The color can be specified in terms of its palette index or its RGB value. The data specifying which color to use is stored in the GState, with separate color fields to keep track of how to draw lines, areas, and text.

GrSetLineColor() changes the color used when drawing lines. The GrSetAreaColor() routine sets the color to be used when filling areas. GrSetTextColor() sets the color to be used when rendering text. GrGetLineColor() , GrGetAreaColor() , and GrGetTextColor() return the color values and flags stored with the GState.

The default system palette includes several colors whose indexes have been set up so they may be referenced by descriptive constant names. The constants are members of the enumerated type Color , the most common shown in the figure above. Thus, instead of having to remember that the index 02 means green, the constant C_GREEN can be passed to the appropriate color setting command.

Other Color values include a 16-shade gray scale (the C_GRAY_...entries), some "unused" entries (the C_UNUSED_... entries), and a number of entries which have been set up to allow you to specify a color by its red, green, and blue components on a zero-to-five scale (the C_R..._G..._B... entries).

Programmers should use care when using these constants in conjunction with palette manipulation, as it is possible to change the RGB color value associated with a palette entry. Since the constant names are associated with palette indexes instead of RGB values, it is possible to change the RGB value of palette entry 02 so that the C_GREEN constant actually refers to, for example, a shade of magenta.

When the Color Isn't in the Palette

GrSetLineColorMap(), GrSetAreaColorMap(), GrSetTextColorMap(), GrGetLineColorMap(), GrGetAreaColorMap(), GrGetTextColorMap(), GrMapColorIndex(), GrMapColorRGB()

Not all users have video devices which can display 256 colors at a time. Even fewer have printers capable of doing so. Therefore, the graphics system makes allowances for drawings which use unavailable colors. Exactly what the system will do with an unavailable color depends on the color mapping mode used. By default, the system will choose the two (or more) closest available colors and dither them together in an attempt to form a mixture which will appear to be the correct color overall when seen from a distance.

GrSetLineColorMap() , GrSetAreaColorMap() , and GrSetTextColorMap() set the color mapping to use when drawing with an unavailable color. GrGetLineColorMap() , GrGetAreaColorMap() , and GrGetTextColorMap() return the current color mapping modes. The geode may draw either in the closest available color, or using a dithering of the closest colors. Often it's a good idea to have text map to solid colors since its detailed nature doesn't go too well with dithering.

When a geode wants to learn more about which colors are available, it can use the GrMapColorIndex() routine to find the RGB value associated with an index. The GrMapColorRGB() routine returns the index and true RGB color of the palette entry that most closely matches the values passed.

Custom Palettes

GrCreatePalette(), GrDestroyPalette(), GrSetPaletteEntry(), GrSetPalette(), GrGetPalette()

If the system default palette does not meet a geode's needs, the geode can change its own palette. Some bitmaps (such as those in GIF) have palettes associated with them, and a geode displaying such bitmaps might wish to display the bitmap in its true colors without settling for the closest defaults. Specialized tasks such as photo processing, anti-aliasing, and color cycle animation tend to depend on the ability to manipulate palettes. A geode can create a custom palette associated with a window, then change the color values of entries in that palette.

Since the palette is associated with a window, there can be as many custom palettes as there are windows. The video driver uses the palette associated with the active window. This means that all the inactive windows (and the background) will also be drawn with the palette of the active window; thus, if you give a window a special palette, that may make inactive windows look different. To avoid this, try to avoid changing palette entries 0-15, as the UI uses these (These are the entries representing C_RED, etc.).

GrCreatePalette() creates a custom palette and associates it with your graphic state's associated window. The custom palette starts with all entries having their original RGB values from the default palette. GrSetPaletteEntry() takes a palette entry and sets it to a new RGB value. GrSetPalette() allows you to specify new values for several palette entries at a time. GrSetPalette() can also set an entry back to its default value. GrDestroyPalette() destroys the custom palette, freeing the memory used for it.

Given a choice of palette entries to change, you might choose one of the C_UNUSED_... entries.

Call GrGetPalette() to get a handle to a memory block containing the palette data. Depending on the GetPalType passed, you will either get the palette information for your current palette or the default palette. This routine returns the handle of a memory block. The memory block contains an array with 256 entries (one for each color), each entry consisting of three bytes. The first byte of each entry is the color's red component, the second is the color's green component, and the third is the color's blue component.


Up: GEOS SDK TechDocs| Up | Prev: 3 Shape Attributes | Next: 3.2 Patterns and Hatching