Text Styles Contents Index Drawing in Color




12 Graphics

12.1 Overview of Graphics

The CLIM graphic drawing model is an idealized model of graphical pictures. The model provides the language that application programs use to describe the intended visual appearance of textual and graphical output. Usually not all of the contents of the screen are described using the graphic drawing model. For example, menus and scroll bars might be described in higher-level terms.

An important aspect of the CLIM graphic drawing model is its extreme device independence. The model describes ideal graphical images and ignores limitations of actual graphics devices. One consequence of this is that the actual visual appearance of the screen can only be an approximation of the appearance specified by the model. Another consequence of this is that the model is highly portable.

CLIM separates output into two layers, a text/graphics layer in which one specifies the desired visual appearance independent of device resolution and characteristics, and a rendering layer in which some approximation of the desired visual appearance is created on the device. Of course application programs can inquire about the device resolution and characteristics if they wish and modify their desired visual appearance on that basis. (There is also a third layer above these two layers, the adaptive toolkit layer where one specifies the desired functionality rather than the desired visual appearance.)


Issue: SWM
There are still no functions to ask about device resolution and characteristics. What characteristics do we need to be able to get to besides the obvious ones of resolution and ``color depth''. Also, do we really need to refer to the adaptive toolkit layer here?
CLIM's drawing functions provide convenient ways to draw several commonly-used shapes.

The interaction between graphics and output recording will be described in Chapter Output Recording .

12.2 Definitions

Drawing plane.
A drawing plane is an infinite two-dimensional plane on which graphical output occurs. The drawing plane contains an arrangement of colors and opacities that is modified by each graphical output operation. It is not possible to read back the contents of a drawing plane, except by examining the output-history. Normally each window has its own drawing plane.

Coordinates.
Coordinates are a pair of real numbers in implementation-defined units that identify a point in the drawing plane.

Sheets and Mediums.
In this chapter, we use a medium as a destination for output. The medium has a drawing plane, two designs called the medium's foreground and background, a transformation, a clipping region, a line style, and a text style. There are per-medium, dynamically scoped, default drawing options. Different medium classes are provided to allow programmers to draw on different sorts of devices, such as displays, printers, and virtual devices such as bitmaps.

Many sheets can be used for doing output, so the drawing functions can also take a sheet as the output argument. In this case, drawing function ``trampolines'' to the sheet's medium. So, while the functions defined here are specified to be called on sheets, they can also be called on sheets.

A stream is a special kind of sheet that implements the stream protocol; streams include additional state such as the current text cursor (which is some point in the drawing plane).

By default, the ``fundamental'' coordinate system of a CLIM stream (not a general sheet or medium, whose fundamental coordinate system is not defined) is a left handed system with x increasing to the right, and y increasing downward. (0,0) is at the upper left corner.

12.3 Drawing is Approximate

Note that although the drawing plane contains an infinite number of mathematical points, and drawing can be described as an infinite number of color and opacity computations, the drawing plane cannot be viewed directly and has no material existence. It is only an abstraction. What can be viewed directly is the result of rendering portions of the drawing plane onto a medium. No infinite computations or objects of infinite size are required to implement CLIM, because the results of rendering have finite size and finite resolution.

A drawing plane is described as having infinitely fine spatial, color, and opacity resolution, and as allowing coordinates of unbounded positive or negative magnitude. A viewport into a drawing plane, on the other hand, views only a finite region (usually rectangular) of the drawing plane. Furthermore, a viewport has limited spatial resolution and can only produce a limited number of colors. These limitations are imposed by the display hardware on which the viewport is displayed. A viewport also has limited opacity resolution, determined by the finite arithmetic used in the drawing engine (which may be hardware or software or both).

Coordinates are real numbers in implementation-defined units. Often these units equal the spatial resolution of a viewport, so that a line of thickness 1 is equivalent to the thinnest visible line. However, this equivalence is not required and should not be assumed by application programs.

