GRAPHICS(2)GRAPHICS(2)
NAME
Display, Point, Rectangle, Cursor, initdraw, geninitdraw, newwindow, 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*)
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 represented rectangle, so abutting rectangles have no
points in common.
Thus,
max
contains the coordinates 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 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 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 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 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 International 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];
} 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 window),
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)
formats
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 containing 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
file; 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 concatenated 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 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 are 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->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 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.
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 are buffered, so the functions may not take effect immediately.
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
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 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 */
...
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 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.