CW CHAPTER 5

From Atari Wiki
Jump to navigation Jump to search








CHAPTER 5: INTRODUCING THE VDI
-------------------------------

[NOTE: Words enclosed in asterisks (i.e. *word*) should be 
read as italicized text. This text file is copyright 1993 by 
Clayton Walnum. All rights reserved.]

GEM (Graphics Environment Manager) is made up of many 
libraries of functions, each of which handles certain 
portions of the system's activities. These libraries are 
grouped into two major units, called the AES (Applications 
Environment Services) and the VDI (Virtual Device 
Interface). The AES, which we've been using since the 
beginning of the book, contains the functions we need to 
handle windows, dialog boxes, menu bars, and event 
processing. The VDI controls most of the ST's graphic 
capabilities and provides some mouse and cursor control 
functions, as well.
	The VDI plays an important role in making your graphics 
programs operate on many different devices. Unfortunately, 
one of the crucial elements in the graphics interface, GDOS 
(Graphics Device Operating System), is not built into the 
current operating system. GDOS is the portion of the VDI 
that links the graphics functions to the drivers needed to 
assure that the graphics operate properly on all graphics 
devices. GDOS also makes it possible to load different fonts 
into your ST, using the standard VDI functions.
	At this time, however, we're concerned only with one 
device: the screen.
 
--The VDI functions--

The VDI provides a series of functions that let us quickly 
draw many graphic shapes. This simplifies the development of 
programs that rely heavily on graphics. If you programmed an 
8-bit Atari (or still do), think of all the work involved in 
drawing a circle. The VDI provides a function that will draw 
any size circle we want--with a single call. There are also 
functions for drawing ellipses, lines, rectangles, rounded 
rectangles, arcs, pie slices and a number of other useful 
graphics.
	And it doesn't stop there. Each graphic function has a 
group of related attributes that may be set before the 
graphic is drawn, allowing various types of lines, fills and 
colors.

--The Program--

This chapter's sample program shows how to set up your 
program to use the VDI. It also includes a demonstration of 
some of the VDI's graphics capabilities. Specifically, when 
the program is run, you will see the different types of line 
styles available through the VDI. To exit the program, press 
your Return key.
 
--The VDI Arrays--

Calling VDI functions is a lot like calling AES functions. 
In both cases, you must place appropriate values into 
control and input arrays, and then call the function by 
using a *trap #2* instruction. Look at the data section of 
this chapter's sample program. There, you'll find the usual 
AES parameter block (*apb*). Right below that, you'll see 
something called *vpb*. Yep. That's a VDI parameter block. 
Although these parameter blocks work the same way--that is, 
they both tell the OS where to find the arrays it needs--
they contain different values. The VDI, for example, doesn't 
use the *addr_in* or *addr_out* arrays. Let's look at the 
*vpb* in detail.
	The first value is the address of a control array. In 
our *apb* we have a 0 in this location because we found it 
easier to have different control arrays for each function, 
and then plug the address of the appropriate array into the 
*apb* when we needed it. But because the values in the VDI 
control array vary from one function call to another, it's 
clumsy to try to set them up ahead of time.
	The *int_in* and *int_out* arrays are the same as those 
in the *apb*. We can use the same arrays for either an AES 
or VDI call. But the VDI *apb* has something a little 
different, arrays called *pts_in* and *pts_out*. These 
arrays usually contain coordinates for the VDI's drawing 
functions. For example, the starting and ending screen 
coordinates for a line would go into the *pts_in* array 
before calling the function.

--Initializing the VDI--

When we use the VDI in our programs, we must set up 
something called a virtual workstation. To do this, we do 
the following:

1) Get a handle to the physical screen.
2) Open a virtual workstation.
3) Clear the virtual workstation.

Look at this chapter's program listing. After the usual 
program initialization, which concludes with the call to 
*appl_init*, we begin the VDI initialization. The first step 
is performed by calling the AES function #77, *graf_handle*, 
like this:

move.l  #graf_handle,apb
jsr     aes
move    int_out,gr_handle
 
	This returns the handle for the currently open device 
