Drawing in Color Contents Index Extended Stream Output




14 General Designs

This chapter discusses more general designs than Chapter Drawing in Color and reveals that regions are also designs. This chapter generalizes to those designs that do not have the same color and opacity at every point in the drawing plane. These include:

Several of the features described in this chapter may not be fully supported in Release 2 of CLIM.

Note: A design is a unification of both a shape and a color and opacity. As such, a design can serve multiple roles. For example, the same design can play the role of an ink that colors the drawing plane, a shape that specifies where to draw another design, a stencil that controls the compositing of two designs, the background of a window, or a region that defines clipping. It is important not to get confused between type , which is inherent in an object, and role , which is determined by how an object is used in a particular function call.

14.1 The Compositing Protocol

Compositing creates a design whose appearance at each point is a composite of the appearances of two other designs at that point. Three varieties of compositing are provided: composing over , composing in , and composing out .

The methods for compose-over , compose-in , and compose-out will typically specialize both of the design arguments.

In Release 2, compositing might only be supported for uniform designs.

compose-overdesign1 design2[Generic function]
Composes a new design that is equivalent to the design design1 on top of the design design2 . Drawing the resulting design produces the same visual appearance as drawing design2 and then drawing design1 , but might be faster and might not allow the intermediate state to be visible on the screen.

If both arguments are regions, compose-over is the same as region-union .

This function is permitted to capture its mutable inputs; the consequences of modifying those objects are unspecified. The result returned by compose-over might be freshly constructed or might be an existing object.

compose-inink mask[Generic function]
Composes a new design by clipping the design ink to the inside of the design mask . The first design, ink , supplies the color, while the second design, mask , changes the shape of the design by adjusting the opacity.

More precisely, at each point in the drawing plane the resulting design specifies a color and an opacity as follows: the color is the same color that ink specifies. The opacity is the opacity that ink specifies, multiplied by the stencil opacity of mask .

The stencil opacity of a design at a point is defined as the opacity that would result from drawing the design onto a fictitious medium whose drawing plane is initially completely transparent black (opacity and all color components are zero), and whose foreground and background are both opaque black. With this definition, the stencil opacity of a member of class opacity is simply its value.

If mask is a solid design, the effect of compose-in is to clip ink to mask . If mask is translucent, the effect is a soft matte.

If both arguments are regions, compose-in is the same as region-intersection .

This function is permitted to capture its mutable inputs; the consequences of modifying those objects are unspecified. The result returned by compose-in might be freshly constructed or might be an existing object.

compose-outink mask[Generic function]
Composes a new design by clipping the design ink to the outside of the design mask . The first design, ink , supplies the color, while the second design, mask , changes the shape of the design by adjusting the opacity.

More precisely, at each point in the drawing plane the resulting design specifies a color and an opacity as follows: the color is the same color that ink specifies. The opacity is the opacity that ink specifies, multiplied by 1 minus the stencil opacity of mask .

If mask is a solid design, the effect of compose-out is to clip ink to the complement of mask . If mask is translucent, the effect is a soft matte.

If both arguments are regions, compose-out is the same as region-difference of mask and ink .

This function is permitted to capture its mutable inputs; the consequences of modifying those objects are unspecified. The result returned by compose-out might be freshly constructed or might be an existing object.

14.2 Patterns and Stencils

Patterning creates a bounded rectangular arrangement of designs, like a checkerboard. Drawing a pattern draws a different design in each rectangular cell of the pattern. To create an infinite pattern, apply make-rectangular-tile to a pattern.

A stencil is a special kind of pattern that contains only opacities.

make-patternarray designs[Function]
Returns a pattern design that has (array-dimension array 0) cells in the vertical direction and (array-dimension array 1) cells in the horizontal direction. array must be a two-dimensional array of non-negative integers less than the length of designs . designs must be a sequence of designs . The design in cell (i,j) of the resulting pattern is the nth element of designs , if n is the value of (aref array i j) . For example, array can be a bit-array and designs can be a list of two designs, the design drawn for 0 and the one drawn for 1.

Each cell of a pattern can be regarded as a hole that allows the design in it to show through. Each cell might have a different design in it. The portion of the design that shows through a hole is the portion on the part of the drawing plane where the hole is located. In other words, incorporating a design into a pattern does not change its alignment to the drawing plane, and does not apply a coordinate transformation to the design. Drawing a pattern collects the pieces of designs that show through all the holes and draws the pieces where the holes lie on the drawing plane. The pattern is completely transparent outside the area defined by the array.

Each cell of a pattern occupies a 1 by 1 square. You can use transform-region to scale the pattern to a different cell size and shape, or to rotate the pattern so that the rectangular cells become diamond-shaped. Applying a coordinate transformation to a pattern does not affect the designs that make up the pattern. It only changes the position, size, and shape of the cells' holes, allowing different portions of the designs in the cells to show through. Consequently, applying make-rectangular-tile to a pattern of nonuniform designs can produce a different appearance in each tile. The pattern cells' holes are tiled, but the designs in the cells are not tiled and a different portion of each of those designs shows through in each tile.

This function is permitted to capture its mutable inputs; the consequences of modifying those objects are unspecified.
pattern-widthpattern[Generic function]
pattern-heightpattern[Generic function]
These functions return the width and height, respectively, of the pattern pattern .

make-stencilarray[Function]
Returns a pattern design that has (array-dimension array 0) cells in the vertical direction and (array-dimension array 1) cells in the horizontal direction. array must be a two-dimensional array of real numbers between 0 and 1 (inclusive) that represent opacities. The design in cell (i,j) of the resulting pattern is the value of (make-opacity (aref array i j)) .

