Graphics Contents Index General Designs




13 Drawing in Color

This chapter describes the :ink drawing option and the simpler values that can be supplied for that option, such as colors. More complex values that have a regular or irregular pattern in the ink are described in Chapter General Designs .


Issue: SWM
We need to add a thing called a ``palette'', which is simply an abstract color map. Palettes are primarily used as a resource for the limited number of colors on most hosts. Do we need to be able to used them to more directly control color maps, to do ``color map animation'', for example?

Issue: SWM
We need to add a thing called a ``raster ink'', which includes things like plane masks, pixel values, etc. Be clear that this is platform and device dependent.

13.1 The :ink Drawing Option

The :ink drawing option, used with the drawing functions described in Chapter Graphics , can take as its value: More exactly, an ink can be any member of the class design . For now you may think of a design as a possibly translucent color. More general designs are described in Chapter General Designs .

The drawing functions work by selecting a region of the drawing plane and painting it with color. The region to be painted is the intersection of the shape specified by the drawing function and the :clipping-region drawing option, which is then transformed by the :transformation drawing option. The :ink drawing option is a design that specifies a new arrangement of colors (and opacities) in this region of the medium's drawing plane. Any viewports or dataports attached to this drawing plane are updated accordingly. The :ink drawing option is never affected by the :transformation drawing option nor by the medium's transformation; this ensures that stipple patterns on adjacent sheets join seamlessly.


Issue: DCPL
The description of how the clipping region and transformations contribute isn't good enough. It is true if there are no other transformations and clipping regions present, and both are specified in the current drawing operation. But it doesn't say what happens if things are nested. I'm not sure it needs to. Rather, I think it should just say that the the region is clipped by the current clipping region in effect, then transformed by the current transform in effect, and that the rules for these are discussed in the drawing options section.
Drawing consists conceptually of the following sequence of operations, performed in parallel at every point in the drawing plane. Of course, the actual implementation does not involve an infinite (or large parallel) computation.

    The design specifies a color and an opacity at the point. These can depend on the drawing plane's current color and opacity, on the medium's foreground color, and on the medium's background color.

    The color blending function is applied to the design's color and opacity and the drawing plane's color and opacity, returning a new color and opacity for the point.

    The drawing plane's color and opacity at that point are set to the new color and opacity.

13.2 Basic Designs

design[Protocol Class]
A design is an object that represents a way of arranging colors and opacities in the drawing plane. The design class is the protocol class for designs. If you want to create a new class that behaves like a design, it should be a subclass of design. Subclasses of design must obey the design protocol.The fundamental operation of the CLIM graphic drawing model is to draw a design onto a drawing plane, thus drawing is always controlled by designs. The designs discussed in this chapter do the same thing at each point in the drawing plane. Chapter General Designs discusses more general designs and reveals that regions are also designs.

A design can be characterized in several different ways:

All designs are either bounded or unbounded . Bounded designs are transparent everywhere beyond a certain distance from a certain point. Drawing a bounded design has no effect on the drawing plane outside that distance. Unbounded designs have points of non-zero opacity arbitrarily far from the origin. Drawing an unbounded design affects the entire drawing plane.

All designs are either uniform or non-uniform . Uniform designs have the same color and opacity at every point in the drawing plane. Uniform designs are always unbounded, unless they are completely transparent.

All designs are either solid or translucent . At each point a solid design is either completely opaque or completely transparent. A solid design can be opaque at some points and transparent at others. In translucent designs, at least one point has an opacity that is intermediate between completely opaque and transparent.

All designs are either colorless or colored . Drawing a colorless design uses a default color specified by the medium's foreground design. This is done by drawing with (compose-in +foreground-ink+ the-colorless-design) . See Chapter General Designs for the details of compose-in .

designpobject[Predicate]
Returns true if object is a design , otherwise returns false .

13.3 Color

color[Protocol Class]
A member of the class color is a completely opaque design that represents the intuitive definition of color: white, black, red, pale yellow, and so forth. The visual appearance of a single point is completely described by its color. Drawing a color sets the color of every point in the drawing plane to that color, and sets the opacity to 1. The color class is the protocol class for a color, and is a subclass of design . If you want to create a new class that behaves like a color, it should be a subclass of color. Subclasses of color must obey the color protocol.All of the standard instantiable color classes provided by CLIM are immutable.