(the screen) or workstation, as well as the size of the 
system font. Because GEM is capable of having many programs 
in memory at once, each requires some identification, to 
keep commands for one program from corrupting another. This 
is accomplished by assigning each program a handle. The 
variable *gr_handle* in the above call is an integer value 
that identifies the current workstation. After the call, 
this value is found in the first element of the *int_out* 
array.
	The *graf_handle* call also returns some information 
about the system font. The width of a character cell will be 
in *int_out+2*, the cell height will be in *int_out+4*, the 
width of a box that can enclose a character will be in 
*int_out+6*, and the height of the box will be in 
*int_out+8*. We won't be using any of this character 
information now, but you should know where to find it when 
you need it.
 
--The Virtual Workstation--

The *graf_handle* call returns the handle to the physical 
workstation. What we really need for our program is a handle 
to a virtual workstation. It's kind of tough to explain the 
difference, but I'll give it a shot.
	A particular device may have many virtual workstations, 
but only one physical workstation. The physical workstation 
is directly associated with the device itself, usually the 
screen. You can think of a virtual workstation as a 
"pretend" device. It has its own section of memory and keeps 
its data and status completely separate from all other 
virtual workstations. When you activate an application (such 
as clicking on a desk accessory), it becomes bound to the 
physical workstation. In a sense, it becomes the physical 
workstation.
	We get the handle for our virtual workstation with a 
call to the VDI function #100, *v_opnvwk*, like this:
 
	move    #100,contrl
	clr     contrl+2
	move    #11,contrl+6
	move    gr_handle,contrl+12
	movea.l #int_in,a5
	move    #9,d5
loop:
	move    #1,(a5)+
	dbra    d5,loop
	move    #2,int_in+20
	jsr     vdi
	move    contrl+12,vws_handle
 
	This function expects the system attributes to be in 
