DRAW-IMAGE(2) DRAW-IMAGE(2)
NAME
Image - pictures and drawing
SYNOPSIS
include "draw.m";
draw := load Draw Draw->PATH;
Image: adt
{
r: Rect;
clipr: Rect;
ldepth: int;
repl: int;
display: ref Display;
screen: ref Screen;
draw: fn(dst: self ref Image, r: Rect, src: ref Image,
mask: ref Image, p: Point);
gendraw: fn(dst: self ref Image, r: Rect, src: ref Image,
p0: Point, mask: ref Image, p1: Point);
line: fn(dst: self ref Image, p0,p1: Point,
end0,end1,thick: int, src: ref Image, sp: Point);
poly: fn(dst: self ref Image, p: array of Point,
end0,end1,thick: int, src: ref Image, sp: Point);
bezspline: fn(dst: self ref Image, p: array of Point,
end0,end1,thick: int, src: ref Image, sp: Point);
fillpoly: fn(dst: self ref Image, p: array of Point,
wind: int, src: ref Image, sp: Point);
fillbezspline: fn(dst: self ref Image, p: array of Point,
wind: int, src: ref Image, sp: Point);
ellipse: fn(dst: self ref Image, c: Point, a, b,
thick: int, src: ref Image, sp: Point);
fillellipse:fn(dst: self ref Image, c: Point, a, b: int,
src: ref Image, sp: Point);
bezier: fn(dst: self ref Image, a,b,c,d: Point,
end0,end1,thick: int, src: ref Image, sp: Point);
fillbezier: fn(dst: self ref Image, a,b,c,d: Point, wind:int,
src: ref Image, sp: Point);
arrow: fn(a,b,c: int): int;
text: fn(dst: self ref Image, p: Point, src: ref Image,
sp: Point, font: ref Font, str: string): Point;
readpixels: fn(src: self ref Image, r: Rect,
data: array of byte): int;
writepixels:fn(dst: self ref Image, r: Rect,
data: array of byte): int;
top: fn(win: self ref Image);
bottom: fn(win: self ref Image);
flush: fn(win: self ref Image, func: int);
origin: fn(win: self ref Image, log, scr: Point): int;
Page 1 Plan 9 (printed 10/23/25)
DRAW-IMAGE(2) DRAW-IMAGE(2)
};
DESCRIPTION
The Image type defines rectangular pictures and the methods
to draw upon them; it is also the building block for higher
level objects such as windows and fonts. In particular, a
window is represented as an Image; no special operators are
needed to draw on a window.
r The coordinates of the rectangle in the plane for
which the Image has defined pixel values. It
should not be modified after the image is created.
clipr The clipping rectangle: operations that read or
write the image will not access pixels outside
clipr. Frequently, clipr is the same as Image.r,
but it may differ; see in particular the discus-
sion of Image.repl. The clipping region may be
modified dynamically.
ldepth The log base 2 of the number of bits per pixel in
the picture: 0 for one bit per pixel, 3 for eight
bits per pixel, etc. The library supports
Image.ldepth values 0, 1, 2, and 3 only. The
value should not be modified after the image is
created.
repl A boolean value specifying whether the image is
tiled to cover the plane when used as a source for
a drawing operation. If Image.repl is zero, oper-
ations are restricted to the intersection of
Image.r and Image.clipr. If Image.repl is set,
Image.r defines the tile to be replicated and
Image.clipr defines the portion of the plane cov-
ered by the tiling, in other words, Image.r is
replicated to cover Image.clipr; in such cases
Image.r and Image.clipr are independent.
For example, a replicated image with Image.r set
to ((0, 0), (1, 1)) and Image.clipr set to
((0, 0), (100, 100)), with the single pixel of
Image.r set to blue, behaves identically to an
image with Image.r and Image.clipr both set to
((0, 0), (100, 100)) and all pixels set to blue.
However, the first image requires far less memory.
The replication flag may be modified dynamically
along with the clipping rectangle.
dst.draw(r, src, mask, p)
Draw is the standard drawing function. Only those
pixels within the intersection of dst.r and
dst.clipr will be affected; draw ignores dst.repl.
Page 2 Plan 9 (printed 10/23/25)
DRAW-IMAGE(2) DRAW-IMAGE(2)
The operation proceeds as follows:
1. If repl is set in src or mask, replicate
their contents to fill their clip rectangles.
2. Translate src and mask so p is aligned with
r.min.
3. Set r to the intersection of r and dst.r.
4. Intersect r with src.clipr. If src.repl is
false, also intersect r with src.r.
5. Intersect r with mask.clipr. If mask.repl is
false, also intersect r with mask.r.
6. For each location in r for which the mask
pixel is non-zero, set the dst pixel to be
the value of the src pixel.
The various ldepth values involved need not be
identical. If the src or mask images are single
replicated pixels, any ldepth is fine. Otherwise,
if their ldepth is not the same as the destina-
tion, they must have ldepth value 0. For draw and
gendraw only, if mask is nil, a mask of all ones
is used. These restrictions may weaken in later
implementations.
display Tells on which display the image resides.
screen If the image is a window on a Screen (see draw-
screen(2)), this field refers to that screen; oth-
erwise it is nil.
dst.gendraw(r, src, p0, mask, p1)
Similar to draw() except that it aligns the source
and mask differently: src is aligned so p0 corre-
sponds to r.min and mask is aligned so p1 corre-
sponds to r.min. For most purposes with simple
masks and source images, draw is sufficient, but
gendraw is the general operator and the one the
other drawing primitives are built upon.
dst.line(p0, p1, end0, end1, thick, src, sp)
Line draws in dst a line of width 1+2*thick pixels
joining points p0 and p1. The line is drawn using
pixels from the src image aligned so sp in the
source corresponds to p0 in the destination. The
line touches both p0 and p1, and end0 and end1
specify how the ends of the line are drawn.
Draw->Endsquare terminates the line
Page 3 Plan 9 (printed 10/23/25)
DRAW-IMAGE(2) DRAW-IMAGE(2)
perpendicularly to the direction of the line; a
thick line with Endsquare on both ends will be a
rectangle. Draw->Enddisc terminates the line by
drawing a disc of diameter 1+2*thick centered on
the end point. Draw->Endarrow terminates the line
with an arrowhead whose tip touches the endpoint.
See the description of arrow for more information.
Line and the other geometrical operators are
equivalent to calls to gendraw using a mask pro-
duced by the geometric procedure.
dst.poly(p, end0, end1, thick, src, sp)
Poly draws a general polygon; it is equivalent to
a series of calls to line joining adjacent points
in the array of Points p. The ends of the polygon
are specified as in line; interior lines are ter-
minated with Enddisc to make smooth joins. The
source is aligned so sp corresponds to p[0].
dst.bezspline(p, end0, end1, thick, src, sp)
Bezspline takes the same arguments as poly but
draws a quadratic B-spline (despite its name)
rather than a polygon. If the first and last
points in p are equal, the spline has periodic end
conditions.
dst.fillpoly(p, wind, src, sp)
Fillpoly is like poly but fills in the resulting
polygon rather than outlining it. The source is
aligned so sp corresponds to p[0]. The winding
rule parameter wind resolves ambiguities about
what to fill if the polygon is self-intersecting.
If wind is ~0, a pixel is inside the polygon if
the polygon's winding number about the point is
non-zero. If wind is 1, a pixel is inside if the
winding number is odd. Complementary values (0 or
~1) cause outside pixels to be filled. The mean-
ing of other values is undefined. The polygon is
closed with a line if necessary.
dst.fillbezspline(p, wind, src, sp)
Fillbezspline is like fillpoly but fills the qua-
dratic B-spline rather than the polygon outlined
by p. The spline is closed with a line if neces-
sary.
dst.ellipse(c, a, b, thick, src, sp)
Ellipse draws in dst an ellipse centered on c with
horizontal and vertical semiaxes a and b. The
source is aligned so sp in src corresponds to c in
dst. The ellipse is drawn with thickness
Page 4 Plan 9 (printed 10/23/25)
DRAW-IMAGE(2) DRAW-IMAGE(2)
1+2*thick.
dst.fillellipse(c, a, b, src, sp)
Fillellipse is like ellipse but fills the ellipse
rather than outlining it.
dst.bezier(a, b, c, d, end0, end1, thick, src, sp)
Bezier draws the cubic Bezier curve defined by
Points a, b, c, and d. The end styles are deter-
mined by end0 and end1; the thickness of the curve
is 1+2*thick. The source is aligned so sp in src
corresponds to a in dst.
dst.fillbezier(a, b, c, d, wind, src, sp)
Fillbezier is to bezier as fillpoly is to poly.
arrow(a, b, c)
Arrow is a function to describe general arrow-
heads; its result is passed as end parameters to
line, poly, etc. If all three parameters are
zero, it produces the default arrowhead, other-
wise, a sets the distance along line from end of
the regular line to tip, b sets the distance along
line from the barb to the tip, and c sets the dis-
tance perpendicular to the line from edge of line
to the tip of the barb, all in pixels.
dst.text(p, src, sp, font, str)
Text draws in dst characters specified by the
string str and font font; it is equivalent to a
series of calls to gendraw using source src and
masks determined by the character shapes. The
text is positioned with the left of the first
character at p.x and the top of the line of text
at p.y. The source is positioned so sp in src
corresponds to p in dst. Text returns a Point that
is the position of the next character that would
be drawn if the string were longer.
For characters with undefined or zero-width images
in the font, the character at font position 0
(NUL) is drawn.
src.readpixels(r, data)
Readpixels fills the data array with pixels from
the specified rectangle of the src image. The
pixels are presented one horizontal line at a
time, starting with the top-left pixel of r. Each
scan line starts with a new byte in the array,
leaving the last byte of the previous line par-
tially empty, if necessary. Pixels are packed as
tightly as possible within data, regardless of the
Page 5 Plan 9 (printed 10/23/25)
DRAW-IMAGE(2) DRAW-IMAGE(2)
rectangle being extracted. Bytes are filled from
most to least significant bit order, as the x
coordinate increases, aligned so x=0 would appear
as the leftmost pixel of its byte. Thus, for
ldepth 0, the pixel at x offset 165 within the
rectangle will be in a data byte with mask value
16r04 regardless of the overall rectangle: 165 mod
8 equals 5, and 16r80 >> 5 equals 16r04. It is an
error to call readpixels with an array that is too
small to hold the rectangle's pixels. The return
value is the number of bytes copied.
dst.writepixels(r, data)
Writepixels copies pixel values from the data
array to the specified rectangle in the dst image.
The format of the data is that produced by
readpixels. The return value is the number of
bytes copied. It is an error to call writepixels
with an array that is too small to fill the rect-
angle.
win.top() If the image win is a window, top pulls it to the
``top'' of the stack of windows on its Screen,
perhaps obscuring other images. If win is not a
window, top has no effect.
win.bottom()
If the image win is a window, bottom pulls it to
the ``bottom'' of the stack of windows on its
Screen, perhaps obscuring it. If win is not a
window, bottom has no effect.
image.flush(flag)
The connection to a display has a buffer used to
gather graphics requests generated by calls to the
draw library. By default, the library flushes the
buffer at the conclusion of any call that affects
the visible display image itself. The flush rou-
tine allows finer control of buffer management.
The flag has three possible values: Flushoff turns
off all automatic flushing caused by writes to
image, typically a window or the display image
itself (buffers may still be written when they
fill or when other objects on the display are mod-
ified); Flushnow causes the buffer to be flushed
immediately; and Flushon restores the default
behaviour.
win.origin(log, scr)
When a window is created (see draw-screen(2)), the
coordinate system within the window is identical
to that of the screen: the upper left corner of
Page 6 Plan 9 (printed 10/23/25)
DRAW-IMAGE(2) DRAW-IMAGE(2)
the window rectangle is its physical location on
the display, not for example (0, 0). This symme-
try may be broken, however: origin allows control
of the location of the window on the display and
the coordinate system used by programs drawing on
the window. The first argument, log, sets the
upper left corner of the logical (in-window) coor-
dinate system without changing the position of the
window on the screen. The second argument, scr,
sets the upper left corner of physical (on-screen)
coordinate system, that is, the window's location
on the display, without changing the internal
coordinate system. Therefore, changing scr with-
out changing log moves the window without requir-
ing the client using it to be notified of the
change; changing log without changing scr allows
the client to set up a private coordinate system
regardless of the window's location. It is per-
missible for values of scr to move some or all of
the window off screen. Origin returns -1 if the
image is not a window or, in the case of changes
to scr, if there are insufficient resources avail-
able to move the window; otherwise it returns 1.
Page 7 Plan 9 (printed 10/23/25)