TOC PREV NEXT INDEX

Graphic Display API for drawing

This topic describes the Graphics Display Kit's Application Program Interface (API) for drawing in screen space in a view's rendering window.

This topic discusses:

Introduction

Summary of examples

Detailed example: DrawCursor

Header files

Structures

Common parameters to the GD2d_draw routines

Introduction

The Graphics Display Kit has an application program interface (API) that lets a program create screen-space 2D drawings in a view's rendering window. This section documents the same routines that are used by the interactivity modules.

For more information on the interactivity modules, see Interactivity .

Although you could create drawings with the windowing system API calls (e.g., X), the routines described in this chapter have the additional benefit of being portable across platforms (UNIX and Windows systems).

Data structures

To use the API, you typically access the following structures:

GDview -- Contains information about a view, including pointers to the structures GDwinfo, GDstate, and GDstack.

GDwinfo -- Contains information about the rendering window. In the context of drawing, it contains the window's size.

GDstate -- Contains the current attribute information for the view. In the context of drawing, it specifies surface color, drawing mode, line width, line style, and text font.

GDstack -- Contains "old" attribute information that is pushed and popped onto the stack as the objects in the view are rendered. This structure provides the mechanism that provides inheritance of attributes.

Summary of examples

The Graphics Display Kit provides several examples, including objects and C functions, illustrating the drawing API.

In the Network Editor, you can find the objects in Libraries.Templates.GD.Examples

You can find the source code for the C functions in samples.c, in the src/gd directory.

Her is s a summary of the examples:

Object name

Function name

Description

DrawCursor

DrawCursor

Lets the user display and move a cross-hair cursor in a view's rendering window.

TestDrawCursor

 

A macro that combines DrawCursor and a UItwoPoint object. The UItwoPoint runs when the user holds down the right mouse button in the connected view's rendering window.

Doodle

Doodle

A sophisticated example that lets the user draw a line, box, or arbitrary region in a continuous mouse gesture, and supports the copy and XOR drawing modes.

SuperDoodle

 

A macro that combines Doodle and a UItwoPoint object. The UItwoPoint runs when the user holds down the right mouse button.

Routines

The API includes the following routines:

GDstack_push and GDstack_pop -- Save and restore a view's state, so you can make changes to the state for the purposes of drawing, then restore the saved state.

GDstate_set_ xxxx -- Set a view's GDstate structure.

GD2d_draw_ xxxx -- Create various types of drawings, such as points, lines, polylines, and text.

GDview_call_func -- Used to access the renderer specific routine to refresh the view.

Detailed example: DrawCursor

DrawCursor is a Graphics Display Kit object that draws a cross-hair cursor in the rendering window. The vertical and horizontal lines that make up the cursor extend to the borders of the window. The cursor is centered on a particular point in the window.

DrawCursor performs its processing by calling the C function DrawCursor. You can find the source code for DrawCursor in gd/samples.c.

DrawCursor object

Here is the V code for the DrawCursor object:

group DrawCursor {
GDview_templ+IPort+nonotify &view_in;
int+IPort2+nonotify x;
int+IPort2+nonotify y;
int+IPort2 state;
method+notify_val update = "DrawCursor";
};

view_in is a connection to a view.

x and y specify the point in screen space where the cursor should be positioned.

state specifies whether to draw a cursor (1 means yes).

You typically connect x, y, and state to a UItwoPoint object, so the user can display and move the cursor with a mouse operation.

TestCursor object

The Graphics Display Kit supplies a macro called TestCursor that includes DrawCursor and a UIonePoint interactor. Here is its definition:


macro TestCursor {
GDview_templ+IPort2+nonotify &view;
ilink rv;

UItwoPoint UItwoPoint {
view+IPort2 => rv;
&startEvent = "Shift<Btn1Down>";
&runEvent = "Shift<Btn1Motion>";
&stopEvent = "Shift<Btn1Up>";
};
DrawCursor DrawCursor {
view_in => view;
x => UItwoPoint.x;
y => UItwoPoint.y;
state => UItwoPoint.state;
}
};