A color can be specified by three real numbers between 0 and 1 (inclusive), giving the amounts of red, green, and blue. Three 0's mean black; three 1's mean white. The intensity-hue-saturation color model is also supported, but the red-green-blue color model is the primary model we will use in the specification.

colorpobject[Predicate]
Returns true if object is a color , otherwise returns false .

The following functions create colors. These functions produce objects that have equivalent effects; the only difference is in how the color components are specified. The resulting objects are indistinguishable when drawn. Whether these functions use the specified values exactly or approximate them because of limited color resolution is unspecified. Whether these functions create a new object or return an existing object with equivalent color component values is unspecified.

make-rgb-colorred green blue[Function]
Returns a member of class color . The red , green , and blue arguments are real numbers between 0 and 1 (inclusive) that specify the values of the corresponding color components.

make-ihs-colorintensity hue saturation[Function]
Returns a member of class color . The intensity argument is a real number between 0 and sqrt(3) (inclusive). The hue and saturation arguments are real numbers between 0 and 1 (inclusive).

make-gray-colorluminance[Function]
Returns a member of class color . luminance is a real number between 0 and 1 (inclusive). On a black-on-white display device, 0 means black, 1 means white, and the values in between are shades of gray. On a white-on-black display device, 0 means white, 1 means black, and the values in between are shades of gray.

The following two functions comprise the color protocol. Both of them return the components of a color. All subclasses of color must implement methods for these generic functions.

color-rgbcolor[Generic function]
Returns three values, the red , green , and blue components of the color color . The values are real numbers between 0 and 1 (inclusive).

color-ihscolor[Generic function]
Returns three values, the intensity , hue , and saturation components of the color color . The first value is a real number between 0 andn sqrt(3) (inclusive). The second and third values are real numbers between 0 and 1 (inclusive).

13.3.1 Standard Color Names and Constants

Table 13.1 lists the commonly provided color names that can be looked up with find-named-color . Application programs can define other colors; these are provided because they are commonly used in the X Windows community, not because there is anything special about these particular colors. This table is a subset of the color listed in the file /X11/R4/mit/rgb/rgb.txt , from the X11 R4 distribution.




alice-blue antique-white aquamarine
azure beige bisque
black blanched-almond blue
blue-violet brown burlywood
cadet-blue chartreuse chocolate
coral cornflower-blue cornsilk
cyan dark-goldenrod dark-green
dark-khaki dark-olive-green dark-orange
dark-orchid dark-salmon dark-sea-green
dark-slate-blue dark-slate-gray dark-turquoise
dark-violet deep-pink deep-sky-blue
dim-gray dodger-blue firebrick
floral-white forest-green gainsboro
ghost-white gold goldenrod
gray green green-yellow
honeydew hot-pink indian-red
ivory khaki lavender
lavender-blush lawn-green lemon-chiffon
light-blue light-coral light-cyan
light-goldenrod light-goldenrod-yellow light-gray
light-pink light-salmon light-sea-green
light-sky-blue light-slate-blue light-slate-gray
light-steel-blue light-yellow lime-green
linen magenta maroon
medium-aquamarine medium-blue medium-orchid
medium-purple medium-sea-green medium-slate-blue
medium-spring-green medium-turquoise medium-violet-red
midnight-blue mint-cream misty-rose
moccasin navajo-white navy-blue
old-lace olive-drab orange
orange-red orchid pale-goldenrod
pale-green pale-turquoise pale-violet-red
papaya-whip peach-puff peru
pink plum powder-blue
purple red rosy-brown
royal-blue saddle-brown salmon
sandy-brown sea-green seashell
sienna sky-blue slate-blue
slate-gray snow spring-green
steel-blue tan thistle
tomato turquoise violet
violet-red wheat white
white-smoke yellow yellow-green
Table 13.1: Standard color names.




In addition, the following color constants are provided.

