3.3.2 Object-drawing functions

The following are the “drawing functions” in (plotutils plot). When invoked on a Plotter, these functions cause it to draw objects (paths, text strings, marker symbols, and points [i.e., pixels]) on the associated graphics display.

Paths may be simple or compound. A simple path is a sequence of contiguous line segments, arc segments (either circular or elliptic), and/or Bezier curve segments (either quadratic or cubic). Such simple paths are drawn incrementally, one segment at a time. A simple path may also be a circle, rectangle, or ellipse. A compound path consists of multiple simple paths, which must be nested.

You do not need to begin a path by calling any special function. You should, at least in theory, end a path under construction, and request that it be drawn on the graphics display, by calling endpath!. But the endpath! function is automatically called when any other object is drawn, and at the end of each page of graphics. It is also called automatically when any path-related attribute is changed: for example, when move! is called to change the graphics cursor position. So endpath! seldom needs to be invoked explicitly.

When drawing a compound path, you would end each of its constituent simple paths by calling endsubpath!, and the compound path as a whole by calling endpath!. After each call to endsubpath!, you are allowed to call move! to reposition the graphics cursor, prior to beginning the next simple path. Such a call to move! will not automatically invoke endpath!. This is an exception to the above rule.

In the current Guile binding, each of these functions takes a pointer to a <plotter> as its first argument.

Procedure: alabel! plotter horiz-justify vert-justify s

alabel! takes three arguments horiz_justify (a symbol), vert_justify (a symbol), and s (a string), which specify an ‘adjusted label,’ i.e., a justified text string. The path under construction (if any) is ended and drawn, as if endpath had been called, and the string s is drawn according to the specified justifications. If horiz_justify is equal to the symbols ‘l’, ‘c’, or ‘r’, then the string will be drawn with left, center or right justification, relative to the current graphics cursor position. If vert_justify is equal to symbols ‘b’, ‘x’, ‘c’, ‘C’, or ‘t’, then the bottom, baseline, center, cap line, or top of the string will be placed even with the current graphics cursor position. The graphics cursor is moved to the right end of the string if left justification is specified, and to the left end if right justification is specified.

The string may contain escape sequences of various sorts (see Text String Format), though it should not contain line feeds or carriage returns. In fact it should include only printable characters, from the byte ranges 0x200x7e and 0xa00xff. The string may be plotted at a nonzero angle, if textangle has been called.

Procedure: arc! plotter xc yc x0 y0 x1 y1
Procedure: arcrel! plotter xc yc x0 y0 x1 y1

arc! takes six arguments specifying the beginning (x0, y0), end (x1, y1), and center (xc, yc) of a circular arc. If the graphics cursor is at (x0, y0) and a path is under construction, then the arc is added to the path. Otherwise the current path (if any) is ended and drawn, as if endpath had been called, and the arc begins a new path. In all cases the graphics cursor is moved to (x1, y1).

The direction of the arc (clockwise or counterclockwise) is determined by the convention that the arc, centered at (xc, yc), sweep through an angle of at most 180 degrees. If the three points appear to be collinear, the direction is taken to be counterclockwise. If (xc, yc) is not equidistant from (x0, y0) and (x1, y1) as it should be, it is corrected by being moved to the closest point on the perpendicular bisector of the line segment joining (x0, y0) and (x1, y1). arcrel and farcrel are similar to arc and farc, but use cursor-relative coordinates.

Procedure: bezier2! plotter x0 y0 x1 y1 x2 y2
Procedure: bezier2rel! plotter x0 y0 x1 y1 x2 y2

bezier2! takes six arguments specifying the beginning p0=(x0, y0) and end p2=(x2, y2) of a quadratic Bezier curve, and its intermediate control point p1=(x1, y1). If the graphics cursor is at p0 and a path is under construction, then the curve is added to the path. Otherwise the current path (if any) is ended and drawn, as if endpath! had been called, and the curve begins a new path. In all cases the graphics cursor is moved to p2. bezier2rel! are similar to bezier2! but use cursor-relative coordinates.