Connect a view, such as the view output of one of the viewers (SimpleViewer, Viewer, etc.) to TestCursor's first input port. Connect a UIrenderView object, such as the rv output of one of the viewers, to the second input port.

DrawCursor function

Here is the source code for the function DrawCursor, located in gd/samples.c.


void DrawCursor(elem_id)
OMobj_id elem_id;
{
OMobj_id view_id;
GDview *view;
int state, x, y;
static int prev_x, prev_y;
short lines[16];
float white[3];
int xmax, ymax;


white[0]=white[1]=white[2]= 1.0;

/* Get the view's object id. */
view_id = OMfind_subobj(elem_id,
OMstr_to_name("view_in"), OM_OBJ_RD);
if (OMis_null_obj(view_id)) {
printf("[DrawCursor]: Can't get view\n");
return;
}

if (!GDget_int_val(elem_id, "state", &state)) {
printf("[DrawCursor]: Can't get state\n");
return;
}
if (!GDget_int_val(elem_id, "x", &x)) {
printf("[DrawCursor]: Can't get x\n");
return;
}
if (!GDget_int_val(elem_id, "y", &y)) {
printf("[DrawCursor]: Can't get y\n");
return;
}

/* get pointer to local view structure so we can find
the state and winfo.
*/
view = (GDview *)GDget_local(view_id,
(OMpfi)GDview_create);
if (!view) {
printf("[DrawCursor]: Can't get view information\n");
return;
}

/* Setup stuff to draw the cursor */
if (!view->Winfo || !view->State) {
printf
("[DrawCursor]: Winfo or State not initialized in view\n");
return;
}

/* Get view width and height. We should provide a routine
to access this info (or a macro).
*/
xmax = view->Winfo->w;
ymax = view->Winfo->h;

/* Push start of rendering marker onto the stack so we can
restore original attributes when we are done.
*/
GDstack_push(view);

/* Set the color to be used for drawing */
GDstate_set_color(view, white);

/* Currently allowed modes are 0 = copy and non-zero = XOR.
This needs to be improved so we have defines for each draw mode.
*/
GDstate_set_draw_mode(view, 1);

/* Tell GD to use the front buffer (ie. window) as the
drawable. This allows our drawing to be visible even if
we are in double buffer mode.
*/
GDstate_set_drawable(view, 1);

switch (state) {
case 1: /* start event */
/* draw full screen cursor */
lines[0] = x;
lines[1] = 0;
lines[2] = x;
lines[3] = ymax;
lines[4] = 0;
lines[5] = y;
lines[6] = xmax;
lines[7] = y;
GD2d_draw_lines(view->State, 4, lines, NULL, NULL);
break;
case 2: /* run event */
/* erase line at previous position. Do this by redrawing line,
which works because the mode is xor. The previous line was
created by an xor on the background, so another xor restores
the previous background. */
lines[0] = prev_x;
lines[1] = 0;
lines[2] = prev_x;
lines[3] = ymax;
lines[4] = 0;
lines[5] = prev_y;
lines[6] = xmax;
lines[7] = prev_y;
/* draw line at new position */
lines[8] = x;
lines[9] = 0;
lines[10] = x;
lines[11] = ymax;
lines[12] = 0;
lines[13] = y;
lines[14] = xmax;
lines[15] = y;
GD2d_draw_lines(view->State, 8, lines, NULL, NULL);
break;
case 3: /* stop event */
/* erase line at previous position */
lines[0] = prev_x;
lines[1] = 0;
lines[2] = prev_x;
lines[3] = ymax;
lines[4] = 0;
lines[5] = prev_y;
lines[6] = xmax;
lines[7] = prev_y;
GD2d_draw_lines(view->State, 4, lines, NULL, NULL);
break;
default: /* unknow event */
printf("[DrawCursor]: Unknown event\n");
break;
}
/* save xy as prev_xy for erasure on other events */
prev_x = x;
prev_y = y;

GDstack_pop(view);
}

Header files Structures