+red+[Constant]
+green+[Constant]
+blue+[Constant]
+cyan+[Constant]
+magenta+[Constant]
+yellow+[Constant]
+black+[Constant]
+white+[Constant]
Constants corresponding to the usual definitions of red, green, blue, cyan, magenta, yellow, black, and white.

13.3.2 Contrasting Colors

make-contrasting-inksn &optional k[Function]
If k is not supplied, this returns a vector of n designs with recognizably different appearance. Elements of the vector are guaranteed to be acceptable values for the :ink argument to the drawing functions, and will not include +foreground-ink+ , +background-ink+ , or nil . Their class is otherwise unspecified. The vector is a fresh object that may be modified.

If k is supplied, it must be an integer between 0 and n -1 (inclusive), in which case make-contrasting-inks returns the k 'th design rather than returning a vector of designs.

If the implementation does not have n different contrasting inks, make-contrasting-inks signals an error. This will not happen unless n is greater than eight.

The rendering of the design may be a color or a stippled pattern, depending on whether the output medium supports color.

contrasting-inks-limitport[Generic function]
Returns the number of contrasting colors (or stipple patterns if port is monochrome or grayscale) that can be rendered on any medium on the port port . Implementations are encouraged to make this as large as possible, but it must be at least 8. All classes that obey the medium protocol must implement a method for this generic function.

13.4 Opacity

opacity[Protocol Class]
A member of the class opacity is a completely colorless design that is typically used as the second argument to compose-in to adjust the opacity of another design. See Chapter General Designs for the details of compose-in . The opacity class is the protocol class for an opacity, and is a subclass of design . If you want to create a new class that behaves like an opacity, it should be a subclass of opacity. Subclasses of opacity must obey the opacity protocol.All of the standard instantiable opacity classes provided by CLIM are immutable.

Opacity controls how graphical output covers previous output. Opacity can vary from totally opaque to totally transparent. Intermediate opacity values result in color blending so that the earlier picture shows through what is drawn on top of it.

An opacity may be specified by a real number between 0 and 1 (inclusive). 0 is completely transparent, 1 is completely opaque, fractions are translucent. The opacity of a design is the degree to which it hides the previous contents of the drawing plane when it is drawn.

The fully transparent and fully opaque opacity levels (that is, opacities 0 and 1) must always be supported, but a valid CLIM implementation might only support a handful of opacity levels in between (including none). A valid CLIM implementation might implement color blending and unsaturated colors by stippling, although it is preferred, when possible, for a viewport to display a uniform color as a uniform color rather than as a perceptible stipple.

opacitypobject[Predicate]
Returns true if object is an opacity , otherwise returns false .

The following function returns an opacity:

make-opacityvalue[Function]
Returns a member of class opacity whose opacity is value , which is a real number in the range from 0 to 1 (inclusive), where 0 is fully transparent and 1 is fully opaque.

+transparent-ink+[Constant]
An fully transparent ink, that is, an opacity whose value is 0. This is typically used as the ``background'' ink in a call to make-pattern .

The following function returns the sole component of an opacity. This is the only function in the opacity protocol. All subclasses of opacity must implement methods for this generic function.

opacity-valueopacity[Generic function]
Returns the opacity value of the opacity opacity , which is a real number in the range from 0 to 1 (inclusive).

13.5 Color Blending

Drawing a design that is not completely opaque at all points allows the previous contents of the drawing plane to show through. The simplest case is drawing a solid design: where the design is opaque, it replaces the previous contents of the drawing plane; where the design is transparent, it leaves the drawing plane unchanged. In the more general case of drawing a translucent design, the resulting color is a blend of the design's color and the previous color of the drawing plane. For purposes of color blending, the drawn design is called the foreground and the drawing plane is called the background.

The function compose-over performs a similar operation: it combines two designs to produce a design, rather than combining a design and the contents of the drawing plane to produce the new contents of the drawing plane. For purposes of color blending, the first argument to compose-over is called the foreground and the second argument is called the background. See Chapter General Designs for the details of compose-over .