The quadratic Bezier curve is tangent at p0 to the line segment joining p0 to p1, and is tangent at p2 to the line segment joining p1 to p2. So it fits snugly into a triangle with vertices p0, p1, and p2.

When using a PCL Plotter to draw Bezier curves on a LaserJet III, you should set the parameter PCL_BEZIERS to "no". That is because the LaserJet III, which was Hewlett–Packard’s first PCL 5 printer, does not recognize the Bezier instructions supported by later PCL 5 printers. See Plotter parameters.

Procedure: bezier3! plotter x0 y0 x1 y1 x2 y2 x3 y3
Procedure: bezier3rel! plotter x0 y0 x1 y1 x2 y2 x3 y3

bezier3! take eight arguments specifying the beginning p0=(x0, y0) and end p3=(x3, y3) of a cubic Bezier curve, and its intermediate control points p1=(x1, y1) and p2=(x2, y2). If the graphics cursor is at p0 and a path is under construction, then the curve is added to the path. Otherwise the current path (if any) is ended and drawn, as if endpath! had been called, and the curve begins a new path. In all cases the graphics cursor is moved to p3. bezier3rel! are similar to bezier3!, but use cursor-relative coordinates.

The cubic Bezier curve is tangent at p0 to the line segment joining p0 to p1, and is tangent at p3 to the line segment joining p2 to p3. So it fits snugly into a quadrangle with vertices p0, p1, p2, and p3.

When using a PCL Plotter to draw Bezier curves on a LaserJet III, you should set the parameter PCL_BEZIERS to "no". That is because the LaserJet III, which was Hewlett–Packard’s first PCL 5 printer, does not recognize the Bezier instructions supported by later PCL 5 printers. See Plotter parameters.

Procedure: box! plotter x1 y1 x2 y2
Procedure: boxrel! plotter x1 y1 x2 y2

box! takes four arguments specifying the starting corner (x1, y1) and opposite corner (x2, y2) of a ‘box’, or rectangle. The path under construction (if any) is ended, and the box is drawn as a new path. This path is also ended, and the graphics cursor is moved to the midpoint of the box. boxrel! is similar to box!, but use cursor-relative coordinates.

Procedure: circle! plotter xc yc r
Procedure: circlerel! plotter xc yc r

circle! takes three arguments specifying the center (xc, yc) and radius (r) of a circle. The path under construction (if any) is ended, and the circle is drawn as a new path. This path is also ended, and the graphics cursor is moved to (xc, yc). circlerel! is similar to circle!, but uses cursor-relative coordinates for xc and yc.

Procedure: cont! plotter x y
Procedure: contrel! plotter x y

cont! take two arguments specifying the coordinates (x, y) of a point. If a path is under construction, the line segment from the current graphics cursor position to the point (x, y) is added to it. Otherwise the line segment begins a new path. In all cases the graphics cursor is moved to (x, y). contrel! is similar to cont!, but uses cursor-relative coordinates.

Procedure: ellarc! plotter xc yc x0 y0 x1 y1
Procedure: ellarcrel! plotter xc yc x0 y1 x1 y1

ellarc! takes six arguments specifying the three points pc=(xc,yc), p0=(x0,y0), and p1=(x1,y1) that define a so-called quarter ellipse. This is an elliptic arc from p0 to p1 with center pc. If the graphics cursor is at point p0 and a path is under construction, the quarter-ellipse is added to it. Otherwise the path under construction (if any) is ended and drawn, as if endpath had been called, and the quarter-ellipse begins a new path. In all cases the graphics cursor is moved to p1.

The quarter-ellipse is an affinely transformed version of a quarter circle. It is drawn so as to have control points p0, p1, and p0+p1-pc. This means that it is tangent at p0 to the line segment joining p0 to p0+p1-pc, and is tangent at p1 to the line segment joining p1 to p0+p1-pc. So it fits snugly into a triangle with these three control points as vertices. Notice that the third control point is the reflection of pc through the line joining p0 and p1. ellarcrel!is similar to ellarc! and fellarc, but use cursor-relative coordinates.

