Programmer Reference : Common Graphics : Using palettes : Selecting and drawing with palettes
Selecting and drawing with palettes
This section describes how to select palettes and how to draw using palettes.
Selecting a palette
Before you can draw using the colors of a given palette, the palette must first be selected in the window of the application's shell widget. This ensures that the palette's colors are available in the video hardware when the window is active. This is done using the setPalette: message.
If the default palette is to be used, the setPalette: message is not required, because it is selected by default when windows are created. Remember that CgIndexedPalettes can be selected in windows, not CgDirectPalettes.
The setPalette: message can be sent only to the window of a shell widget or to a pixmap. It is an error to send setPalette: to other windows. The shell window's palette is inherited by all child windows of the shell window.
The size of selected palettes should be kept as small as possible, to minimize color resource allocation. This gives other applications a better chance of drawing with their preferred colors.
The following example illustrates how to select a palette. This assumes that the shell message answers the CwTopLevelShell widget of the application (see "Shell widgets" for more information on shell widgets).
| names colors color palette |
names := #('black' 'white' 'red' 'green' 'blue' 'brown' 'aquamarine' 'pink').
colors := Array new: names size.
1 to: names size do: [:i |
color := self shell screen lookupColor: (names at: i).
color isNil ifTrue: self error: 'Color not found.'].
colors at: i put: color].
palette := CgIndexedPalette colors: colors.
self shell window setPalette: palette
Retrieving the selected palette
The selected palette can be retrieved using the getPalette message.
The getPalette message can be sent to any drawable. If getPalette is sent to a window that is not a shell window, the palette of the shell window is answered.
Drawing with palettes
To use a color specified by the selected palette, the corresponding pixel value is set in the graphics context foreground or background component. For example, the following code draws a blue-filled rectangle, assuming the palette in the previous example is selected. This code assumes that the drawable message answers the window of a CwDrawingArea widget (which is a child of the shell widget used in the previous example).
| gc |
gc := self drawable
createGC: None
values: CgGCValues new.
"Blue has a pixel value of 4 in the palette."
gc setForeground: 4.
self drawable
fillRectangle: gc x: 0 y: 0 width: 100 height: 50.
gc freeGC
Alternatively, the getPalette and nearestPixelValue: methods can be used to find the appropriate pixel value.
| gc palette pixelValue |
gc := self drawable
createGC: None
values: CgGCValues new.
palette := self drawable getPalette.
pixelValue := palette
nearestPixelValue: (self shell screen lookupColor: 'blue').
gc setForeground: pixelValue.
self drawable
fillRectangle: gc x: 0 y: 0 width: 100 height: 50.
gc freeGC
Drawing in black and white
If drawing is done in black or white, the blackPixel and whitePixel methods of CgDrawable can be used to determine the pixel value to use for the selected palette.
The blackPixel and whitePixel methods of CgDrawable answer the pixel value of the color closest to black and white, respectively, in the drawable's selected palette.
Drawing in pixmaps using palettes
Drawing in pixmaps requires special consideration when using palettes other than the default palette.
When a CgPixmap is first created using createPixmap:, the default palette is selected in the pixmap, not the palette of receiver of the createPixmap: message. The receiver is only used to specify the screen and compatible depths of the pixmap. Because the receiver might not be the intended destination of a copy operation using the pixmap, the receiver's palette is not selected in the pixmap.
The palette of the window in which the pixmap is to be displayed must be selected in the pixmap before drawing is done. This is required so that the pixel-value-to-color mapping of the pixmap is the same as that of the destination window. If this is not done, the pixel-value-to-color mappings for the pixmap and the destination window will be different, and the results will not be what is expected when the pixmap is copied to the window.
The following code shows the correct way to draw in a pixmap using a palette other than the default palette. The code assumes that the shell method answers the CwTopLevelShell widget and that the drawingArea method answers the CwDrawingArea widget in which the pixmap will be displayed.
| shellWindow destWindow colors color palette pixmap gc |
shellWindow := self shell window.
destWindow := self drawingArea window.
"Create the palette."
colors := Array new: 16.
0 to: 15 do: [:i |
color := CgRGBColor red: 65535 * i // 15 green: 0 blue: 0.
colors at: i + 1 put: color].
palette := CgIndexedPalette colors: colors.
"Select the palette in the shell window."
shellWindow setPalette: palette.
"Create the pixmap and select the palette in it."
pixmap := destWindow
createPixmap: 320 height: 50 depth: destWindow depth.
pixmap setPalette: palette.
"Draw vertical bars in increasing intensities of red in the pixmap."
gc := pixmap
createGC: None
values: nil.
0 to: 15 do: [:i |
gc setForeground: i.
fillRectangle: gc x: i * 20 y: 0 width: 20 height: 50].
"Copy the pixmap to the destination window."
copyArea: destWindow gc: gc srcX: 0 srcY: 0 width: 320 height: 50
destX: 0 destY: 0.
"Free the gc and pixmap."
gc freeGC.
pixmap freePixmap
Last modified date: 01/29/2015