A program should include the following header files, in addition to any standard header files:

#include <avs/util.h>
#include <avs/om.h>
#include <avs/om_type.h>
#include <avs/gd.h>

GDview

GDview is a data structure that contains information about a view. For the purposes of drawing, the important members are Winfo, State, and Stack. These are pointers to the view's GDwinfo, GDstate, and GDstack structures. GDview is defined in avs/gd_str.h.

Contents


struct _GDview {
OMobj_id view_id; /* reference to DB element */
OMobj_id upd_func, del_func; /* functions for view update, delete */
OMobj_id event_func, pick_func; /* event handling and picking */
OMobj_id virtpal_func; /* virtual palette handling function */
OMobj_id pick_ctrl_id; /* reference to pick control element */
GDwinfo *Winfo; /* info about view parent window */
PALvirt *VirtPal; /* virtual palette attached to view */
PALfunc change_func; /* function the palette code will call */
/* renderer specific view functions */
OMpfi view_avail;
OMpfi view_create;
OMpfi view_clear;
OMpfi view_transp_pass;
OMpfi view_accel;
OMpfi view_swap1;
OMpfi view_image_pass;
OMpfi view_swap2;
OMpfi view_refresh;
OMpfi view_delete;
OMpfi view_resize;
/* end of renderer specifice functions */
GDstack *Stack;
GDstate *State;
GDlight_info *LightInfo;
GDviewAttrs *ViewAttr;
GDoutput *Output;
int ncams; /* number of cameras */
GDcamera **cameras; /* array of cameras */
int vobjs; /* number of objects in top level list */
GDobject **objs; /* array of objects */
int renderer; /* current renderer */
int available; /* 1 if view avail,0 when rendererchanged */
int status; /* status of cameras/objects in the view */
int mode; /* update mode - auto/manual */
int timer; /* if 1 spew rendering times */
int pcache; /* if 1 render to pcache (XGL only) */
int accel; /* accel mode for incremental rendering */
int accel_valid; /* accel buffers valid */
int double_buffer;
float back_col[3]; /* background color */
/* sequence numbers for update view routine */
int rend_seq, mode_seq, upd_seq, refresh_seq, accel_seq;
int timer_seq, pcache_seq, buffer_seq, col_seq;
};

Accessing GDview from a program

A view object has a subobject called local_ptr, which points to the view's GDview structure. You can use the utility routine GDget_local to get the pointer.

Here is an example of accessing GDview from a program:


