5.6. Drawing With X   

5.6.1. Graphics Contexts   

Fortunately drawing in X is much simpler than creating windows. The only preparation that we need to do before we can start drawing is to create a graphics context (GC). This data structure contains virtually everything needed to specify pen parameters for drawing. Some examples of what can be defined include :


- Foreground colour
- Background colour
- Pen width
- Line type (eg. solid, dashed, double dashed)
- Join type (eg. miter, round or bevelled)

The most important thing to remember about graphic contexts is that we need to create one before we can start drawing.

The X library maintains a complex cache of GC values, so always treat the structure as read only. Never try to directly write to the structure, always use the GC functions to set the values. With this warning in mind we will show the data structure.

     typedef struct _XGC {

XExtData *ext_data;
GContext gid;
Bool rects;
Bool dashes;
unsigned long dirty;
XGCValues values;
} *GC;

Remember, never try to update this structure directly.

5.6.2. Creating a Graphics Context   

To create a graphics context the XCreateGC function is used.

     Display        *display;

Drawable drawable; /* Eg. window id */
XGCValues xgcvalues;
unsigned long valuemask;
GC gc;
valuemask = 0L; /* No options filled in */
gc = XCreateGC (display, drawable, valuemask, &xgcvalues );

Note that in the above case we are just accepting the default values for the graphics context. This is the usual situation. The defaults are listed below.


arc_mode ArcPieSlice
background 1
cap_style CapButt
clip_mask None
clip_x_origin 0
clip_y_origin 0
fill_style FillSolid
fill_rule EvenOddRule
font implementation dependant
foreground 0
function GXcopy
graphics_exposures True
join_style JoinMiter
line_width 0 (use hardware accelerators, if any)
line_style LineSolid
plane_mask all planes ( all 1s)
subwindow_mode ClipByChildren

The changes that we are most likely to want to make are to the foreground and background colours. One method of doing this is given below.

     Display        *display;

int screen;
GC gc;
unsigned long f_colour;
unsigned long b_colour;
f_colour = BlackPixel(display, screen);
b_colour = WhitePixel(display, screen);
XSetForeground ( display, gc, f_colour );
XSetBackground ( display, gc, b_colour );

5.6.3. Drawing Lines   

The function XDrawLine draws a line between pixel (x1, y1) and pixel (x2, y2).

     Display        *display;

Drawable drawable;
GC gc;
int x1, y1;
int x2, y2;
XDrawLine ( display, drawable, gc, x1, y1, x2, y2);

Note that in practise you will normally pass the window id as the drawable parameter. A drawable is an X term for either windows or pixmaps (which are off screen drawing areas). Most X drawing functions can draw into either of these, but in practise your application will most likely just be drawing into a window.


5.6.4. Drawing Shapes   

Sometimes we will wish to draw more complicated shapes than just lines. X also understands how to draw rectangles and arcs. The functions used are given below.

     Display        *display;

Drawable drawable;
GC gc;
int x, y;
unsigned int width, height;
XDrawRectangle ( display, drawable, gc, x, y, width, height);

The value (x, y) defines the upper left corner of the rectangle, in terms of pixels from the window origin.

Drawing arcs or circles is a similar exercise. You define the bounding rectangle for the arc, and the start angle and path angle (the angle size swept out by the arc). All angles are measured in 1/64 of a degree, eg. 90 degrees is 90 x 64 = 5760 units. An angle of 0 units is the direction of the positive x- axis, and anticlockwise is positive.

     Display        *display;

Drawable drawable;
GC gc;
int x, y;
unsigned int width, height;
int start_angle;
int path_angle;
XDrawArc ( display, drawable, gc, x, y, width, height,
start_angle, path_angle);

5.6.5. Filled Shapes   

The routines described above draw hollow shapes. As you have already guessed, there are similar routines for drawing solid shapes. For completeness, we list the filled version of the above routines.

     Display        *display;

Drawable drawable;
GC gc;
int x, y;
unsigned int width, height;
int start_angle;
int path_angle;
XFillRectangle ( display, drawable, gc, x, y, width, height);
XFillArc ( display, drawable, gc, x, y, width, height,
start_angle, path_angle);

5.6.6. Multiple Objects   

You can also draw multiple objects of a type at a time, rather than sending your requests singularly. This has efficiency advantages, but be careful if you are using an older version of X. There are only so many requests that you can bundle together into one network packet and send off to the X server. Newer versions of X will break up very large requests, but older versions didn't break up big requests into packets.

There our ways to check on the max request size (XMaxRequestSize(display)), but we won't go into that in this course. Just be aware that this could be a potential limitation.


X defines the following structures for your use when drawing multiple objects.

     typedef struct {

short x, y;
} XPoint;
typedef struct {
short x, y;
unsigned short width, height;
} XRectangle;
typedef struct {
short x, y;
unsigned short width, height;
short angle1, angle2;
} XArc;

The functions to draw multiple objects are given below.

     Display        display;

Drawable drawable;
GC gc;
XPoint points [ ARBITRARY_SIZE ];
int no_points;
XRectangle rects [ ARBITRARY_SIZE ];
int no_rects;
XArc arcs [ ARBITRARY_SIZE ];
int no_arcs;
int mode;
XDrawPoints (display, drawable, gc, points, no_points, mode);
XDrawLines (display, drawable, gc, points, no_points, mode );
XDrawRectangles (display, drawable, gc, rects, no_rects) ;
XFillRectangles (display, drawable, gc, rects, no_rects );
XDrawArcs ( display, drawable, gc, arcs, no_arcs );
XFillArcs ( display, drawable, gc, arcs, no_arcs );

The only unexpected item in the above is the new field, mode. This value can have one of two values, CoordModeOrigin or CoordModePrevious. When using CoordModePrevious, the first point is drawn relative to the window origin.  

xlogo.ps