the *int_in* array. (In this example, we're loading the 
values into *int_in* using a loop.) These attributes 
determine default values for system attributes such as 
default colors, fill patterns, and line styles. (For those 
of you familiar with C, the *int_in* array in this call 
serves the same function as C's *work_in* array.) In the 
above example, we place a 1 in elements 1 through 10 of the 
*int_in* array, and a 2 in the eleventh element of the 
*int_in* array. This is the standard way to initialize these 
attributes.
	You should note the manner in which the control array 
is used, since all VDI calls require similar parameters in 
this array. The first element of the control array must 
contain the opcode for the VDI function we wish to call. 
*Contrl+2* must contain the number of point pairs that will 
be found in the *pts_in* array, in this case, 0. *Contrl+6* 
must contain the number of integer values that are in the 
*int_in* array. In this function call, *int_in* will contain 
11 values, so we place an 11 in *contrl+6*. Finally, 
*contrl+12* must contain the device handle. In most VDI 
calls, this value will be the handle to our virtual 
workstation. However, because we don't yet have that handle, 
we use the graphics handle that was returned by the call to 
*graf_handle*.
	After the call to *v_opnvwk*, our *int_out* and 
*pts_out* arrays will contain much information about the 
virtual device's current attributes, as follows:

	control+4 -- 6 = # of point pairs in pts_out
	control+8 -- 45 = # of integers in int_out
	control+12 -- Device handle (0 if no device opened)

	int_out, work_out[0] -- Maximum horizontal screen coord.
	int_out+2, work_out[1] -- Maximum vertical screen coord.
	int_out+4, work_out[2] -- Device coordinate units flag:
		0 = Device can display a precisely scaled image.
		1 = Device cannot display a precisely scaled image.
	int_out+6, work_out[3] -- Width of a pixel in microns.
	int_out+8, work_out[4] -- Height of a pixel in microns.
	int_out+10, work_out[5] -- Number of font heights:
		0 = continuous scaling.
	int_out+12, work_out[6] -- Number of line types.
	int_out+14, work_out[7] -- Number of line widths:
		0 = Continuous scaling.
	int_out+16, work_out[8] -- Number of marker styles.
	int_out+18, work_out[9] -- Number of marker sizes:
		0 = Continuous scaling.
	int_out+20, work_out[10] -- Number of supported text fonts.
	int_out+22, work_out[11] -- Number of pattern styles.
	int_out+24, work_out[12] -- Number of hatch styles.
	int_out+26, work_out[13] -- Number of available colors.
	int_out+28, work_out[14] -- Number of generalized drawing 
						primitives.     
	int_out+30 to int_out+48
	work_out[15] to work_out[24] -- Code numbers for available      
						generalized drawing primitives:
		1 = filled bar.
		2 = arc.
		3 = pie slice.
		4 = filled circle.
		5 = filled ellipse.
		6 = elliptical arc.
		7 = elliptical pie slice.
		8 = rounded rectangle.
		9 = filled rounded rectangle.
		10 = justified graphics text.
		-1 = end of GDP list.
	int_out+50 to int_out+68
	work_out[25] to work_out[34] -- Code numbers for graphics
				operations available to the GDPs:
		0 = lines.
		1 = markers.
		2 = graphics text.
		3 = fills.
		4 = none.
	int_out+70, work_out[35] -- Color flag:
		0 = no colors available on device.
		1 = colors available on device.
	int_out+72, work_out[36] -- Text rotation flag:
		0 = device cannot rotate text.
		1 = device can rotate text.
	int_out+74, work_out[37] -- Fill flag:
		0 = device cannot fill areas.
		1 = device can fill areas.
	int_out+76, work_out[38] -- Cell array flag:
		0 = device not capable of cell array operation.
		1 = device capable of cell array operation.
	int_out+78, work_out[39] -- Number of available colors:
		0 = more than 32,767.
		1 = Black and white
		2 or more = Number of colors available.
	int_out+80, work_out[40] -- Locator input devices:
		1 = keyboard.
		2 = keyboard and mouse (or other device)
	int_out+82, work_out[41] -- Valuator input devices:
		1 = keyboard.
		2 = other device.
	int_out+84, work_out[42] -- Choice devices:
		1 = function keys.
		2 = other keypad.
	int_out+86, work_out[43] -- Text input devices:
		1 = keyboard.
	int_out+88, work_out[44] -- Type of workstation:
		0 = output.
		1 = input.
		2 = input and output.
		3 = reserved
		4 = metafile output.
	pts_out, work_out[45] -- Minimum character width.
	pts_out+2, work_out[46] -- Minimum character height.
	pts_out+4, work_out[47] -- Maximum character width.
	pts_out+6, work_out[48] -- Maximum character height.
	pts_out+8, work_out[49] -- Minimum line width.
	pts_out+10, work_out[50] -- 0.
	pts_out+12, work_out[51] -- Maximum line width.
	pts_out+14, work_out[52] -- 0.
	pts_out+16, work_out[53] -- Minimum marker width.
	pts_out+18, work_out[54] -- Minimum marker height.
	pts_out+20, work_out[55] -- Maximum marker width.
	pts_out+22, work_out[56] -- Maximum marker height.

	Don't let all this information intimidate you. Right 
now, we're only concerned with the three values returned in 
*contrl+4*, *contrl+8*, and *contrl+12*. *Contrl+12* will 
contain the handle to our virtual workstation, *contrl+4* 
will contain the number of points (two values each) returned 
in *pts_out*, and *contrl+8* will contain the number of 
integers returned in *int_out*. For this function call, 
*contrl+4* should contain a 6 after the call, which mean six 
pairs of integers have been returned in *pts_out*, and 
*contrl+8* should contain a 45, the number of integers 
returned in *int_out*. For every VDI call, *contrl+4* and 
*contrl+8* are used the same way. You can always check them 
to see how many values have been returned by a VDI function.
	Finally, in the above example, notice that we are 
calling a subroutine called *vdi* to perform a VDI function. 
The *vdi* subroutine works similarly to the *aes* 
subroutine, setting up the VDI function and then doing a 
*trap #2*.

--Clearing the Workstation--

The last step in getting the VDI initialized is to clear the 
workstation. Clearing a workstation ensures that all the 
devices have been flushed and the screen has been erased. In 
other words, it presents us with a blank slate upon which 
our program can begin to operate. To clear a workstation, we 
call VDI function #3, *v_clrwk*, like this:

move    #3,contrl
clr     contrl+2
clr     contrl+6
move    vws_handle,contrl+12
jsr     vdi

	As you can see, this function has no special 
parameters, nor does it return any values. It simply does 
its business and returns control to the program. Notice 
again, how we're using the control array. Because we have no 
values in the *pts_in* and *int_in* arrays, we set both 
*contrl+2* and *contrl+6* to 0. When calling a VDI function, 
you also must be sure that the virtual workstation handle is 
in *contrl+12*. In the above example, we show the 
workstation handle being placed in *contrl+12*. However, in 
the sample program, this instruction is missing. Why? 
Because the handle is already in *contrl+12*, where it was 
placed by the call to *v_opnvwk*. The handle will stay in 
*contrl+12*, right where we want it, until we overwrite it.

--Polylines--

Now that we've got our workstation set up, we can get down 
to business. The first graphic we'll experiment with is the 
polyline. Those of you who are up on your linguistics know 
that the prefix "poly" means "many." A polyline is one or 
more lines connected from point to point, which allows the 
programmer to draw complex shapes with a single function 
call.
	But before we draw our polylines, we need to set some 
line attributes, like color, width, and end style. Any lines 
drawn after we've set the attributes will use those 
attributes. Also, the line attributes stay in effect until 
we change them again.
	To set a line's color, we use a call to VDI function 
#17, *vsl_color*, like this:

move    #17,contrl
clr     contrl+2
move    #1,contrl+6
move    vws_handle,contrl+12
move    color,int_in
jsr     vdi

	Here, *color* is an integer from 0 to the device 
maximum (low resolution=15, medium resolution=3, and high 
resolution=1). If we use a number higher than the maximum, 
the function will default to color 1. On the ST, the default 
color palette, starting with 0 and ending with 15, is white, 
black, red, green, blue, cyan, yellow, magenta, white, 
black, light red, light green, light blue, light cyan, light 
yellow and light magenta. The actual color value set is 
returned in *int_out*.
     When we're drawing lines, we can also choose an end 
style with a call to VDI function #108, *vsl_ends*:

move    #108,contrl
clr     contrl+2
move    #2,contrl+6
move    vws_handle,contrl+12
move    ends,int_in
move    ends,int_in+2
jsr     vdi

In this case, *ends* is an integer value from 0 to 2. A 
value of 0 will yield a square end, 1 will get us an arrow, 
and 2 will result in a rounded end. Here we're using *ends* 
as both the beginning and ending line style, but each end of 
the line can have a different end style if we like. To do 
this, we'd put the first end style in *int_in* and the 
second end style in *int_in+2*. This function returns no 
values.
     Finally, we can set the thickness of our lines with a 
call to VDI function #16, *vsl_width*:

move    #16,contrl
move    #1,contrl+2
clr     contrl+6
move    vws_handle,contrl+12
move    width,pts_in
clr     pts_in+2
jsr     vdi

	The variable *width*, which is placed into the first 
element of *pts_in*, must be an odd positive integer. The 
line will be set to the closest width less than or equal to 
the value of *width*. Notice that, for some strange reason, 
*pts_in+2* must contain a 0. The actual width set is 
returned in the first element of *pts_out*.
	Once we have the attributes set, we can draw our first 
line. We do this with a call to VDI function #6, *v_pline*:

move    #6,contrl
move    #2,contrl+2
clr     contrl+6
move    vws_handle,contrl+12
move    x1,pts_in
move    y1,pts_in+2
move    x2,pts_in+4
move    y2,pts_in+6
jsr     vdi

	In this call, *x1* and *y1* are the X and Y coordinates 
of one end of the line. The integers *x2* and *y2* are, of 
course, the X and Y coordinates of the other end of the 
line. In the example program, we're using *v_pline* to draw 
only single lines. However, as we said before, this function 
can be used to draw many connected lines. For example, to 
extend the above example so that it draws two connected 
lines, we could do something like this:

move    #6,contrl
move    #3,contrl+2
clr     contrl+6
move    vws_handle,contrl+12
move    x1,pts_in
move    y1,pts_in+2
move    x2,pts_in+4
move    y2,pts_in+6
move    x3,pts_in+8
move    y3,pts_in+10
jsr     vdi

	Notice that we are now loading a 3 into *contrl+2*, 
because the *pts_in* array now contains three points. 
(Remember, a point is really two values.) We've also loaded 
the values *x3* and *y3* (the new point) into the next two 
elements of the *pts_in* array. These values are the next 
point to which the *v_pline* function should draw. We could 
continue drawing lines by adding more and more points to the 
*pts_in* array. We just must be sure that the value in 
*contrl+2* is the total number of points in the array, 
otherwise the function will ignore some of the points.
     If we're drawing a polyline at the smallest width, we 
can choose between six system line types with a call to VDI 
function #15, *vsl_type*:

move    #15,contrl
clr     contrl+2
move    #1,contrl+6
move    vws_handle,contrl+12
move    type,int_in
jsr     vdi

Here, *type* is an integer value from 1 to 7 as follows:
 
     1 solid        ________________
     2 long dash    ___ ___ ___ ___
     3 dots         ...............
     4 dash dot     __.__.__.__.__.
     5 dash         __ __ __ __ __ __
     6 dash dot dot __..__..__..__..__
     7 user defined
 
	Type 7 lets you set up your own line types, but we're 
not going to get into that now. This function returns, in 
*int_out*, the actual line type set.
	Now that we've covered the basics of setting up the VDI 
and calling graphics functions, let's take a quick look at 
some of the other graphics you can draw with the VDI.

--Rectangles--

We can use *v_pline* to draw a standard square-cornered box, 
but the VDI also supplies a function that will let us draw 
rectangles with rounded corners. To do this, we call VDI 
function #11, sub-function #8, *v_rbox*:

move    #11,contrl
move    #2,contrl+2
clr     contrl+6
move    #8,contrl+10
move    vws_handle,contrl+12
move    x1,pts_in
move    y1,pts_in+2
move    x2,pts_in+4
move    y2,pts_in+6
jsr     vdi

	Here, we must supply the pixel coordinates of the 
upper-left and lower-right corners. We place these values 
into the *pts_in* array. Also note that this function call 
requires that you place a sub-function number (8) into 
*contrl+10*. The line attributes--color, style and width--
are used with *v_rbox*, allowing a wide variety of 
rectangles. This function returns no values.
	You can also draw a filled rounded rectangle, using VDI 
function #11, sub-function #9, *v_rfbox*:

move    #11,contrl
move    #2,contrl+2
clr     contrl+6
move    #9,contrl+10
move    vws_handle,contrl+12
move    x1,pts_in
move    y1,pts_in+2
move    x2,pts_in+4
move    y2,pts_in+6
jsr     vdi

	This function uses the currently active fill pattern, 
which we'll learn to set later on.
	To draw a filled rectangle with square corners, use VDI 
function #11, sub-function #1, *v_bar*:

move    #11,contrl
move    #2,contrl+2
move    #0,contrl+6
move    #1,contrl+10
move    vws_handle,contrl+12
move    x1,pts_in
move    y1,pts_in+2
move    x2,pts_in+4
move    y2,pts_in+6
jsr     vdi

	As you may suspect, this function, too, uses the 
current fill pattern.

--Circles, Ellipses, and Arcs--

     GEM's VDI provides several functions for drawing 
various types of curved lines and shapes. If you'd like to 
draw a filled circle, just use VDI Function #11, sub-
function #4, *v_circle*:

move    #11,contrl
move    #3,contrl+2
move    #0,contrl+6
move    #4,contrl+10
move    vws_handle,contrl+12
move    centerx,pts_in
move    centery,pts_in+2
move    #0,pts_in+4
move    #0,pts_in+6
move    radius,pts_in+8
move    #0,pts_in+10
jsr     vdi

	Here, *centerx* and *centery* are the X and Y 
coordinates of the circle's center, and *radius* is the 
circle's radius. Note that *pts_in+4*, *pts_in+6*, and 
*pts_in+10* all contain dummy arguments of 0. The *v_circle* 
function, like *v_rfbox*, uses the current fill attributes.
	You can draw ellipses, too. An ellipse looks something 
like a squashed circle or a solid oval and is drawn by a 
call to VDI function #11, sub-function 5, *v_ellipse*:

move    #11,contrl
move    #2,contrl+2
move    #0,contrl+6
move    #5,contrl+10
move    vws_handle,contrl+12
move    x,pts_in
move    y,pts_in+2
move    hrad,pts_in+4
move    vrad,pts_in+6
jsr     vdi

	Here, the parameters *x* and *y* denote the ellipse's 
center point, and *hrad* and *vrad* are the X and Y radiuses 
in pixels. Once again, the active fill attributes are used. 
No values are returned from the function.
	Arcs are curved lines and are easy to draw with VDI 
function #11, sub-function #2, *v_arc*:

move    #11,contrl
move    #4,contrl+2
move    #2,contrl+6
move    #2,contrl+10
move    vws_handle,contrl+12
move    angle1,int_in
move    angle2,int_in+2
move    x,pts_in
move    y,pts_in+2
move    #0,pts_in+4
move    #0,pts_in+6
move    #0,pts_in+8
move    #0,pts_in+10
move    rad,pts_in+12
move    #0,pts_in+14
jsr     vdi

	The parameters *x*, *y*, and *rad* are the X,Y-
coordinates of the center and the radius, respectively. The 
integers *angle1* and *angle2* are the beginning and ending 
angles of the arc, in tenths of degrees (that is, values 
from 1 to 3600). Note that *pts_in+4*, *pts_in+6*, 
*pts_in+8*, *pts_in+10*, and *pts_in+14* all contain dummy 
arguments that must contain zeroes. No value is returned 
from the function.
	The final call in this family of functions allows you 
to draw pie slices, which help you to draw pie charts. To 
draw a pie slice, use a call to VDI function #11, sub-
function #3, *v_pieslice*:

move    #11,contrl
move    #4,contrl+2
move    #2,contrl+6
move    #3,contrl+10
move    vws_handle,contrl+12
move    angle1,int_in
move    angle2,int_in+2
move    x,pts_in
move    y,pts_in+2
move    #0,pts_in+4
move    #0,pts_in+6
move    #0,pts_in+8
move    #0,pts_in+10
move    rad,pts_in+12
move    #0,pts_in+14
jsr     vdi

	The parameters here are the same as those for the arc 
function. However, the body of the pie slice will be colored 
by whatever fill pattern is active. This function returns no 
values.

--Polymarkers--

     Polymarkers are a number of predefined shapes you can 
use in your graphics. To draw them, you call VDI function 
#7, *v_pmarker*:

move    #7,contrl
move    #3,contrl+2
move    #0,contrl+6
move    vws_handle,contrl+12
move    x1,pts_in
move    y1,pts_in+2
move    x2,pts_in+4
move    y2,pts_in+6
move    x3,pts_in+8
move    y3,pts_in+10
jsr     vdi
	
	The parameter placed in *contrl+2* is the number of 
markers you want to draw. The X,Y coordinates for the 
markers are stored in the *pts_in* array. The above example 
shows three markers being drawn, but you can draw as many as 
you need. This function returns no values.
     What do these markers look like? You have a choice of 
six predefined shapes which (from 1 to 6, respectively) are 
dot, plus sign, asterisk, square, diagonal cross, and 
diamond. To set the polymarker type, call VDI function #18, 
*vsm_type*:

move    #18,contrl
move    #0,contrl+2
move    #1,contrl+6
move    vws_handle,contrl+12
move    type,int_in
jsr     vdi

	Here, *type* is a value from 1 to 6. If you should 
choose a value out of this range, the function will select 
the asterisk as a default. The value chosen will be returned 
in *int_out*.
     There are two other attributes that affect polymarkers: 
color and height. Color is set with a call to VDI function 
#20, *vsm_color*:

move    #20,contrl
move    #0,contrl+2
move    #1,contrl+6
move    vws_handle,contrl+12
move    color,int_in
jsr     vdi

	Here, *color* is a value from 0 to the device maximum. 
All the rules of the *vsl_color* call apply in this case. 
The actual color set is returned in *int_out*.
     You can change the size of all polymarkers, except the 
dot (which always appears in the smallest size), with a call 
to VDI function #19, *vsm_height*:

move    #19,contrl
move    #1,contrl+2
move    #0,contrl+6
move    vws_handle,contrl+12
move    #0,pts_in
move    height,pts_in+2
jsr     vdi

	The parameter *height* is the polymarker's size on the 
Y-axis. The actual height will be the greatest height 
available on the device, less than or equal to the height 
parameter. This will be returned in *pts_out+2*. Note that, 
in the above function call, *pts_in* is always 0, with the 
requested height being placed in *pts_in+2*.

--Fill Patterns--

GEM supplies many patterns we can use to fill our figures. 
There's a series of functions to let us set these patterns 
up the way we want them. The first step is a call to VDI 
function #23, *vsf_interior*:

move    #23,contrl
move    #0,contrl+2
move    #1,contrl+6
move    vws_handle,contrl+12
move    pattern,int_in
jsr     vdi

	Here, *pattern* is a value from 0 to 4. The values are 
interpreted as follows:
 
 0  Hollow (background color)
 1  Solid
 2  Pattern
 3  Hatch
 4  User-defined
 
	The actual pattern set is returned in *int_out*.
	If you choose style 0 or 1, you need go no further, but 
style 2 allows you to choose between 24 different patterns, 
and style 3 provides 12 hatch styles. You choose the pattern 
you wish to use, with a call to VDI function #24, 
*vsf_style*:

move    #24,contrl
move    #0,contrl+2
move    #1,contrl+6
move    vws_handle,contrl+12
move    fill,int_in
jsr     vdi

Here, *fill* is a value from 0 to 23. Consult your reference 
manual to see what these styles look like. The fill that was 
actually set is returned in *int_out*.
     The color of the fill is selected with a call to VDI 
function #25, *vsf_color*:

move    #25,contrl
move    #0,contrl+2
move    #1,contrl+6
move    vws_handle,contrl+12
move    color,int_in
jsr     vdi

	All the rules for the *vsl_color* function apply here, 
also, with the actual color that was set returned in 
*int_out*.
     Finally, you can choose between a visible or invisible 
border for your fill with a call to VDI function #104, 
*vsf_perimeter*:

move    #104,contrl
move    #0,contrl+2
move    #1,contrl+6
move    vws_handle,contrl+12
move    flag,int_in
jsr     vdi

	Here, a *flag* value of 0 will give you an invisible 
border. Any other value will cause the border to be drawn in 
the current fill color.

--Conclusion--

     Now that you've been introduced to many of the graphics 
functions available to you through the VDI, study the sample 
program to see them in action, then take some time and 
experiment with the VDI on your own. See if you can write a 
program to draw a simple picture, or maybe a graph.

--Summary--

* The VDI (Virtual Device Interface) controls most of the 
ST's graphic capabilities and provides some mouse and cursor 
control functions, as well.

* You call VDI functions much like you call AES functions, 
by placing appropriate values into control and input arrays, 
and then calling the function by using a *trap #2* 
instruction.

* To initialize the VDI, you must get a handle to the 
physical screen, open a virtual workstation, and finally 
clear the workstation.

* The AES function #77, *graf_handle*, obtains a handle to 
the physical workstation and returns information about the 
system font.

* The VDI function #100, *v_opnvwk*, obtains a handle to a 
virtual workstation.

* The VDI function #3, *v_clrwk*, clears a workstation, 
flushing all devices and clearing the screen.

* The VDI functions *vsl_color* (#17), *vsl_ends* (#108), 
*vsl_width* (#16), and *vsl_type* (#15) set various line 
attributes.

* The VDI function #6, *v_pline*, draws polylines.

* Other shapes can be drawn using the VDI functions *v_rbox* 
(#11,8), *v_rfbox* (#11,9), *v_bar* (#11,1), *v_circle* 
(#11,4), *v_ellipse* (#11,5), *v_arc* (#11,2), and 
*v_pieslice* (#11,3).

* Polymarkers are drawn by VDI function #7, *v_pmarker*.

* The polymarker attributes can be set by the VDI functions 
*vsm_type* (#18), *vsm_color* (#20), and *vsm_height* (#19).

* The current fill pattern's attributes can be set by the 
VDI functions *vsf_interior* (#23), *vsf_style* (#24), 
*vsf_color* (#25), and *vsf_perimeter* (#104).


CW_PROG5.S (Source of the chapiter)
CW_PROG5MAC.S (Source of the chapiter)


Back to Assembly_language_tutorials