GRAPHICS(2) GRAPHICS(2)
NAME
Display, Point, Rectangle, Cursor, initdraw, geninitdraw,
drawerror, initdisplay, closedisplay, getdefont, getwindow,
gengetwindow, flushimage, bufimage, lockdisplay,
unlockdisplay, openfont, buildfont, freefont, Pfmt, Rfmt,
strtochan, chantostr, chantodepth - interactive graphics
SYNOPSIS
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <cursor.h>
int initdraw(void (*errfun)(Display*, char*), char *font,
char *label)
int geninitdraw(char *devdir, void(*errfun)(Display*, char*),
char *font, char *label, char *windir, int ref)
int newwindow(char *str)
void drawerror(Display *d, char *msg)
Display*initdisplay(char *devdir, char *win, void(*errfun)(Display*, char*))
void closedisplay(Display *d)
Subfont*getdefont(Display *d)
int flushimage(Display *d, int vis)
uchar*bufimage(Display *d, int n)
void lockdisplay(Display *d)
void unlockdisplay(Display *d)
int getwindow(Display *d, int ref)
int gengetwindow(Display *d, char *winname,
Image **ip, Screen **sp, int ref)
Font* openfont(Display *d, char *name)
Font* buildfont(Display *d, char *desc, char *name)
void freefont(Font *f)
int Pfmt(Fmt*)
Page 1 Plan 9 (printed 10/29/25)
GRAPHICS(2) GRAPHICS(2)
int Rfmt(Fmt*)
ulong strtochan(char *s)
char* chantostr(char *s, ulong chan)
int chantodepth(ulong chan)
extern Display *display
extern Image *screen
extern Screen *_screen
extern Font *font
DESCRIPTION
A Display structure represents a connection to the graphics
device, draw(3), holding all graphics resources associated
with the connection, including in particular raster image
data in use by the client program. The structure is defined
(in part) as:
typedef
struct Display
{
...
void (*error)(Display*, char*);
...
Image *black;
Image *white;
Image *opaque;
Image *transparent;
Image *image;
Font *defaultfont;
Subfont *defaultsubfont;
...
};
A Point is a location in an Image (see below and draw(2)),
such as the display, and is defined as:
typedef
struct Point {
int x;
int y;
} Point;
The coordinate system has x increasing to the right and y
increasing down.
A Rectangle is a rectangular area in an image.
Page 2 Plan 9 (printed 10/29/25)
GRAPHICS(2) GRAPHICS(2)
typedef
struct Rectangle {
Point min; /* upper left */
Point max; /* lower right */
} Rectangle;
By definition, min.x≤max.x and min.y≤max.y. By convention,
the right (maximum x) and bottom (maximum y) edges are
excluded from the represented rectangle, so abutting rectan-
gles have no points in common. Thus, max contains the coor-
dinates of the first point beyond the rectangle.
The Image data structure is defined in draw(2).
A Font is a set of character images, indexed by runes (see
utf(6)). The images are organized into Subfonts, each con-
taining the images for a small, contiguous set of runes.
The detailed format of these data structures, which are
described in detail in cachechars(2), is immaterial for most
applications. Font and Subfont structures contain two
interrelated fields: `ascent', the distance from the top of
the highest character (actually the top of the image holding
all the characters) to the baseline, and `height', the dis-
tance from the top of the highest character to the bottom of
the lowest character (and hence, the interline spacing).
See cachechars(2) for more details.
Buildfont parses the font description in the buffer desc,
returning a Font* pointer that can be used by string (see
draw(2)) to draw characters from the font. Openfont does
the same, but reads the description from the named file.
Freefont frees a font. The convention for naming font files
is:
/lib/font/bit/name/range.size.font
where size is approximately the height in pixels of the
lower case letters (without ascenders or descenders). Range
gives some indication of which characters will be available:
for example ascii, latin1, euro, or unicode. Euro includes
most European languages, punctuation marks, the Interna-
tional Phonetic Alphabet, etc., but no Oriental languages.
Unicode includes every character for which appropriate-sized
images exist on the system.
A Cursor is defined:
typedef struct
Cursor {
Point offset;
uchar clr[2*16];
uchar set[2*16];
Page 3 Plan 9 (printed 10/29/25)
GRAPHICS(2) GRAPHICS(2)
} Cursor;
The arrays are arranged in rows, two bytes per row, left to
right in big-endian order to give 16 rows of 16 bits each.
A cursor is displayed on the screen by adding offset to the
current mouse position, using clr as a mask to draw white at
the pixels where clr is one, and then drawing black at the
pixels where set is one. Setcursor and moveto (see
mouse(2)) and esetcursor and emoveto (see event(2)) change
the cursor image and its location on the screen.
The routine initdraw connects to the display; it returns -1
if it fails and sets the error string. Initdraw sets up the
global variables display (the Display structure representing
the connection), screen (an Image representing the display
memory itself or, if rio(1) is running, the client's win-
dow), and font (the default font for text). The arguments
to initdraw include a label, which is written to /dev/label
if non-nil so that it can be used to identify the window
when hidden (see rio(1)). The font is created by reading the
named font file. If font is null, initdraw reads the file
named in the environment variable $font; if $font is not
set, it imports the default (usually minimal) font from the
operating system. The global font will be set to point to
the resulting Font structure. The errfun argument is a
graphics error function to call in the event of a fatal
error in the library; it must never return. Its arguments
are the display pointer and an error string. If errfun is
nil, the library provides a default, called drawerror.
Another effect of initdraw is that it installs print(2) for-
mats Pfmt and Rfmt as `%P' and `%R' for printing Points and
Rectangles.
The geninitdraw function provides a less automated way to
establish a connection, for programs that wish to connect to
multiple displays. Devdir is the name of the directory con-
taining the device files for the display (if nil, default
/dev); errfun, font, and label are as in initdraw; windir is
the directory holding the winname files; and ref specifies
the refresh function to be used to create the window, if
running under rio(1) (see window(2)).
The function newwindow may be called before initdraw or
geninitdraw to cause the program to occupy a newly created
window rather than take over the one in which it is running
when it starts. The str argument, if non-null, is concate-
nated to the string "new " that is used to create the window
(see rio(4)). For example, newwindow("-hide -dy 100") will
cause the program to run in a newly created, hidden window
100 pixels high.
Initdisplay is part of geninitdraw; it sets up the display
Page 4 Plan 9 (printed 10/29/25)
GRAPHICS(2) GRAPHICS(2)
structures but does not allocate any fonts or call
getwindow. The arguments are similar to those of initdraw;
win names the directory, default /dev, in which the files
associated with the window reside. Closedisplay disconnects
the display and frees the associated data structures.
Getdefont builds a Subfont structure from in-core data
describing a default subfont. None of these routines is
needed by most programs, since initdraw calls them as
needed.
The data structures associated with the display must be pro-
tected in a multi-process program, because they assume only
one process will be using them at a time. Multi-process
programs should set display->locking to 1, to notify the
library to use a locking protocol for its own accesses, and
call lockdisplay and unlockdisplay around any calls to the
graphics library that will cause messages to be sent to the
display device. Initdraw and geninitdraw initialize the
display to the locked state.
Getwindow returns a pointer to the window associated with
the application; it is called automatically by initdraw to
establish the screen pointer but must be called after each
resizing of the window to restore the library's connection
to the window. If rio is not running, it returns
display->image; otherwise it negotiates with rio by looking
in /dev/winname to find the name of the window and opening
it using namedimage (see allocimage(2)). The resulting win-
dow will be created using the refresh method ref (see
window(2)); this should almost always be Refnone because rio
provides backing store for the window.
Getwindow overwrites the global variables screen, a pointer
to the Image defining the window (or the overall display, if
no window system is running); and _screen, a pointer to the
Screen representing the root of the window's hierarchy. (See
window(2). The overloading of the screen word is an unfortu-
nate historical accident.) Getwindow arranges that screen
point to the portion of the window inside the border;
sophisticated clients may use _screen to make further sub-
windows. Programs desiring multiple independent windows may
use the mechanisms of rio(4) to create more windows (usually
by a fresh mount of the window sytem in a directory other
than /dev), then use gengetwindow to connect to them.
Gengetwindow's extra arguments are the full path of the
window's winname file and pointers to be overwritten with
the values of the `global' Image and Screen variables for
the new window.
The graphics functions described in draw(2), allocimage(2),
cachechars(2), and subfont(2) are implemented by writing
commands to files under /dev/draw (see draw(3)); the writes
Page 5 Plan 9 (printed 10/29/25)
GRAPHICS(2) GRAPHICS(2)
are buffered, so the functions may not take effect immedi-
ately. Flushimage flushes the buffer, doing all pending
graphics operations. If vis is non-zero, any changes are
also copied from the `soft screen' (if any) in the driver to
the visible frame buffer. The various allocation routines
in the library flush automatically, as does the event pack-
age (see event(2)); most programs do not need to call
flushimage. It returns -1 on error.
Bufimage is used to allocate space for n bytes in the dis-
play buffer. It is used by all the graphics routines to
send messages to the display.
The functions strtochan and chantostr convert between the
channel descriptor strings used by image(6) and the internal
ulong representation used by the graphics protocol (see
draw(3)'s b message). Chantostr writes at most nine bytes
into the buffer pointed at by s and returns s on success, 0
on failure. Chantodepth returns the number of bits per
pixel used by the format specified by chan. Both chantodepth
and strtochan return 0 when presented with bad input.
EXAMPLES
To reconnect to the window after a resize event,
if(getwindow(display, Refnone) < 0)
sysfatal("resize failed: %r");
To create and set up a new rio(1) window,
Image *screen2;
Screen *_screen2;
srvwsys = getenv("wsys");
if(srvwsys == nil)
sysfatal("can't find $wsys: %r");
rfork(RFNAMEG); /* keep mount of rio private */
fd = open(srvwsys, ORDWR);
if(fd < 0)
sysfatal("can't open $wsys: %r");
/* mount creates window; see rio(4) */
if(mount(fd, -1, "/tmp", MREPL, "new -dx 300-dy 200") < 0)
sysfatal("can't mount new window: %r");
if(gengetwindow(display, "/tmp/winname",
&screen2, &_screen2, Refnone) < 0)
sysfatal("resize failed: %r");
/* now open /tmp/cons, /tmp/mouse */
...
Page 6 Plan 9 (printed 10/29/25)
GRAPHICS(2) GRAPHICS(2)
FILES
/lib/font/bit directory of fonts
SOURCE
/sys/src/libdraw
SEE ALSO
rio(1), addpt(2), allocimage(2), cachechars(2), subfont(2),
draw(2), event(2), frame(2), print(2), window(2), draw(3),
rio(4), image(6), font(6)
DIAGNOSTICS
An error function may call errstr(2) for further diagnos-
tics.
BUGS
The names clr and set in the Cursor structure are reminders
of an archaic color map and might be more appropriately
called white and black.
Page 7 Plan 9 (printed 10/29/25)