Procedure: ellipse! plotter xc yc rx ry angle
Procedure: ellipserel! plotter xc yc rx ry angle

ellipse! takes five arguments specifying the center (xc, yc) of an ellipse, the lengths of its semiaxes (rx and ry), and the inclination of the first semiaxis in the counterclockwise direction from the x axis in the user coordinate system. The path under construction (if any) is ended, and the ellipse is drawn as a new path. This path is also ended, and the graphics cursor is moved to (xc, yc). ellipserel! is similar to ellipse!, but uses cursor-relative coordinates.

Procedure: endpath! plotter

endpath! terminates the path under construction, if any, and draws it. It also removes the path from the current graphics context, so that a new path may be constructed.

The path under construction may be a simple path, or a compound path constructed with the aid of endsubpath! (see below). A simple path is constructed by one or more successive calls to cont!, line1, arc!, ellarc!, bezier2!, bezier3!. A simple path may also be constructed by a single call to circle!, ellipse!, or box!.

It is often not necessary to call endpath! explicitly, since it is frequently called automatically. It will be called if any non-path object is drawn, if any path-related drawing attribute is set, or if move or fmove is invoked to set the cursor position. It will also be called if restorestate is called to pop a graphics context off the stack, and if closepl is called to end a page of graphics. So it is seldom necessary to call endpath explicitly. However, if a Plotter plots objects in real time, calling endpath will ensure that a completed path is drawn on the graphics display without delay.

Procedure: endsubpath! plotter

endsubpath! terminates the simple path under construction, if any, and signals that the construction of the next simple path in a compound path is to begin. Immediately after endsubpath! is called, it is permissible to call move! to reposition the graphics cursor. (At other times in the drawing of a compound path, calling move! would force a premature end to the path, by automatically invoking endpath!.)

Procedure: label! plotter s

label! takes a single string argument s and draws the text contained in s at the current graphics cursor position. The text is left justified, and the graphics cursor is moved to the right end of the string. This function is provided for backward compatibility; the function call label!(s) is equivalent to alabel!(‘l’,‘x’,s).

Procedure: labelwidth! plotter s

labelwidth! is not really an object-drawing function: it is a query functions. It computes and returns the width of a string in the current font, in the user coordinate system. The string is not drawn.

Procedure: line! plotter x1 y1 x2 y2
Procedure: linerel! plotter x1 y1 x2 y2

line! takes four arguments specifying the start point (x1, y1) and end point (x2, y2) of a line segment. If the graphics cursor is at (x1, y1) and a path is under construction, the line segment is added to it. Otherwise the path under construction (if any) is ended and drawn, as if endpath had been called, and the line segment begins a new path. In all cases the graphics cursor is moved to (x2, y2). linerel! is similar to line!, but use cursor-relative coordinates.

Procedure: marker! plotter x y type size
Procedure: markerrel! plotter x y type size

marker! takes four arguments specifying the position (x,y) of a marker symbol, its type, and its font size in user coordinates. The path under construction (if any) is ended and drawn, as if endpath! had been called, and the marker symbol is plotted. The graphics cursor is moved to (x,y). markerrel! are similar to marker! and fmarker, but use cursor-relative coordinates for the position (x,y).

A marker symbol is a visual representation of a point, which is visible on all types of Plotter. In this it differs from the points produced by the point! function (see below). Marker symbol types 0…31 are taken from a standard set, and marker symbol types 32 and above are interpreted as the index of a character in the current text font. See Available marker symbols.

Procedure: point! plotter x y
Procedure: pointrel! plotter x y

point! takes two arguments specifying the coordinates (x, y) of a point. The path under construction (if any) is ended and drawn, as if endpath! had been called, and the point is plotted. The graphics cursor is moved to (x, y). pointrel! is similar to point!, but use cursor-relative coordinates.

‘Point’ is a misnomer. Any Plotter that produces a bitmap, i.e., an X Plotter, an X Drawable Plotter, a PNG Plotter, a PNM Plotter, or a GIF Plotter, draws a point as a single pixel. Most other Plotters draw a point as a small solid circle, usually so small as to be invisible. So point should really be called pixel.