A valid CLIM implementation can be quite restrictive in the size and resolution of its viewports. For example, the spatial resolution might be only a few dozen points per inch, the maximum size might be only a few hundred points on a side, and there could be as few as two displayable colors (usually black and white). The fully transparent and fully opaque opacity levels must always be supported, but a valid CLIM implementation might support only a few opacity levels in between (or possibly even 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.

When CLIM records the output to a sheet, there are no such limitations since CLIM just remembers the drawing operations that were performed, not the results of rendering.

CLIM provides some ways to ask what resolution limits are in effect for a medium. See Chapter Drawing Options for their descriptions.

The application programmer uses the CLIM graphic drawing model as an interface to describe the intended visual appearance. An implementation does its best to approximate that ideal appearance in a viewport, within its limitations of spatial resolution, color resolution, number of simultaneously displayable colors, and drawing speed. This will usually require tradeoffs, for example between speed and accuracy, and each implementation must make these tradeoffs according to its own hardware/software environment and user concerns. For example, if the actual device supports a limited number of colors, the desired color may be approximated by techniques such as dithering or stippling. If the actual device cannot draw curves exactly, they may be approximated, with or without anti-aliasing. If the actual device has limited opacity resolution, color blending may be approximate. A viewport might display colors that don't appear in the drawing plane, both because of color and opacity approximation and because of anti-aliasing at the edges of drawn shapes.

It is likely that different implementations will produce somewhat different visual appearance when running the same application. If an application requires more detailed control, it must resort to a lower-level interface, and will become less portable as a result. These lower-level interfaces will be documented on a per-platform basis.

Drawing computations are always carried out ``in color'', even if the viewport is only capable of displaying black and white. In other words, the CLIM drawing model is always the fully general model, even if an implementation's color resolution is limited enough that full use of the model is not possible. Of course an application that fundamentally depends on color will not work well on a viewport that cannot display color. Other applications will degrade gracefully.

Whether the implementation uses raster graphics or some other display technique is invisible at this interface. CLIM does not specify the existence of pixels nor the exact details of scan conversion, which will vary from one drawing engine to the next.

Performance will also vary between implementations. This interface is defined in terms of simple conceptual operations, however an actual implementation may use caching, specialized object representations, and other optimizations to avoid materializing storage-intensive or computation-costly intermediate results and to take advantage of available hardware.

12.4 Rendering Conventions for Geometric Shapes

The intent of this section is to describe the conventions for how CLIM should render a shape on a display device. These conventions and the accompanying examples are meant to describe a set of goals that a CLIM implementation should try to meet. However, compliant CLIM implementations may deviate from these goals if necessary (for example, if the rendering performance on a specific platform would be unacceptably slow if these goals were met exactly and implementors feel that users would be better served by speed than by accuracy). Note that we discuss only pixel-based display devices here, which are the most common, but by no means the only, sort of display device that can be supported by CLIM.

When CLIM draws a geometric shape on some sort of display device, the idealized geometric shape must somehow be rendered on the display device. The geometric shapes are made up of a set of mathematical points, which have no size; the rendering of the shape is usually composed of pixels, which are roughly square. These pixels exist in ``device coordinates'', which are gotten by transforming the user-supplied coordinates by all of the user-supplied transformation, the medium transformation, and the transformation that maps from the sheet to the display device. (Note that if the last transformation is a pure translation that translates by an integer multiple of device units, then it has no effect on the rendering other than placement of the figure drawn on the display device.)

Roughly speaking, a pixel is affected by drawing a shape only when it is inside the shape (we will define what we mean by ``inside'' in a moment). Since pixels are little squares and the abstract points have no size, for most shapes there will be many pixels that lie only partially inside the shape. Therefore, it is important to describe the conventions used by CLIM as to which pixels should be affected when drawing a shape, so that the proper interface to the per-platform rendering engine can be constructed. (It is worth noting that on devices that support color or grayscale, the rendering engine may attempt to draw a pixel that is partially inside the shape darker or lighter, depending on how much of it is inside the shape. This is called anti-aliasing .) The conventions used by CLIM is the same as the conventions used by X11:

It is important to note that these rules imply that the decision point used for insideness checking is offset from the point used for addressing the pixel by half a device unit in both the x and y directions. It is worth considering the motivations for these conventions.

When two shapes share a common edge, it is important that only one of the shapes own any pixel. The two triangles in Figure 12.1 illustrate this. The pixels along the diagonal belong to the lower figure. When the decision point of the pixel (its center) lies to one side of the line or the other, there is no issue. When the boundary passes through a decision point, which side the inside of the figure is on is used to decide. These are the triangles that CLIM implementations should attempt to draw in this case.

Figure 12.1: Pixel assignment with boundary on decision points.
The reason for choosing the decision point half a pixel offset from the address point is to reduce the number of common figures (such as rectilinear lines and rectangles with integral coordinates) that invoke the boundary condition rule. This usually leads to more symmetrical results. For instance, in Figure 12.2 , we see a circle drawn when the decision point is the same as the address point. The four lighter points are indeterminate: it is not clear whether they are inside or outside the shape. Since we want to have each boundary case determined according to which side has the figure on it, and since we must apply the same rule uniformly for all figures, we have no choice but to pick only two of the four points, leading to an undesirable lopsided figure.

Figure 12.2: Choosing any two of the shaded pixels causes asymmetry.
If we had instead chosen to take all four boundary points, we would have a nice symmetrical figure. However, since this figure is symmetrical about a whole pixel, it is one pixel wider than it ought to be. The problem with this can be seen clearly in Figure 12.3 if we attempt to draw a rectangle and circle overlaid with the following code:

(defun draw-test (medium radius)
  (draw-circle* medium 0 0 radius :ink +foreground-ink+)
  (draw-rectangle* medium (- radius) (- radius) (+ radius) (+ radius)
                   :ink +flipping-ink+))
Figure 12.3: Two forms of a circle inscribed in a rectangle.
It is for this reason that we choose to have the decision point at the center of the pixel. This draws circles that look like the one in Figure 12.4 . It is this shape that CLIM implementations should attempt to draw.

Figure 12.4: An aesthetically pleasing circle.
A consequence of these rendering conventions is that, when the start or end coordinate (minus 1/2 the line thickness, if the shape is a path) is not an integer, then rendering is not symmetric under reflection transformations. Thus to correctly and portably draw an outline of thickness 1 around a (rectilinear) rectangular area with integral coordinates, the outline path must have half-integral coordinates. Drawing rectilinear areas whose boundaries are not on pixel boundaries cannot be guaranteed to be portable. Another way to say the same thing is that the ``control points'' for a rectangular area are at the corners, while the control points for a rectilinear path are in the center of the path, not at the corners. Therefore, in order for a path and an area to abut seamlessly, the coordinates of the path must be offset from the coordinates of the area by half the path's thickness.

12.4.1 Permissible Alternatives During Rendering

Some platforms may distinguish between lines of the minimum thinness from lines that are thicker than that. The two rasterizations depicted in Figure 12.5 are both perfectly reasonable rasterizations of tilted lines that are a single device unit wide. The right-hand line is drawn as a tilted rectangle, the left as the ``thinnest visible'' line.

Figure 12.5: Two examples of lines of thickness 1.
For thick lines, a platform may choose to draw the exact tilted fractional rectangle, or the coordinates of that rectangle might be rounded so that it is distorted into another polygonal shape. The latter case may be prove to be faster on some platforms. The two rasterizations depicted in Figure 12.6 are both reasonable.

Figure 12.6: Two examples of lines of thickness 2.
The decision about which side of the shape to take when a boundary line passes through the decision point is made arbitrarily, although we have chosen to be compatible with the X11 definition. This is not necessarily the most convenient decision. The main problem with this is illustrated by the case of a horizontal line (see Figure 12.7 ). Our definition chooses to draw the rectangular slice above the coordinates, since those pixels are the ones whose centers have the figure immediately above them. This definition makes it simpler to draw rectilinear borders around rectilinear areas.

Figure 12.7: Two possible definitions of horizontal lines. Left figure is X11 definition.

12.5 Drawing Functions

Each drawing function takes keyword arguments allowing any drawing option or suboption to be supplied separately in the call to the function. In some implementations of CLIM, the drawing functions may ignore drawing options that are irrelevant to that function; in other implementations, an error may be signalled. See Chapter Drawing Options for a more complete discussion of the drawing options. An error will be signalled if any drawing function is called on a sheet that is mute for output.

While the functions in this section are specified to be called on mediums, they can also be called on sheets and streams. CLIM implementations will typically implement the method on a medium, and write a ``trampoline'' on the various sheet and stream classes that trampolines to the medium.

Implementation note: The drawing functions are all specified as ordinary functions, not as generic functions. This is intended to ease the task of writing compile-time optimizations that avoid keyword argument taking, check for such things as constant drawing options, and so forth. If you need to specialize any of the drawing methods, use define-graphics-method .

Each drawing function comes in two forms, a ``structured'' version and a ``spread'' version. The structured version passes points, whereas the spread version passes coordinates. See Section ``Spread'' Point Arguments to Functions for more information on this.

Any drawing functions may create an output record that corresponds to the figure being drawn. See Chapter Extended Stream Output for a complete discussion of output recording. During output recording, none of these functions capture any arguments that are points, point sequences, coordinate sequences, or text strings. Line styles, text styles, transformations, and clipping regions may be captured.

Note that the CLIM specification does not specify more complex shapes such as cubic splines and B'ezier curves. These are suitable candidates for extensions to CLIM.

12.5.1 Basic Drawing Functions

draw-pointmedium point &key ink clipping-region transformation line-style line-thickness line-unit[Function]
draw-point*medium x y &key ink clipping-region transformation line-style line-thickness line-unit[Function]
These functions (structured and spread arguments, respectively) draw a single point on the medium medium at the point point (or the position (x,y)).

The unit and thickness components of the current line style (see Chapter Drawing Options ) affect the drawing of the point by controlling the size on the display device of the ``blob'' that is used to render the point.

draw-pointsmedium points &key ink clipping-region transformation line-style line-thickness line-unit[Function]
draw-points*medium position-seq &key ink clipping-region transformation line-style line-thickness line-unit[Function]
These functions (structured and spread arguments, respectively) draw a set of points on the medium medium . points is a sequence of point objects; position-seq is a sequence of coordinate pairs, which are real numbers. It is an error if position-seq does not contain an even number of elements.

Ignoring the drawing options, these functions exist as equivalents to

(map nil #`(lambda (point) (draw-point medium point)) points)
and
(do ((i 0 (+ i 2)))
    ((= i (length position-seq)))
  (draw-point* medium (elt position-seq i) (elt position-seq (+ i 1))))
for convenience and efficiency.

draw-linemedium point1 point2 &key ink clipping-region transformation line-style line-thickness line-unit line-dashes line-cap-shape[Function]
draw-line*medium x1 y1 x2 y2 &key ink clipping-region transformation line-style line-thickness line-unit line-dashes line-cap-shape[Function]
These functions (structured and spread arguments, respectively) draw a line segment on the medium medium from the point point1 to point2 (or from the position (x1 ,y1 ) to (x2 ,y2 )).

The current line style (see Chapter Drawing Options ) affects the drawing of the line in the obvious way, except that the joint shape has no effect. Dashed lines start dashing at point1 .

draw-linesmedium points &key ink clipping-region transformation line-style line-thickness line-unit line-dashes line-cap-shape[Function]
draw-lines*medium position-seq &key ink clipping-region transformation line-style line-thickness line-unit line-dashes line-cap-shape[Function]
These functions (structured and spread arguments, respectively) draw a set of disconnected line segments. points is a sequence of point objects; position-seq is a sequence of coordinate pairs. It is an error if position-seq does not contain an even number of elements.

Ignoring the drawing options, these functions are equivalent to

(do ((i 0 (+ i 2)))
    ((= i (length points)))
  (draw-line medium (elt points i) (elt points (1+ i))))
and
(do ((i 0 (+ i 4)))
    ((= i (length position-seq)))
  (draw-line* medium (elt position-seq i)       (elt position-seq (+ i 1))
                     (elt position-seq (+ i 2)) (elt position-seq (+ i 3))))
draw-polygonmedium point-seq &key (filled t ) (closed t ) ink clipping-region transformation line-style line-thickness line-unit line-dashes line-joint-shape line-cap-shape[Function]
draw-polygon*medium coord-seq &key (filled t ) (closed t ) ink clipping-region transformation line-style line-thickness line-unit line-dashes line-joint-shape line-cap-shape[Function]
Draws a polygon or polyline on the medium medium . When filled is false , this draws a set of connected lines, otherwise it draws a filled polygon. If closed is true (the default) and filled is false , it ensures that a segment is drawn that connects the ending point of the last segment to the starting point of the first segment. The current line style (see Chapter Drawing Options ) affects the drawing of unfilled polygons in the obvious way. The cap shape affects only the ``open'' vertices in the case when closed is false . Dashed lines start dashing at the starting point of the first segment, and may or may not continue dashing across vertices, depending on the window system.

point-seq is a sequence of point objects; coord-seq is a sequence of coordinate pairs. It is an error if coord-seq does not contain an even number of elements.

If filled is true , a closed polygon is drawn and filled in. In this case, closed is assumed to be true as well.

draw-rectanglemedium point1 point2 &key (filled t ) ink clipping-region transformation line-style line-thickness line-unit line-dashes line-joint-shape[Function]
draw-rectangle*medium x1 y1 x2 y2 &key (filled t ) ink clipping-region transformation line-style line-thickness line-unit line-dashes line-joint-shape[Function]
Draws either a filled or unfilled rectangle on the medium medium that has its sides aligned with the coordinate axes of the native coordinate system. One corner of the rectangle is at the position (x1 ,y1 ) and the opposite corner is at (x2 ,y2 ). The arguments x1 , y1 , x2 , and y1 are real numbers that are canonicalized in the same way as for make-bounding-rectangle . filled is as for draw-polygon* .

The current line style (see Chapter Drawing Options ) affects the drawing of unfilled rectangles in the obvious way, except that the cap shape has no effect.

draw-rectanglesmedium points &key ink clipping-region transformation line-style line-thickness line-unit line-dashes line-joint-shape[Function]
draw-rectangles*medium position-seq &key ink clipping-region transformation line-style line-thickness line-unit line-dashes line-joint-shape[Function]
These functions (structured and spread arguments, respectively) draw a set of rectangles. points is a sequence of point objects; position-seq is a sequence of coordinate pairs. It is an error if position-seq does not contain an even number of elements.

Ignoring the drawing options, these functions are equivalent to

(do ((i 0 (+ i 2)))
    ((= i (length points)))
  (draw-rectangle medium (elt points i) (elt points (1+ i))))
and
(do ((i 0 (+ i 4)))
    ((= i (length position-seq)))
  (draw-rectangle* medium (elt position-seq i)       (elt position-seq (+ i 1))
                          (elt position-seq (+ i 2)) (elt position-seq (+ i 3))))
draw-ellipsemedium center-pt radius-1-dx radius-1-dy radius-2-dx radius-2-dy &key (filled t ) start-angle end-angle ink clipping-region transformation line-style line-thickness line-unit line-dashes line-cap-shape[Function]
draw-ellipse*medium center-x center-y radius-1-dx radius-1-dy radius-2-dx radius-2-dy &key (filled t ) start-angle end-angle ink clipping-region transformation line-style line-thickness line-unit line-dashes line-cap-shape[Function]
These functions (structured and spread arguments, respectively) draw an ellipse (when filled is true , the default) or an elliptical arc (when filled is false ) on the medium medium . The center of the ellipse is the point center-pt (or the position (center-x ,center-y )).

Two vectors, (radius-1-dx ,radius-1-dy ) and (radius-2-dx ,radius-2-dy ) specify the bounding parallelogram of the ellipse as explained in Chapter Regions . All of the radii are real numbers. If the two vectors are collinear, the ellipse is not well-defined and the ellipse-not-well-defined error will be signalled. The special case of an ellipse with its major axes aligned with the coordinate axes can be obtained by setting both radius-1-dy and radius-2-dx to 0.

start-angle and end-angle are real numbers that specify an arc rather than a complete ellipse. Angles are measured with respect to the positive x axis. The elliptical arc runs positively (counter-clockwise) from start-angle to end-angle . The default for start-angle is 0; the default for end-angle is 2pi .

In the case of a ``filled arc'' (that is when filled is true and start-angle or end-angle are supplied and are not 0 and 2pi ), the figure drawn is the ``pie slice'' area swept out by a line from the center of the ellipse to a point on the boundary as the boundary point moves from start-angle to end-angle .

When drawing unfilled ellipses, the current line style (see Chapter Drawing Options ) affects the drawing in the obvious way, except that the joint shape has no effect. Dashed elliptical arcs start ``dashing'' at start-angle .

draw-circlemedium center-pt radius &key (filled t ) start-angle end-angle ink clipping-region transformation line-style line-thickness line-unit line-dashes line-cap-shape[Function]
draw-circle*medium center-x center-y radius &key (filled t ) start-angle end-angle ink clipping-region transformation line-style line-thickness line-unit line-dashes line-cap-shape[Function]
These functions (structured and spread arguments, respectively) draw a circle (when filled is true , the default) or a circular arc (when filled is false ) on the medium medium . The center of the circle is center-pt or (center-x ,center-y ) and the radius is radius . These are just special cases of draw-ellipse and draw-ellipse* . filled is as for draw-ellipse* .

start-angle and end-angle allow the specification of an arc rather than a complete circle in the same manner as that of the ellipse functions, above.

The ``filled arc'' behavior is the same as that of an ellipse, above.

draw-textmedium string-or-char point &key text-style (start 0 ) end (align-x :left ) (align-y :baseline ) toward-point transform-glyphs ink clipping-region transformation text-style text-family text-face text-size[Function]
draw-text*medium string-or-char x y &key text-style (start 0 ) end (align-x :left ) (align-y :baseline ) toward-x toward-y transform-glyphs ink clipping-region transformation text-style text-family text-face text-size[Function]
The text specified by string-or-char is drawn on the medium medium starting at the position specified by the point point (or the position (x,y)). The exact definition of ``starting at'' is dependent on align-x and align-y . align-x is one of :left , :center , or :right . align-y is one of :baseline , :top , :center , or :bottom . align-x defaults to :left and align-y defaults to :baseline ; with these defaults, the first glyph is drawn with its left edge and its baseline at point .

text-style defaults to nil , meaning that the text will be drawn using the current text style of the medium.

start and end specify the start and end of the string, in the case where string-or-char is a string. If start is supplied, it must be an integer that is less than the length of the string. If end is supplied, it must be an integer that is less than the length of the string, but greater than or equal to start .

Normally, glyphs are drawn from left to right no matter what transformation is in effect. toward-x or toward-y (derived from toward-point in the case of draw-text ) can be used to change the direction from one glyph to the next one. For example, if toward-x is less than the x position of point , then the glyphs will be drawn from right to left. If toward-y is greater than the y position of point , then the glyphs' baselines will be positioned one above another. More precisely, the reference point in each glyph lies on a line from point to toward-point , and the spacing of each glyph is determined by packing rectangles along that line, where each rectangle is ``char-width'' wide and ``char-height'' high.

If transform-glyphs is true , then each glyph is transformed as an image before it is drawn. That is, if a rotation transformation is in effect, then each glyph will be rotated individually. If transform-glyphs is not supplied, then the individual glyphs are not subject to the current transformation. It is permissible for CLIM implementations to ignore transform-glyphs if it is too expensive to implement.

12.5.2 Compound Drawing Functions

CLIM also provides a few compound drawing functions. The compound drawing functions could be composed by a programmer from the basic drawing functions, but are provided by CLIM because they are commonly used.

draw-arrowmedium point-1 point-2 &key ink clipping-region transformation line-style line-thickness line-unit line-dashes line-cap-shapeto-head from-head head-length head-width[Function]
draw-arrow*medium x1 y1 x2 y2 &key ink clipping-region transformation line-style line-thickness line-unit line-dashes line-cap-shapefrom-head to-head head-length head-width[Function]
These functions (structured and spread arguments, respectively) draw a line segment on the medium medium from the point point1 to point2 (or from the position (x1 ,y1 ) to (x2 ,y2 )). If to-head is true (the default), then the ``to'' end of the line is capped by an arrowhead. If from-head is true (the default is false ), then the ``from'' end of the line is capped by an arrowhead. The arrowhead has length head-length (default 10) and width head-width (default 5).

The current line style (see Chapter Drawing Options ) affects the drawing of the line portion of the arrow in the obvious way, except that the joint shape has no effect. Dashed arrows start dashing at point1 .

draw-ovalmedium center-pt x-radius y-radius &key (filled t ) ink clipping-region transformation line-style line-thickness line-unit line-dashes line-cap-shape[Function]
draw-oval*medium center-x center-y x-radius y-radius &key (filled t ) ink clipping-region transformation line-style line-thickness line-unit line-dashes line-cap-shape[Function]
These functions (structured and spread arguments, respectively) draw a filled or unfilled oval (that is, a ``race-track'' shape) on the medium medium . The oval is centered on center-pt (or (center-x ,center-y )). If x-radius or y-radius is 0, then a circle is drawn with the specified non-zero radius. Other, a figure is drawn that results from drawing a rectangle with dimension x-radius by y-radius , and the replacing the two short sides with a semicircular arc of the appropriate size.

12.6 Pixmaps

A pixmap can be thought of as an ``off-screen window'', that is, a medium that can be used for graphical output, but is not visible on any display device. Pixmaps are provided to allow a programmer to generate a piece of output associated with some display device that can then be rapidly drawn on a real display device. For example, an electrical CAD system might generate a pixmap that corresponds to a complex, frequently used part in a VLSI schematic, and then use copy-from-pixmap to draw the part as needed.

The exact representation of a pixmap is explicitly unspecified. There is no interaction between the pixmap operations and output recording, that is, displaying a pixmap on a sheet or medium is a pure drawing operation that affects only the display, not the output history. Some mediums may not support pixmaps; in this case, an error will be signalled.

allocate-pixmapmedium width height[Generic function]
Allocates and returns a pixmap object that can be used on any medium that shares the same characteristics as medium . (The exact definition of ``shared characteristics'' will vary from host to host.) medium can be a medium, a sheet, or a stream.

The resulting pixmap will be at least width units wide, height units high, and as deep as is necessary to store the information for the medium. The exact representation of pixmaps is explicitly unspecified.

The returned value is the pixmap.

deallocate-pixmappixmap[Generic function]
Deallocates the pixmap pixmap .

pixmap-widthpixmap[Generic function]
pixmap-heightpixmap[Generic function]
pixmap-depthpixmap[Generic function]
These functions return, respectively, the width, height, and depth of the pixmap pixmap . These values may be different from the programmer-specified values, since some window systems need to allocate pixmaps only of particular sizes.

copy-to-pixmapmedium medium-x medium-y width height &optional pixmap (pixmap-x 0 ) (pixmap-y 0 )[Function]
Copies the pixels from the medium medium starting at the position specified by (medium-x ,medium-y ) into the pixmap pixmap at the position specified by (pixmap-x ,pixmap-y ). A rectangle whose width and height is specified by width and height is copied. medium-x and medium-y are specified in user coordinates. (If medium is a medium or a stream, then medium-x and medium-y are transformed by the user transformation.) The copying must be done by medium-copy-copy .

If pixmap is not supplied, a new pixmap will be allocated. Otherwise, pixmap must be an object returned by allocate-pixmap that has the appropriate characteristics for medium .

The returned value is the pixmap.

copy-from-pixmappixmap pixmap-x pixmap-y width height medium medium-x medium-y[Function]
Copies the pixels from the pixmap pixmap starting at the position specified by (pixmap-x ,pixmap-y ) into the medium medium at the position (medium-x ,medium-y ). A rectangle whose width and height is specified by width and height is copied. medium-x and medium-y are specified in user coordinates. (If medium is a medium or a stream, then medium-x and medium-y are transformed by the user transformation.) The copying must be done by medium-copy-copy .

pixmap must be an object returned by allocate-pixmap that has the appropriate characteristics for medium .

The returned value is the pixmap.

copy-areamedium from-x from-y width height to-x to-y[Generic function]
Copies the pixels from the medium medium starting at the position specified by (from-x ,from-y ) to the position (to-x ,to-y ) on the same medium. A rectangle whose width and height is specified by width and height is copied. from-x , from-y , to-x , and to-y are specified in user coordinates. (If medium is a medium or a stream, then the x and y values are transformed by the user transformation.) The copying must be done by medium-copy-copy .

medium-copy-areafrom-drawable from-x from-y width height to-drawable to-x to-y[Generic function]
Copies the pixels from the source drawable from-drawable at the position (from-x ,from-y ) to the destination drawable to-drawable at the position (to-x ,to-y ). A rectangle whose width and height is specified by width and height is copied. from-x , from-y , to-x , and to-y are specified in user coordinates. The x and y are transformed by the user transformation.

This is intended to specialize on both the from-drawable and to-drawable arguments. from-drawable and to-drawable may be either mediums or pixmaps.

with-output-to-pixmap(medium-var medium &key width height) &body body[Macro]
Binds medium-var to a ``pixmap medium'', that is, a medium that does output to a pixmap with the characteristics appropriate to the medium medium , and then evaluates body in that context. All the output done to the medium designated by medium-var inside of body is drawn on the pixmap stream. The pixmap medium must support the medium output protocol, including all of the graphics function. CLIM implementations are permitted, but not required, to have pixmap mediums support the stream output protocol (write-char and write-string ).

width and height are integers that give the width and height of the pixmap. If they are unsupplied, the result pixmap will be large enough to contain all of the output done by body .

medium-var must be a symbol; it is not evaluated.

The returned value is a pixmap that can be drawn onto medium using copy-from-pixmap .

12.7 Graphics Protocols

Every medium must implement methods for the various graphical drawing generic functions. Furthermore, every sheet that supports the standard output protocol must implement these methods as well; often, the sheet methods will trampoline to the methods on the sheet's medium. All of these generic functions take the same arguments as the non-generic spread function equivalents, except the arguments that are keyword arguments in the non-generic functions are positional arguments in the generic functions.

Every medium must implement methods for the various graphical drawing generic functions. All of these generic functions take as (specialized) arguments the medium, followed by the drawing function-specific arguments, followed by the ink, line style (or text style), and clipping region.

The drawing function-specific arguments will either be x and y positions, or a sequence of x and y positions. These positions will be in medium coordinates, and must be transformed by applying the medium's device transformation in order to produce device coordinates. Note that the user transformation will have already been applied to the positions when the medium-specific drawing function is called. However, the medium-specific drawing function will still need to apply the device transformation to the positions in order to draw the graphics in the appopriate place on the host window.

The ink, line style, text style, and clipping regions arguments are not part of the medium-specific drawing functions. They must be extracted from the medium object. Each medium-specific method will decode the ink, line (or text) style, and clipping region in a port-specific way and communicate it to the underlying port.

12.7.1 General Behavior of Drawing Functions

Using draw-line* as an example, calling any of the drawing functions specified above results in the following series of function calls on a non-output recording sheet:

12.7.2 Medium-specific Drawing Functions

All mediums and all sheets that support the standard output protocol must implement methods for the following generic functions.

The method for each of these drawing functions on the most specific, implementation-dependent medium class will transform the coordinates by the device transformation of the medium's sheet, extract the medium's port-specific ``drawable'', and then invoke a port-specific drawing function (such as xlib:draw-line ) to do the actual drawing.

An :around on basic-medium for each of the drawing functions will have already transformed the user coordinates to medium coordinates before the most specific, implementation-dependent method is called.

Implementation note: CLIM implementations should provide ``trampoline'' methods on sheets that support the standard output protocol that simply call the same generic function on the medium. Sheets that support output recording will require extra mechanism before delegating to the medium in order to implement such functionality as creating output records and handling scrolling.

medium-draw-point*medium x y[Generic function]
Draws a point on the medium medium .

medium-draw-points*medium coord-seq[Generic function]
Draws a set of points on the medium medium . coord-seq is a sequence of coordinate pairs, which are real numbers. It is an error if coord-seq does not contain an even number of elements.

medium-draw-line*medium x1 y1 x2 y2[Generic function]
Draws a line on the medium medium . The line is drawn from (x1,y1) to (x2,y2).

medium-draw-lines*stream position-seq[Generic function]
Draws a set of disconnected lines on the medium medium . coord-seq is a sequence of coordinate pairs, which are real numbers. Each successive pair of coordinate pairs is taken as the start and end position of each line. It is an error if coord-seq does not contain an even number of elements.

medium-draw-polygon*medium coord-seq closed[Generic function]
Draws a polygon or polyline on the medium medium . coord-seq is a sequence of coordinate pairs, which are real numbers. It is an error if coord-seq does not contain an even number of elements. Each successive coordinate pair is taken as the position of one vertex of the polygon.

medium-draw-rectangle*medium x1 y1 x2 y2[Generic function]
Draws a rectangle on the medium medium . The corners of the rectangle are at (x1,y1) and (x2,y2).

medium-draw-rectangles*medium coord-seq[Generic function]
Draws a set of rectangles on the medium medium . coord-seq is a sequence of coordinate pairs, which are real numbers. It is an error if coord-seq does not contain an even number of elements. Each successive pair of coordinate pairs is taken as the upper-left and lower-right corner of the rectangle.

medium-draw-ellipse*medium center-x center-y radius-1-dx radius-1-dy radius-2-dx radius-2-dy start-angle end-angle[Generic function]
Draws an ellipse or elliptical arc on the medium medium . The center of the ellipse is at (x,y), and the radii are specified by the two vectors (radius-1-dx ,radius-1-dy ) and (radius-2-dx ,radius-2-dy ).

start-angle and end-angle are real numbers that specify an arc rather than a complete ellipse. Note that the medium and device transformations must be applied to the angles as well.

medium-draw-text*medium text x y (start 0 ) end (align-x :left ) (align-y :baseline ) toward-x toward-y transform-glyphs[Generic function]
Draws a character or a string on the medium medium . The text is drawn starting at (x,y), and towards (toward-x ,toward-y ). In Some implementations of CLIM, medium-draw-text* may call either medium-draw-string* or medium-draw-character* in order to draw the text.

12.7.3 Other Medium-specific Output Functions

medium-finish-outputmedium[Generic function]
Ensures that all the output sent to medium has reached its destination, and only then return false . This is used by finish-output .

medium-force-outputmedium[Generic function]
Like medium-finish-output , except that it may return false without waiting for the output to complete. This is used by force-output .

medium-clear-areamedium left top right bottom[Generic function]
Clears an area on the medium medium by filling the rectangle whose edges are at left , top , right , and bottom with the medium's background ink. left , top , right , and bottom are in thed medium's coordinate system.

The default method on basic-medium simply uses draw-rectangle* to clear the area. Some host window systems has special functions that are faster than draw-rectangle* .

medium-beepmedium[Generic function]
Causes an audible sound to be played on the medium. The default method does nothing.




Text Styles Contents Index Drawing in Color