Color blending is defined by an ideal function F:(r1,g1,b1,o1,r2,g2,b2,o2) =>(r3,g3,b3,o3) that operates on the color and opacity at a single point. (r1,g1,b1,o1) are the foreground color and opacity. (r2,g2,b2,o2) are the background color and opacity. (r3,g3,b3,o3) are the resulting color and opacity. The color blending function F is conceptually applied at every point in the drawing plane.

F performs linear interpolation on all four components:

o3 = o1 + (1 - o1) * o2
r3 = (o1 * r1 + (1 - o1) * o2 * r2) / o3
g3 = (o1 * g1 + (1 - o1) * o2 * g2) / o3
b3 = (o1 * b1 + (1 - o1) * o2 * b2) / o3
Note that if o3 is zero, these equations would divide zero by zero. In that case r3, g3, and b3 are defined to be zero.

CLIM requires that F be implemented exactly if o1 is zero or one or if o2 is zero. If o1 is zero, the result is the background. If o1 is one or o2 is zero, the result is the foreground. For fractional opacity values, an implementation can deviate from the ideal color blending function either because the implementation has limited opacity resolution or because the implementation can compute a different color blending function much more quickly.

If a medium's background design is not completely opaque at all points, the consequences are unspecified. Consequently, a drawing plane is always opaque and drawing can use simplified color blending that assumes o2 = 1 and o3 = 1. However, compose-over must handle a non-opaque background correctly.

Note that these (r,g,b,o) quadruples of real numbers between 0 and 1 are mathematical and an implementation need not store information in this form. Most implementations are expected to use a different representation.

13.6 Indirect Inks

Drawing with an indirect ink is the same as drawing another design named directly. For example, +foreground-ink+ is a design that draws the medium's foreground design and is the default value of the :ink drawing option. Indirect inks exist for the benefit of output recording. For example, one can draw with +foreground-ink+ , change to a different medium-foreground , and replay the output record; the replayed output will come out in the new color.

You can change the foreground or background design of a medium at any time. This changes the contents of the medium's drawing plane. The effect is as if everything on the drawing plane is erased, the background design is drawn onto the drawing plane, and then everything that was ever drawn (provided it was saved in the output history) is drawn over again, using the medium's new foreground and background.

If an infinite recursion is created using an indirect ink, an error is signalled when the recursion is created, when the design is used for drawing, or both.

Two indirect inks are defined, but no advertised way is provided to create more of them.

+foreground-ink+[Constant]
An indirect ink that uses the medium's foreground design.

+background-ink+[Constant]
An indirect ink that uses the medium's background design.

13.7 Flipping Ink

make-flipping-inkdesign1 design2[Function]
Returns a design that interchanges occurrences of the two designs design1 and design2 . Drawing the resulting design over a background (either by drawing or with compose-over ) is defined to change the color in the background that would have been drawn by design1 at that point into the color that would have been drawn by design2 at that point, and vice versa. The effect on any color other than the colors determined by those two designs is unspecified; however, drawing the same figure twice using the same flipping ink is guaranteed to be an ``identity'' operation. If either design1 or design2 is not solid, the consequences are unspecified. The purpose of flipping is to allow the use of ``XOR hacks'' for temporary changes to the display.

The opacity of a flipping ink is zero at points where the opacity of either design1 or design2 is zero. Otherwise the opacity of a flipping ink is 1. If design1 or design2 is translucent, the consequences are unspecified. If compose-in or compose-out is used to make a flipping ink translucent, the consequences are unspecified.

If design1 and design2 are equivalent, the result can be +nowhere+ .

In Release 2, make-flipping-ink might require design1 and design2 to be colors.

+flipping-ink+[Constant]
A flipping ink that flips +foreground-ink+ and +background-ink+ .

13.8 Examples of Simple Drawing Effects

Drawing in the foreground color.
Use the default, or specify :ink +foreground-ink+ .

Erasing.
Specify :ink +background-ink+ .

Drawing in color.
Specify :ink +green+ , :ink (make-rgb-color 0.6 0.0 0.4) , and so forth.

Drawing an opaque gray.
Specify :ink (make-gray-color 0.25) to draw in a shade of gray independent of the window's foreground color. On a non-color, non-grayscale display this will generally turn into a stipple.



Graphics Contents Index General Designs