GRAPHICS(2)GRAPHICS(2)NAME
Display, Point, Rectangle, Cursor, initdraw, geninitdraw, drawerror,
initdisplay, closedisplay, getdefont, getwindow, gengetwindow, flushim‐
age, bufimage, lockdisplay, unlockdisplay, openfont, buildfont, free‐
font, Pfmt, Rfmt, strtochan, chantostr, chantodepth - interactive
graphicsSYNOPSIS
#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*)
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.
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 repre‐
sented rectangle, so abutting rectangles have no points in common.
Thus, max contains the coordinates of the first point beyond the rec‐
tangle.
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 containing 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 immate‐
rial for most applications. Font and Subfont structures contain two
interrelated fields: the distance from the top of the highest character
(actually the top of the image holding all the characters) to the base‐
line, and the distance 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 charac‐
ters 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 let‐
ters (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
International Phonetic Alphabet, etc., but no Oriental languages. Uni‐
code 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];
} 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 dis‐
played 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 dis‐
play (the Display structure representing the connection), screen (an
Image representing the display memory itself or, if rio(1) is running,
the client's window), and font (the default font for text). The argu‐
ments 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 draw‐
error. Another effect of initdraw is that it installs print(2) formats
Pfmt and Rfmt as and 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 containing the device files for the
display (if nil, default /dev); errfun, font, and label are as in init‐
draw; windir is the directory holding the winname files; and ref speci‐
fies 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 concatenated to the string "new " that is used to cre‐
ate 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 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 dis‐
connects the display and frees the associated data structures. Getde‐
font 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 protected in a
multi-process program, because they assume only one process will be
using them at a time. Multi-process programs should set display->lock‐
ing 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 applica‐
tion; 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 named‐
image (see allocimage(2)). The resulting window 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 unfortunate historical accident.) Getwindow arranges
that screen point to the portion of the window inside the border;
sophisticated clients may use _screen to make further subwindows. Pro‐
grams 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 win‐
dow'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 are buffered, so the
functions may not take effect immediately. Flushimage flushes the buf‐
fer, 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 package (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 display buffer.
It is used by all the graphics routines to send messages to the dis‐
play.
The functions strtochan and chantostr convert between the channel
descriptor strings used by image(6) and the internal ulong representa‐
tion used by the graphics protocol (see draw(3)'s b message). Chan‐
tostr 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 */
...
FILES
/lib/font/bit directory of fonts
SOURCE
/sys/src/libdraw
SEE ALSOrio(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 diagnostics.
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.
GRAPHICS(2)