//
// elem_id is the object id of the calling group object.
// One of the group's subobjects is view_in, which should
// be connected to a group.
//
void DrawCursor(elem_id)
OMobj_id elem_id;
{
GDview *view;
...

//
// Get the view's object id.
//
view_id = OMfind_subobj(elem_id,
OMstr_to_name("view_in"), OM_OBJ_RD);
if(OMis_null_obj(view_id) {
printf("[DrawCursor]: Can't get view\n");
return;
};
...

//
// Get the view's GDview structure.
//
view = (GDview *) GDget_local(view_id,
(OMpfi)GDview_create);
if (!view) {
printf("[DrawCursor]: Can't get view information\n");
return;
};

GDwinfo structure

GDwinfo is a data structure that contains information about the viewing window. For the purposes of drawing, the important members are the rendering window's width and height (w and h). GDwinfo is defined in avs/gd_str.h.

Contents


struct _GDwinfo {
#ifdef MSDOS
HINSTANCE hInst; /* Original instance */
HWND Parent; /* Parent of view window */
HWND hWnd; /* Handle of view window */
HDC hdc; /* Device context of view window */
int Depth; /* Depth of window */
int bytes_per_pixel;
int xPPM, yPPM; /* Pels Per Meter *
#else
Display *disp; /* X display for view window */
int screen;
Widget widget; /* widget of parent window */
Window parent; /* parent of view window */
Window window; /* actual view window *
#endif
int x, y, w, h; /* position and size of view window */
void *priv; /* renderer private record *
};

Accessing GDwinfo from a program

GDview has a member called Winfo, which is a pointer to the view's GDwinfo structure.

As an example, assume that the variable view is a pointer to a view's GDview structure. The following line gets GDwinfo's w member:


xmax = view->Winfo->w;

GDstate structure

GDstate is a data structure that contains the view's state information. For the purpose of drawing, you typically access only a small portion of the state information. GDstate is defined in avs/gd_str.h.

Contents

Here is GDstate, showing only the members you typically access:


struct _GDstate {
#ifdef MSDOS
HBITMAP Drawable;
#else
Drawable drawable; /* window or pixmap */
#endif
float col[3]; /* surface color */
int draw_mode; /* drawing mode
char font[128]; /* font name for text */
int line_width; /* line width */
int line_style; /* solid or dashed
};

Setting GDstate through special routines

You set GDstate's members through the GDstate_set routines. It is recommended that you avoid accessing the structure members directly.

As an example, assume that view is a pointer to a view's GDview structure. The following line sets the draw_mode state to xor:

GDstate_set_draw_mode (view, 1);

Saving the state

Part of the API are routines called GDstack_push and GDstack_pop. At the start of a routine, before setting a view's states, you typically call the routine GDstack_push to save the current state. At the end of the routine, you typically call the routine GDstack_pop to restore the state.

As an example, assume that view is a pointer to a view's GDview structure. The following lines save and restore the view's state:


GDstack_push(view);
... /* All GDstate and GD2d_draw calls */
GDstack_pop(view);

Common parameters to the GD2d_draw routines

GDstate_ *state

state is a pointer to a view's GDstate structure.

Typically, you specify:

view->State

where view is a pointer to the view's GDview structure. State, a member of GDview, is a pointer to the view's GDstate structure.

int _vcount

vcount is the number of vertices in the drawing. The number differs depending on the drawing.

For example, in the routine GD2d_draw_lines, vcount is two times the number of lines being drawn, because each line is defined by two points.

SHORT2 vert[]

vert is a short array of x and y coordinates for each vertex, specified in screen space.

SHORT2 is a typedef that expands to a two-element short-integer array:

typedef short SHORT2[2];

The number of values you specify depends on the drawing. For example, in the routine GD2d_draw_lines, if you were drawing a single line (vcount of 2), you would specify four values: the x and y values for one vertex of the line, followed by the x and y values for the other vertex.

If you were drawing two lines (vcount of 4), vert would specify eight values: the x and y values for one vertex of the first line, followed by the x and y values for the other vertex of the first line, followed by the same kinds of specifications for the second line.

FLOAT3 fcolor[] and FLOAT3 vcolor[]

Float arrays for facet colors (fcolor) and vertex colors (vcolor).

FLOAT3 is a typedef that expands to a three-element float array:

typedef float FLOAT3[3];

The elements specify a color's red, green, and blue components.

Both of these parameters are optional; you can specify NULL for each. If you specify neither, the renderer uses the view's surface color (which you can set with the GDstate_set_color routine). If you specify fcolor or vcolor, the renderer uses those colors instead. If you specify both fcolor and vcolor, the renderer uses vcolor and ignores fcolor.

When you specify fcolor or vcolor, the number of values you specify for a color depends on the drawing. For example, in the routine GD2d_draw_lines, if you were drawing a single line (vcount of 2), fcolor would specify three values: the red, green, and blue values of the line's one facet. vcolor would specify six values: the red, green, and blue values of one vertex of the line, followed by the red, green, and blue values of the other vertex.

If you were drawing two lines (vcount of 4), fcolor would specify six values: the red, green, and blue for one line, followed by a similar specification for the other line. vcolor would specify 12 values: two red, green, and blue values for one line, followed by two red, green, and blue values for the other line.

The renderer averages color values where two or more apply to the same drawing. For example, if you specify a line's vcolor, the renderer averages the vcolors for the line's vertices and colors the line completely that color.

Specifying fcolor or vcolor in a routine carries a performance penalty, since the renderer must determine colors for each drawing made by the routine.


TOC PREV NEXT INDEX