This function is permitted to capture its mutable inputs; the consequences of modifying those objects are unspecified.

14.3 Tiling

Tiling repeats a rectangular portion of a design throughout the drawing plane. This is most commonly used with patterns.

make-rectangular-tiledesign width height[Function]
Returns a design that, when used as an ink, tiles a rectangular portion of the design design across the entire drawing plane. The resulting design repeats with a period of width horizontally and height vertically. width and height must both be integers. The portion of design that appears in each tile is a rectangle whose top-left corner is at (0,0) and whose bottom-right corner is at (width,height). The repetition of design is accomplished by applying a coordinate transformation to shift design into position for each tile, and then extracting a width by height portion of that design.

Applying a coordinate transformation to a rectangular tile does not change the portion of the argument design that appears in each tile. However, it can change the period, phase, and orientation of the repeated pattern of tiles. This is so that adjacent figures drawn using the same tile have their inks ``line up''.

14.4 Regions as Designs

Any member of the class region is a solid, colorless design. The design is opaque at points in the region and transparent elsewhere. Figure 14.1 shows how the design and region classes relate to each other.

Figure 14.1: The class structure for all designs and regions. Entries in bold correspond to real CLIM classes.
Since bounded designs obey the region protocol, the functions transform-region and untransform-region accept any design as their second argument and apply a coordinate transformation to the design. The result is a design that might be freshly constructed or might be an existing object.

Transforming a uniform design simply returns the argument. Transforming a composite, flipping, or indirect design applies the transformation to the component design(s). Transforming a pattern, tile, or output record design is described in the sections on those designs.

14.5 Arbitrary Designs

draw-designmedium design &key ink clipping-region transformation line-style line-thickness line-unit line-dashes line-joint-shape line-cap-shape text-style text-family text-face text-size[Generic function]
Draws the design design onto the medium medium . This is defined to work for all types of regions and designs, although in practice some implementations may be more restrictive. ink , transformation , and clipping-region are used to modify the medium. The other drawing arguments control the drawing of the design, depending on what sort of design is being drawn. For instance, if design is a path, then line style options may be supplied.

If design is an area, draw-design paints the specified region of the drawing plane with medium's current ink. If design is a path, draw-design strokes the path with medium's current ink under control of the line-style. If design is a point, draw-design is the same as draw-point .

If design is a color or an opacity, draw-design paints the entire drawing plane (subject to the clipping region of the medium).

If design is +nowhere+ , draw-design has no effect.

If design is a non-uniform design (see Chapter General Designs ), draw-design paints the design, positioned at coordinates (0,0).

CLIM implementations are required to support draw-design for the following cases:

draw-pattern*medium pattern x y &key clipping-region transformation[Function]
Draws the pattern pattern on the medium medium at the position (x,y). pattern is any design created by make-pattern . clipping-region and transformation are as for with-drawing-options or any of the drawing functions.

Note that transformation only affects the position at which the pattern is drawn, not the pattern itself. If a programmer wishes to affect the pattern, he should explicity call transform-region on the pattern.

Drawing a bitmap consists of drawing an appropriately aligned and scaled pattern constructed from the bitmap's bits. A 1 in the bitmap corresponds to +foreground-ink+ , while a 0 corresponds to +background-ink+ if an opaque drawing operation is desired, or to +nowhere+ if a transparent drawing operation is desired.

Drawing a (colored) raster image consists of drawing an appropriately aligned and scaled pattern constructed from the raster array and raster color map.

draw-pattern* could be implemented as follows, assuming that the functions pattern-width and pattern-height return the width and height of the pattern.

(defun draw-pattern* (medium pattern x y &key clipping-region transformation)
  (check-type pattern pattern)
  (let ((width (pattern-width pattern))
        (height (pattern-height pattern)))
    (if (or clipping-region transformation)
        (with-drawing-options (medium :clipping-region clipping-region
                                      :transformation transformation)
          (draw-rectangle* medium x y (+ x width) (+ y height)
                           :filled t :ink pattern))
        (draw-rectangle* medium x y (+ x width) (+ y height)
                         :filled t :ink pattern))))

14.6 Examples of More Complex Drawing Effects

Painting a gray or colored wash over a display.
Specify a translucent design as the ink, such as :ink (compose-in +black+ (make-opacity 0.25)) , :ink (compose-in +red+ (make-opacity 0.1)) , or :ink (compose-in +foreground-ink+ (make-opacity 0.75)) . The last example can be abbreviated as :ink (make-opacity 0.75) . On a non-color, non-grayscale display this will usually turn into a stipple.

Drawing a faded but opaque version of the foreground color.
Specify :ink (compose-over (compose-in +foreground-ink+ (make-opacity 0.25)) +background-ink+) to draw at 25% of the normal contrast. On a non-color, non-grayscale display this will probably turn into a stipple.

Drawing a tiled pattern.
Specify :ink (make-rectangular-tile (make-pattern array colors )) .

Drawing a ``bitmap''.
Use (draw-design medium (make-pattern bit-array (list +background-ink+ +foreground-ink+)) :transformation (make-translation-transformation x y )) .

14.7 Design Protocol


Issue: SWM
The generic functions underlying the functions described in this and the preceding chapter will be documented later. This will allow for programmer-defined design classes. This also needs to describe how to decode designs into inks.



Drawing in Color Contents Index Extended Stream Output