Professional GEM - Part IX - VDI Graphics: Lines and solids: Difference between revisions

From Atari Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
 
Line 1: Line 1:
  +
{{Professional GEM}}
<pre>
 
   
   
  +
This issue of ST PRO GEM is the first in a series of two which will explore the fundamentals of VDI graphics output. In this installment, we will take a look at the commands necessary to output simple graphics such as lines, squares and circles as well as more complex figures such as polygons. The following episode will take a first look at graphics text output, with an emphasis on ways to optimize its drawing speed. It will also include another installment of ONLINE Feedback. As usual, there is a download with this column. You should find it under the name GEMCL9.C in DL3 of ATARI16 (PCS-58).
Professional GEM 68
 
   
   
  +
==A bit of history==
PART IX
 
   
  +
One of the reasons that the VDI can be confusing is that drawing anything at all, even a simple line, can involve setting around four different VDI parameters before making the draw call! (Given the state of the GEM documents, just FINDING them can be fun!) Looking backwards a bit sheds some light on why the VDI is structured this way, and also gives us a framework for organizing a discussion of graphics output.
VDI Graphics Lines and Solids
 
   
  +
The GEM VDI closely follows the so-called GKS standard, which defines capabilities and calling sequences for a standardized graphic input/output system. GKS is itself an evolution from an early system called "Core". Both of these standards were born in the days when pen plotters, vectored graphics displays, and minicomputers were the latest items. So, if you wonder why setting the drawing pen color is a separate command, just think back a few years when it actually meant what it says! (The cynical may choose instead to ponder the benefits of standardization.)
   
  +
When doing VDI output, it helps if you pretend that the display screen really is a plotter or some other separate device, which has its own internal parameters which you can set up and read back. The class of VDI commands called Attribute Functions let you set the parameters. Output functions cause the "device" to actually draw someone once it is configured. The Inquire Functions let you read back the parameters if necessary.
This issue of ST PRO GEM is the first in a series of
 
two which will explore the fundamentals of VDI graphics
 
output. In this installment, we will take a look at the
 
commands necessary to output simple graphics such as lines,
 
squares and circles as well as more complex figures such as
 
polygons. The following episode will take a first look at
 
graphics text output, with an emphasis on ways to optimize
 
its drawing speed. It will also include another
 
installment of ONLINE Feedback. As usual, there is a
 
download with this column. You should find it under the
 
name GEMCL9.C in DL3 of ATARI16 (PCS-58).
 
   
  +
There are two parameters which are relevant no matter what type of object you are trying to draw. They are the writing mode and the clipping rectangle. The writing mode is similar to that discussed in the column on raster operations.
   
  +
It determines what effect the figure you are drawing will have on data already on the screen. The writing mode is set with the call:
A BIT OF HISTORY
 
   
  +
<pre>
One of the reasons that the VDI can be confusing is
 
  +
vswrmode(vdihandle, mode);
that drawing anything at all, even a simple line, can involve
 
  +
</pre>
setting around four different VDI parameters before making the
 
draw call! (Given the state of the GEM documents, just
 
FINDING them can be fun!) Looking backwards a bit sheds some
 
light on why the VDI is structured this way, and also gives us
 
a framework for organizing a discussion of graphics output.
 
   
  +
Vdihandle, here and below, is the handle obtained from grafhandle at the beginning of the program. Mode is a word which may be one of:
The GEM VDI closely follows the so-called GKS standard,
 
which defines capabilities and calling sequences for a
 
standardized graphic input/output system. GKS is itself an
 
evolution from an early system called "Core". Both of these
 
standards were born in the days when pen plotters, vectored
 
graphics displays, and minicomputers were the latest
 
items. So, if you wonder why setting the drawing pen color
 
is a separate command, just think back a few years when it
 
actually meant what it says! (The cynical may choose
 
instead to ponder the benefits of standardization.)
 
   
  +
1 - Replace Mode
When doing VDI output, it helps if you pretend that
 
  +
2 - Transparent Mode
the display screen really is a plotter or some other separate
 
  +
3 - XOR mode
device, which has its own internal parameters which you can
 
  +
4 - Reverse Transparent Mode
set up and read back. The class of VDI commands called
 
Attribute Functions let you set the parameters. Output
 
Functions cause the "device" to actually draw someone once it
 
is configured. The Inquire Functions let you read back the
 
parameters if necessary.
 
   
  +
In replace mode, whatever is on the screen is overwritten. If you are writing characters, this means the background of each character cell will be erased.
There are two parameters which are relevant no matter
 
what type of object you are trying to draw. They are the
 
writing mode and the clipping rectangle. The writing mode is
 
similar to that discussed in the column on raster operations.
 
   
  +
In transparent mode, only the pixels directly under the "positive" part of the image, that is, where 1-bits are being written, will be changed. When writing characters, the background of the cell will be left intact.
   
  +
In XOR mode, an exclusive or is performed between the screen contents and what is being written. The effect is to reverse the image under areas where a 1-bit occurs.
 
   
  +
Reverse transparent is like transparent, but with a "reverse color scheme". That is, only places where a 0-bit is to be put are changed to the current writing color. When you write characters in reverse transparent (over white), the effect is reverse video.
   
  +
The other common parameter is the clipping rectangle. It defines the area on the screen where the VDI is permitted to draw. Any output which would fall outside of this area is ignored; it is effectively a null operation. The clip rectangle is set with the call:
Professional GEM Part IX 69
 
   
  +
<pre>
  +
vsclip(vdihandle, flag, pxy);
  +
</pre>
   
  +
Pxy is a four-word array. Pxy[0] and pxy[1] are the X and Y screen coordinates, respectively, of one corner of your clipping rectangle. Pxy[2] and pxy[3] are the coordinates of the diagonally opposite corner of the rectangle. (When working with the AES, use of a GRECT to define the clip is often more convenient. The routine setclip() in the download does this.)
It determines what effect the figure you are drawing will have
 
on data already on the screen. The writing mode is set with the
 
call:
 
   
  +
Flag is set to TRUE if clipping is to be used. If you set it to FALSE, the entire screen is assumed to be fair game.
vswrmode(vdihandle, mode);
 
   
  +
Normally, you should walk the rectangle list for the current window to obtain your clipping rectangles. (See ST PRO GEM #2 for more details.) However, turning off the clip speeds up all output operations, particularly text. You may do this ONLY when you are absolutely certain that the figure you are drawing will not extend out of the top-most window, or out of a dialog.
Vdihandle, here and below, is the handle obtained from
 
grafhandle at the beginning of the program. Mode is a word
 
which may be one of:
 
   
1 - Replace Mode
 
2 - Transparent Mode
 
3 - XOR mode
 
4 - Reverse Transparent Mode
 
   
  +
==The line forms on the left==
In replace mode, whatever is on the screen is
 
overwritten. If you are writing characters, this means the
 
background of each character cell will be erased.
 
   
  +
The VDI line drawing operations include polyline, arc, elliptical arc, and rounded rectangle. I'll first look at the Attribute Functions for line drawing, then go through the drawing primitives themselves.
In transparent mode, only the pixels directly under
 
the "positive" part of the image, that is, where 1-bits are
 
being written, will be changed. When writing characters, the
 
background of the cell will be left intact.
 
   
  +
The most common used line attributes are color and width. The color is set with:
In XOR mode, an exclusive or is performed between the
 
screen contents and what is being written. The effect is to
 
reverse the image under areas where a 1-bit occurs.
 
   
  +
<pre>
Reverse transparent is like transparent, but with a
 
  +
vslcolor(vdihandle, color);
"reverse color scheme". That is, only places where a 0-bit
 
  +
</pre>
is to be put are changed to the current writing
 
color. When you write characters in reverse transparent
 
(over white), the effect is reverse video.
 
   
  +
where color is one of the standard VDI color indices, ranging from zero to 15. (As discussed in column #6, the color which actually appears will depend on the pallette setting of your ST.)
The other common parameter is the clipping rectangle.
 
It defines the area on the screen where the VDI is permitted to
 
draw. Any output which would fall outside of this area is
 
ignored; it is effectively a null operation. The clip
 
rectangle is set with the call:
 
   
  +
The line width may only be set to ODD positive values, for reasons of symmetry. If you try to set an even value, the VDI will take the next lower odd value. The call is:
vsclip(vdihandle, flag, pxy);
 
   
  +
<pre>
Pxy is a four-word array. Pxy[0] and pxy[1] are the X and Y
 
  +
vslwidth(vdihandle, width);
screen coordinates, respectively, of one corner of your
 
  +
</pre>
clipping rectangle. Pxy[2] and pxy[3] are the
 
coordinates of the diagonally opposite corner of the
 
rectangle. (When working with the AES, use of a GRECT to
 
define the clip is often more convenient. The routine
 
setclip() in the download does this.)
 
   
  +
The two less used line parameters are the end style and pattern. With the end style you can cause the output line to have rounded ends or arrowhead ends. The call is:
Flag is set to TRUE if clipping is to be used. If you set
 
it to FALSE, the entire screen is assumed to be fair game.
 
   
  +
<pre>
  +
vslends(vdihandle, beginstyle, endstyle);
  +
</pre>
   
  +
Beginstyle and endstyle are each words which may have the values zero for square ends (the default), one for arrowed ends, or two for rounded ends. They determine the styles for the starting and finishing ends of the line, respectively.
 
   
  +
The line pattern attribute can select dotted or dashed lines as well as more complicated patterns. Before continuing, you should note one warning: VDI line output DOES NOT compensate for pixel aspect ratio. That is, the dashes on a line will look twice as long drawn vertically on a medium-res ST screen as they do when drawn horizontally. The command for setting the pattern is:
   
  +
<pre>
Professional GEM Part IX 70
 
  +
vsltype(vdihandle, style);
  +
</pre>
   
  +
Style is a word with a value between 1 and 7. The styles selected are:
   
  +
1 - Solid (the default)
  +
2 - Long Dash
  +
3 - Dot
  +
4 - Dash, Dot
  +
5 - Dash
  +
6 - Dash, Dot, Dot
  +
7 - (User defined style)
   
  +
The user defined style is determined by a 16-bit pattern supplied by the application. A one bit in the pattern turns a pixel on, a zero bit leaves it off. The pattern is cycled through repeatedly, using the high bit first. To use a custom style, you must make the call:
Normally, you should walk the rectangle list for the
 
current window to obtain your clipping rectangles. (See ST PRO
 
GEM #2 for more details.) However, turning off the clip speeds
 
up all output operations, particularly text. You may do this
 
ONLY when you are absolutely certain that the figure you are
 
drawing will not extend out of the top-most window, or out of a
 
dialog.
 
   
  +
<pre>
  +
vsludsty(vdihandle, pattern);
  +
</pre>
   
  +
before doing vsltype().
THE LINE FORMS ON THE LEFT
 
   
  +
As I mentioned above, the line type Output Functions available are polyline, circular and ellliptical arc, and rounded rectangle. Each has its own calling sequence. The call for a polyline is:
The VDI line drawing operations include polyline,
 
arc, elliptical arc, and rounded rectangle. I'll first look
 
at the Attribute Functions for line drawing, then go through
 
the drawing primitives themselves.
 
   
  +
<pre>
The most common used line attributes are color and
 
  +
vpline(vdihandle, points, pxy);
width. The color is set with:
 
  +
</pre>
   
  +
Points tells how many vertices will appear on the polyline. For instance, a straight line has two vertices: the end and the beginning. A closed square would have five, with the first and last identical. (There is no requirement that the figure described be closed.)
vslcolor(vdihandle, color);
 
   
  +
The pxy array contains the X and Y raster coordinates for the vertices, with a total of 2 * points entries. Pxy[0] and pxy[1] are the first X-Y pair, and so on.
where color is one of the standard VDI color indices, ranging
 
from zero to 15. (As discussed in column #6, the color
 
which actually appears will depend on the pallette setting of
 
your ST.)
 
   
  +
If you happen to be using the XOR drawing mode, remember that drawing twice at a point is equivalent to no drawing at all. Therefore, for a figure to appear closed in XOR mode, the final stroke should actually stop one pixel short of the origin of the figure.
The line width may only be set to ODD positive values,
 
for reasons of symmetry. If you try to set an even value,
 
the VDI will take the next lower odd value. The call is:
 
   
  +
You may notice that in the GEM VDI manual the rounded rectangle and arc commands are referred to as GDPs (Generalized Drawing Primitives). This denotation is historical in nature, and has no effect unless you are writing your own VDI bindings.
vslwidth(vdihandle, width);
 
   
  +
The rounded rectangle is nice to use for customized buttons in windows and dialogs. It gives a "softer" look to the screen than the standard square objects. The drawing command is:
The two less used line parameters are the end style and
 
pattern. With the end style you can cause the output line
 
to have rounded ends or arrowhead ends. The call is:
 
   
  +
<pre>
vslends(vdihandle, beginstyle, endstyle);
 
  +
vrbox(vdihandle, pxy);
  +
</pre>
   
  +
Pxy is a four word array giving opposite corners of the rectangle, just as for the vsclip() call. The corner rounding occurs within the confines of this rectangle. Nothing will protrude unless you specify a line thickness greater than one. The corner rounding is approximately
Beginstyle and endstyle are each words which may have the
 
  +
circular; there is no user control over the degree or shape of rounding.
values zero for square ends (the default), one for arrowed
 
ends, or two for rounded ends. They determine the styles
 
for the starting and finishing ends of the line, respectively.
 
   
  +
Both the arc and elliptical arc commands use a curious method of specifying angles. The units are tenths of degrees, so an entire circle is 3600 units. The count starts at ninety degrees right of vertical, and proceeds counterclockwise. This means that "3 o'clock" is 0 units, "noon" is 900 units, "9 o'clock" is 1800 units, and 2700 units is at "half-past". 3600 units take you back to "3 o'clock".
The line pattern attribute can select dotted or dashed
 
lines as well as more complicated patterns. Before
 
continuing, you should note one warning: VDI line output DOES
 
NOT compensate for pixel aspect ratio. That is, the dashes on a
 
line will look twice as long drawn vertically on a medium-res ST
 
screen as they do when drawn horizontally. The command for
 
setting the pattern is:
 
   
  +
The command for drawing a circular arc is:
   
  +
<pre>
  +
varc(vdihandle, x, y, radius, begin, end);
  +
</pre>
   
  +
X and y specify the raster coordinates of the center of the circle. Radius specifies the distance from center to all points on the arc. Begin and end are angles given in units as described above, both with values between 0 and 3600. The drawing of the arc ALWAYS proceeds counterclockwise, in the direction of increasing arc number. So values of 0 and 900 for begin and end would draw a quarter circle from
 
  +
"three o'clock" to "noon". Reversing the values would draw the other three quarters of the circle.
   
  +
A varc() command which specifies a "full turn" is the fastest way to draw a complete circle on the screen. Be warned, however, that the circle drawing algorithm used in the VDI seems to have some serious shortcomings at small radii! You can experiment with the CIRCLE primitive in ST Logo, which uses varc(), to see what I mean.
   
  +
Notice that if you want an arc to strike one or more given points on the screen, then you are in for some trigonometry. If your math is a bit rusty, I highly recommend the book "A Programmer's Geometry", by Bowyer and Woodwark, published by Butterworths (London, Boston, Toronto).
Professional GEM Part IX 71
 
   
  +
Finally, the elliptical arc is generated with:
   
  +
<pre>
  +
vellarc(vdihandle, x, y, xrad, yrad, begin, end);
  +
</pre>
   
  +
X, y, begin, and end are just as before. Xrad and yrad give the horizontal and vertical radii of the defining ellipse. This means that the distance of the arc from center will be yrad pixels at "noon" and "half-past", and it will be xrad pixels at "3 and 9 o'clock". Again, the arc is always drawn counterclockwise.
vsltype(vdihandle, style);
 
   
  +
There are a number of approaches to keeping the VDI's attributes "in sync" with the actual output operations. Probably the LEAST efficient is to use the Inquire Functions to determine the current attributes. For this reason, I have omitted a discussion of these calls from this column.
Style is a word with a value between 1 and 7. The styles
 
selected are:
 
   
  +
Another idea is to keep a local copy of all significant attributes, use a test-before-set method to minimize the number of Attribute Functions which need to be called. This puts a burden on the programmer to be sure that the local attribute variables are correctly maintained. Failure to do so may result in obscure drawing bugs. If your application employs user defined AES objects, you must be very careful because GEM might call your draw code in the middle of a VDI operation (particularly if the user defined objects are in the menu).
1 - Solid (the default)
 
2 - Long Dash
 
3 - Dot
 
4 - Dash, Dot
 
5 - Dash
 
6 - Dash, Dot, Dot
 
7 - (User defined style)
 
   
  +
Always setting the attributes is a simplistic method, but often proves most effective. The routines plperim() and rrperim() in the download exhibit this approach. Modification for other primitives is straightforward. This style is most useful when drawing operations are scattered throughout the program, so that keeping track of the current attribute status is difficult. Although inherently inefficient, the difference is not very noticable if the drawing operation requested is itself time consuming.
The user defined style is determined by a 16-bit
 
pattern supplied by the application. A one bit in the
 
pattern turns a pixel on, a zero bit leaves it off. The
 
pattern is cycled through repeatedly, using the high bit
 
first. To use a custom style, you must make the call:
 
   
  +
In many applications, such as data graphing programs or "Draw" packages, the output operations are centralized, forming the primary functionality of the code. In this case, it is both easy and efficient to keep track of attribute status between successive drawing operations.
vsludsty(vdihandle, pattern);
 
   
before doing vsltype().
 
   
  +
==Solids==
As I mentioned above, the line type Output
 
Functions available are polyline, circular and ellliptical arc,
 
and rounded rectangle. Each has its own calling sequence.
 
The call for a polyline is:
 
   
  +
There are a wider variety of VDI calls for drawing solid figures. They include rectangle or bar, disk, pie, ellipse, elliptical pie, filled rounded rectangle, and filled polygonal area. Of course, filled figure calls also have their own set of attributes which you will need to set.
vpline(vdihandle, points, pxy);
 
   
  +
The fill color index determines what pen color will be used to draw the solid. It is set with:
Points tells how many vertices will appear on the polyline. For
 
instance, a straight line has two vertices: the end and
 
the beginning. A closed square would have five, with the
 
first and last identical. (There is no requirement
 
that the figure described be closed.)
 
   
  +
<pre>
The pxy array contains the X and Y raster coordinates for
 
  +
vsfcolor(vdihandle, color);
the vertices, with a total of 2 * points entries. Pxy[0] and
 
  +
</pre>
pxy[1] are the first X-Y pair, and so on.
 
   
  +
Color is just the same as for line drawing. A solid may or may not have a visible border. This is determined with the call:
If you happen to be using the XOR drawing mode, remember
 
that drawing twice at a point is equivalent to no drawing
 
at all. Therefore, for a figure to appear closed in XOR
 
mode, the final stroke should actually stop one pixel short of
 
the origin of the figure.
 
   
  +
<pre>
You may notice that in the GEM VDI manual the
 
  +
vsfperimeter(vdihandle, vis);
rounded rectangle and arc commands are referred to as GDPs
 
  +
</pre>
(Generalized Drawing Primitives). This denotation is historical
 
in nature, and has no effect unless you are writing your own
 
VDI bindings.
 
   
  +
Vis is a Boolean. If it is true, the figure will be given a solid one pixel outline in the current fill color index. This is often useful to improve the appearance of solids drawn with a dithered fill pattern. If vis is false, then no outline is drawn.
   
  +
There are two parameters which together determine the pattern used to fill your figure. They are called interior style and interior index. The style determines the general type of fill, and the index is used to select a particular pattern if necessary. The style is set with the command:
 
   
  +
<pre>
  +
vsfinterior(vdihandle, style);
  +
</pre>
   
  +
where style is a value from zero through four. Zero selects a hollow style: the fill is performed in color zero, which is usually white. Style one selects a solid fill with the current fill color. A style of two is called "pattern" and a three is called "hatch", which are terms somewhat suggestive of the options which can then be selected using the interior index. Style four selects the user defined pattern, which is described below.
Professional GEM Part IX 72
 
   
  +
The interior index is only significant for styles two and three. To set it, use:
   
  +
<pre>
  +
vsfstyle(vdihandle, index);
  +
</pre>
   
  +
(Be careful here: it is very easy to confuse this call with the one above due to the unfortunate choice of name.) The index selects the actual drawing pattern. The GEM VDI manual shows fill patterns corresponding to index values from 1 to 24 under style 2, and from 1 to 12 under style 3. However, some of these are implemented differently on the ST. Rather than try to describe them all here, I would suggest that you experiment. You can do so easily in ST Logo by opening the Graphics Settings dialog and playing with the style and index values there.
The rounded rectangle is nice to use for customized
 
buttons in windows and dialogs. It gives a "softer" look to
 
the screen than the standard square objects. The drawing
 
command is:
 
   
  +
The user defined style gives you some interesting options for multi-color fills. It is set with:
vrbox(vdihandle, pxy);
 
   
  +
<pre>
Pxy is a four word array giving opposite corners of the
 
  +
vsfudpat(vdihandle, pattern, planes);
rectangle, just as for the vsclip() call. The corner
 
  +
</pre>
rounding occurs within the confines of this rectangle.
 
Nothing will protrude unless you specify a line thickness
 
greater than one. The corner rounding is approximately
 
circular; there is no user control over the degree or shape of
 
rounding.
 
   
  +
Planes determines the number of color planes in the pattern which you supply. It is set to one if you are setting a monochrome pattern. (Remember, monochrome is not necessarily black). It may be set to higher values on color systems: two for ST medium-res mode, or four for low-res mode. If you use a number lower than four under low-res, the other planes are zero filled.
Both the arc and elliptical arc commands use a curious
 
method of specifying angles. The units are tenths of
 
degrees, so an entire circle is 3600 units. The count
 
starts at ninety degrees right of vertical, and proceeds
 
counterclockwise. This means that "3 o'clock" is 0 units,
 
"noon" is 900 units, "9 o'clock" is 1800 units, and 2700 units
 
is at "half-past". 3600 units take you back to "3 o'clock".
 
   
  +
The pattern parameter is an array of words which is a multiple of 16 words long. The pattern determined is 16 by 16 pixels, with each word forming one row of the pattern. The rows are arranged top to bottom, with the most significant bit to the left. If you have selected a multi-plane pattern, the entire first plane is stored, then the second, and so on.
The command for drawing a circular arc is:
 
   
  +
Note that to use a multi-plane pattern, you set the writing mode to replace using vswrmode(). Since the each plane can be different, you can produce multi-colored patterns. If you use a writing color other than black, some of the planes may "disappear".
varc(vdihandle, x, y, radius, begin, end);
 
   
  +
Most of the solids Output Functions have analogous line drawing commands. The polyline command corresponds to the filled area primitive. The filled area routine is:
X and y specify the raster coordinates of the center of the
 
circle. Radius specifies the distance from center to all
 
points on the arc. Begin and end are angles given in units as
 
described above, both with values between 0 and 3600. The
 
drawing of the arc ALWAYS proceeds counterclockwise, in
 
the direction of increasing arc number. So values of 0 and
 
900 for begin and end would draw a quarter circle from
 
"three o'clock" to "noon". Reversing the values would draw
 
the other three quarters of the circle.
 
   
  +
<pre>
A varc() command which specifies a "full turn" is
 
  +
vfillarea(vdihandle, count, pxy);
the fastest way to draw a complete circle on the screen. Be
 
  +
</pre>
warned, however, that the circle drawing algorithm used in the
 
VDI seems to have some serious shortcomings at small
 
radii! You can experiment with the CIRCLE primitive in
 
ST Logo, which uses varc(), to see what I mean.
 
   
  +
Count and pxy are just the same as for vpline(). If the polygon defined by pxy is not closed, then the VDI will force closure with a straight line from the last to the first point. The polygon may be concave or self-intersecting. If perimeter show is on, the area will be outlined.
Notice that if you want an arc to strike one or more
 
given points on the screen, then you are in for some
 
trigonometry. If your math is a bit rusty, I highly
 
recommend the book "A Programmer's Geometry", by Bowyer
 
and Woodwark, published by Butterworths (London, Boston,
 
Toronto).
 
   
  +
One note of caution is necessary for both vfillarea() and vpline(). There is a limit on the number of points which may be stored in pxy[]. This limit occurs because the contents of pxy[] are copied to the intin[] binding array before the VDI is called. You can determine the maximum number of vertices by checking intout[14] after using the extended inquire function vqextnd().
   
  +
For reasons unknown to this writer, there are TWO different filled rectangle commands in the VDI. The first is
   
  +
<pre>
 
  +
vrrecfl(vdihandle, pxy);
  +
</pre>
   
  +
Pxy is a four word array defining two opposite corners of the rectangle, just as in vsclip(). Vrrecfl() uses the fill attribute settings, except that it NEVER draws a perimeter.
   
  +
The other rectangle routine is vbar(), with exactly the same arguments as vrrecfl(). The only difference is that the perimeter setting IS respected. These two routines are the fastest way to produce a solid rectangle using the VDI. They may be used in XOR mode with a BLACK fill color to quickly invert an area of the screen. You can improve the speed even further by turning off the clip (if possible), and byte aligning the left and right edges of the rectangle.
Professional GEM Part IX 73
 
   
  +
Separate commands are provided for solid circle and ellipse. The circle call is:
   
  +
<pre>
  +
vcircle(vdihandle, x, y, radius);
  +
</pre>
   
  +
and the ellipse command is:
Finally, the elliptical arc is generated with:
 
   
  +
<pre>
vellarc(vdihandle, x, y, xrad, yrad, begin, end);
 
  +
vellipse(vdihandle, x, y, xrad, yrad);
  +
</pre>
   
  +
All of the parameters are identical to those given above for varc() and vellarc(). The solid analogue of an arc is a "pie slice". The VDI pie commands are:
X, y, begin, and end are just as before. Xrad and yrad give
 
the horizontal and vertical radii of the defining ellipse. This
 
means that the distance of the arc from center will be yrad
 
pixels at "noon" and "half-past", and it will be xrad pixels
 
at "3 and 9 o'clock". Again, the arc is always drawn
 
counterclockwise.
 
   
  +
<pre>
There are a number of approaches to keeping the
 
  +
vpieslice(vdihandle, x, y, radius, begin, end);
VDI's attributes "in sync" with the actual output operations.
 
  +
</pre>
Probably the LEAST efficient is to use the Inquire Functions
 
to determine the current attributes. For this reason, I
 
have omitted a discussion of these calls from this column.
 
   
  +
for a slice from a circular pie, and
Another idea is to keep a local copy of all
 
significant attributes, use a test-before-set method to minimize
 
the number of Attribute Functions which need to be called.
 
This puts a burden on the programmer to be sure that the local
 
attribute variables are correctly maintained. Failure to do
 
so may result in obscure drawing bugs. If your application
 
employs user defined AES objects, you must be very careful
 
because GEM might call your draw code in the middle of a VDI
 
operation (particularly if the user defined objects are in the
 
menu).
 
   
  +
<pre>
Always setting the attributes is a simplistic method,
 
  +
vellpie(vdihandle, x, y, xrad, yrad, begin, end);
but often proves most effective. The routines
 
  +
</pre>
plperim() and rrperim() in the download exhibit this
 
approach. Modification for other primitives is
 
straightforward. This style is most useful when drawing
 
operations are scattered throughout the program, so that
 
keeping track of the current attribute status is difficult.
 
Although inherently inefficient, the difference is not very
 
noticable if the drawing operation requested is itself time
 
consuming.
 
   
  +
for a slice from a "squashed" pie. Again, the parameters are identical to those in varc() and vellarc(). The units and drawing order of angles are also the same. The final solids Output Function is:
In many applications, such as data graphing programs
 
or "Draw" packages, the output operations are centralized,
 
forming the primary functionality of the code. In this case,
 
it is both easy and efficient to keep track of attribute
 
status between successive drawing operations.
 
   
  +
<pre>
  +
vrfbox(vdihandle, pxy);
  +
</pre>
   
  +
which draws a filled rounded rectangle. The pxy array defines two two opposite corners of the bounding box, as shown for vsclip().
SOLIDS
 
   
  +
The issues involved in correctly setting the VDI attributes for a fill operation are identical to those in drawing lines. For those who want to employ the "always set" method, I have again included two skeleton routines in the download, which can be modified as desired.
There are a wider variety of VDI calls for drawing
 
solid figures. They include rectangle or bar, disk, pie,
 
ellipse, elliptical pie, filled rounded rectangle, and
 
   
   
  +
==To be continued==
 
 
 
Professional GEM Part IX 74
 
 
 
filled polygonal area. Of course, filled figure calls also
 
have their own set of attributes which you will need to set.
 
 
The fill color index determines what pen color will be
 
used to draw the solid. It is set with:
 
 
vsfcolor(vdihandle, color);
 
 
Color is just the same as for line drawing. A solid may or
 
may not have a visible border. This is determined with the
 
call:
 
 
vsfperimeter(vdihandle, vis);
 
 
Vis is a Boolean. If it is true, the figure will be given a
 
solid one pixel outline in the current fill color index. This
 
is often useful to improve the appearance of solids drawn
 
with a dithered fill pattern. If vis is false, then no outline
 
is drawn.
 
 
There are two parameters which together determine the
 
pattern used to fill your figure. They are called interior
 
style and interior index. The style determines the general
 
type of fill, and the index is used to select a particular
 
pattern if necessary. The style is set with the command:
 
 
vsfinterior(vdihandle, style);
 
 
where style is a value from zero through four. Zero selects a
 
hollow style: the fill is performed in color zero, which
 
is usually white. Style one selects a solid fill with the
 
current fill color. A style of two is called "pattern" and a
 
three is called "hatch", which are terms somewhat suggestive of
 
the options which can then be selected using the interior
 
index. Style four selects the user defined pattern, which is
 
described below.
 
 
The interior index is only significant for styles two
 
and three. To set it, use:
 
 
vsfstyle(vdihandle, index);
 
 
(Be careful here: it is very easy to confuse this call with the
 
one above due to the unfortunate choice of name.) The
 
index selects the actual drawing pattern. The GEM VDI manual
 
shows fill patterns corresponding to index values from 1 to 24
 
under style 2, and from 1 to 12 under style 3. However,
 
some of these are implemented differently on the ST.
 
Rather than try to describe them all here, I would suggest that
 
you experiment. You can do so easily in ST Logo by opening
 
the Graphics Settings dialog and playing with the style and
 
index values there.
 
 
 
 
 
 
Professional GEM Part IX 75
 
 
 
 
The user defined style gives you some interesting options
 
for multi-color fills. It is set with:
 
 
vsfudpat(vdihandle, pattern, planes);
 
 
Planes determines the number of color planes in the pattern
 
which you supply. It is set to one if you are setting
 
a monochrome pattern. (Remember, monochrome is not
 
necessarily black). It may be set to higher values on color
 
systems: two for ST medium-res mode, or four for low-res mode.
 
If you use a number lower than four under low-res, the other
 
planes are zero filled.
 
 
The pattern parameter is an array of words which is
 
a multiple of 16 words long. The pattern determined is 16
 
by 16 pixels, with each word forming one row of the pattern.
 
The rows are arranged top to bottom, with the most significant
 
bit to the left. If you have selected a multi-plane
 
pattern, the entire first plane is stored, then the second,
 
and so on.
 
 
Note that to use a multi-plane pattern, you set the writing
 
mode to replace using vswrmode(). Since the each plane can
 
be different, you can produce multi-colored patterns. If you
 
use a writing color other than black, some of the
 
planes may "disappear".
 
 
Most of the solids Output Functions have analogous
 
line drawing commands. The polyline command corresponds to the
 
filled area primitive. The filled area routine is:
 
 
vfillarea(vdihandle, count, pxy);
 
 
Count and pxy are just the same as for vpline(). If the
 
polygon defined by pxy is not closed, then the VDI will
 
force closure with a straight line from the last to the
 
first point. The polygon may be concave or
 
self-intersecting. If perimeter show is on, the area will be
 
outlined.
 
 
One note of caution is necessary for both vfillarea()
 
and vpline(). There is a limit on the number of points which
 
may be stored in pxy[]. This limit occurs because the contents
 
of pxy[] are copied to the intin[] binding array before the VDI
 
is called. You can determine the maximum number of
 
vertices by checking intout[14] after using the extended
 
inquire function vqextnd().
 
 
For reasons unknown to this writer, there are TWO
 
different filled rectangle commands in the VDI. The first is
 
 
 
 
 
 
 
Professional GEM Part IX 76
 
 
 
 
vrrecfl(vdihandle, pxy);
 
 
Pxy is a four word array defining two opposite corners of the
 
rectangle, just as in vsclip(). Vrrecfl() uses the fill
 
attribute settings, except that it NEVER draws a perimeter.
 
 
The other rectangle routine is vbar(), with exactly the
 
same arguments as vrrecfl(). The only difference is
 
that the perimeter setting IS respected. These two
 
routines are the fastest way to produce a solid rectangle
 
using the VDI. They may be used in XOR mode with a BLACK fill
 
color to quickly invert an area of the screen. You can
 
improve the speed even further by turning off the clip (if
 
possible), and byte aligning the left and right edges of the
 
rectangle.
 
 
Separate commands are provided for solid circle and
 
ellipse. The circle call is:
 
 
vcircle(vdihandle, x, y, radius);
 
 
and the ellipse command is:
 
 
vellipse(vdihandle, x, y, xrad, yrad);
 
 
All of the parameters are identical to those given above for
 
varc() and vellarc(). The solid analogue of an arc is a "pie
 
slice". The VDI pie commands are:
 
 
vpieslice(vdihandle, x, y, radius, begin, end);
 
 
for a slice from a circular pie, and
 
 
vellpie(vdihandle, x, y, xrad, yrad, begin, end);
 
 
for a slice from a "squashed" pie. Again, the parameters are
 
identical to those in varc() and vellarc(). The units and
 
drawing order of angles are also the same. The final
 
solids Output Function is:
 
 
vrfbox(vdihandle, pxy);
 
 
which draws a filled rounded rectangle. The pxy array defines
 
two two opposite corners of the bounding box, as shown
 
for vsclip().
 
 
The issues involved in correctly setting the VDI
 
attributes for a fill operation are identical to those in
 
drawing lines. For those who want to employ the "always set"
 
method, I have again included two skeleton routines in the
 
download, which can be modified as desired.
 
 
 
 
 
 
Professional GEM Part IX 77
 
 
 
 
 
TO BE CONTINUED
 
 
This concludes the first part of our expedition through
 
basic VDI operations. The next issue will tackle the
 
problems of drawing bit mapped text at a reasonable speed.
 
This first pass will not attempt to tackle alternate or
 
proportional fonts, or alternate font sizes. Instead, I
 
will concentrate on techniques for squeezing greater
 
performance out of the standard monospaced system fonts.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
</pre>
 
   
  +
This concludes the first part of our expedition through basic VDI operations. The next issue will tackle the problems of drawing bit mapped text at a reasonable speed. This first pass will not attempt to tackle alternate or proportional fonts, or alternate font sizes. Instead, I will concentrate on techniques for squeezing greater performance out of the standard monospaced system fonts.
Back to [[Professional_GEM]]
 

Latest revision as of 23:37, 12 October 2006

Professional GEM
Part I -- Windows
In the beginningOpen sesameCleaning upThose fat slidersComing up nextFeedback
Part II -- Windows
ExcelsiorRedrawing windowsCaveat emptorInto the bitsA small confessionWindow control requestWindow slider messagesA common bugDept. of dirty tricksA sin of omissionComing soon
Part III -- The dialog handler
A meaningful dialogDefining termsBug alert!A handy trickClean upRecapButton ButtonWho's got the button?Coming up nextDispell gremlins
Part IV -- Resource structure
A maze of twisty little passagesPutting it to workLetters, we get lettersStraw poll!Stay tuned!
Part V -- Resource tree structures
How GEM does itThought experimentsA treewalker of our own
Part VI -- Raster operations
Seasons greetingsDefining termsMonochrome vs. colorStandard vs. device-specific formatEven-word vs. fringesMFDB'sLet's operateTransform formCopy raster opaqueCopy raster transparentThe mode parameterReplace modeErase modeXor modeTransparent modeReverse transparent modeThe problem of colorOptimizing raster operationsAvoid merged copiesMove to corresponding pixelsAvoid fringesUse another methodFeedback resultsThe next questionComing up soon
Part VII -- Menu structures
Happy new yearMenu basicsMenu structuresUsing the menuGetting fancyCheck please?Now you see it now you don'tLunch and dinner menusDo it yourselfMake prettyThat's it for now!
Part VIII -- User interfaces
And now for something completely different!Credit where it's dueFingertipsMusclesEyesShort-term memoryChunkingThink!Are we not men?Of modes and bandwidthTo do is to be!Amen...
Part IX -- VDI Graphics: Lines and solids
A bit of historyThe line forms on the leftSolidsTo be continued
Appendices
Main page


This issue of ST PRO GEM is the first in a series of two which will explore the fundamentals of VDI graphics output. In this installment, we will take a look at the commands necessary to output simple graphics such as lines, squares and circles as well as more complex figures such as polygons. The following episode will take a first look at graphics text output, with an emphasis on ways to optimize its drawing speed. It will also include another installment of ONLINE Feedback. As usual, there is a download with this column. You should find it under the name GEMCL9.C in DL3 of ATARI16 (PCS-58).


A bit of history

One of the reasons that the VDI can be confusing is that drawing anything at all, even a simple line, can involve setting around four different VDI parameters before making the draw call! (Given the state of the GEM documents, just FINDING them can be fun!) Looking backwards a bit sheds some light on why the VDI is structured this way, and also gives us a framework for organizing a discussion of graphics output.

The GEM VDI closely follows the so-called GKS standard, which defines capabilities and calling sequences for a standardized graphic input/output system. GKS is itself an evolution from an early system called "Core". Both of these standards were born in the days when pen plotters, vectored graphics displays, and minicomputers were the latest items. So, if you wonder why setting the drawing pen color is a separate command, just think back a few years when it actually meant what it says! (The cynical may choose instead to ponder the benefits of standardization.)

When doing VDI output, it helps if you pretend that the display screen really is a plotter or some other separate device, which has its own internal parameters which you can set up and read back. The class of VDI commands called Attribute Functions let you set the parameters. Output functions cause the "device" to actually draw someone once it is configured. The Inquire Functions let you read back the parameters if necessary.

There are two parameters which are relevant no matter what type of object you are trying to draw. They are the writing mode and the clipping rectangle. The writing mode is similar to that discussed in the column on raster operations.

It determines what effect the figure you are drawing will have on data already on the screen. The writing mode is set with the call:

 vswrmode(vdihandle, mode);

Vdihandle, here and below, is the handle obtained from grafhandle at the beginning of the program. Mode is a word which may be one of:

1 - Replace Mode 2 - Transparent Mode 3 - XOR mode 4 - Reverse Transparent Mode

In replace mode, whatever is on the screen is overwritten. If you are writing characters, this means the background of each character cell will be erased.

In transparent mode, only the pixels directly under the "positive" part of the image, that is, where 1-bits are being written, will be changed. When writing characters, the background of the cell will be left intact.

In XOR mode, an exclusive or is performed between the screen contents and what is being written. The effect is to reverse the image under areas where a 1-bit occurs.

Reverse transparent is like transparent, but with a "reverse color scheme". That is, only places where a 0-bit is to be put are changed to the current writing color. When you write characters in reverse transparent (over white), the effect is reverse video.

The other common parameter is the clipping rectangle. It defines the area on the screen where the VDI is permitted to draw. Any output which would fall outside of this area is ignored; it is effectively a null operation. The clip rectangle is set with the call:

 vsclip(vdihandle, flag, pxy);

Pxy is a four-word array. Pxy[0] and pxy[1] are the X and Y screen coordinates, respectively, of one corner of your clipping rectangle. Pxy[2] and pxy[3] are the coordinates of the diagonally opposite corner of the rectangle. (When working with the AES, use of a GRECT to define the clip is often more convenient. The routine setclip() in the download does this.)

Flag is set to TRUE if clipping is to be used. If you set it to FALSE, the entire screen is assumed to be fair game.

Normally, you should walk the rectangle list for the current window to obtain your clipping rectangles. (See ST PRO GEM #2 for more details.) However, turning off the clip speeds up all output operations, particularly text. You may do this ONLY when you are absolutely certain that the figure you are drawing will not extend out of the top-most window, or out of a dialog.


The line forms on the left

The VDI line drawing operations include polyline, arc, elliptical arc, and rounded rectangle. I'll first look at the Attribute Functions for line drawing, then go through the drawing primitives themselves.

The most common used line attributes are color and width. The color is set with:

 vslcolor(vdihandle, color);

where color is one of the standard VDI color indices, ranging from zero to 15. (As discussed in column #6, the color which actually appears will depend on the pallette setting of your ST.)

The line width may only be set to ODD positive values, for reasons of symmetry. If you try to set an even value, the VDI will take the next lower odd value. The call is:

 vslwidth(vdihandle, width);

The two less used line parameters are the end style and pattern. With the end style you can cause the output line to have rounded ends or arrowhead ends. The call is:

 vslends(vdihandle, beginstyle, endstyle);

Beginstyle and endstyle are each words which may have the values zero for square ends (the default), one for arrowed ends, or two for rounded ends. They determine the styles for the starting and finishing ends of the line, respectively.

The line pattern attribute can select dotted or dashed lines as well as more complicated patterns. Before continuing, you should note one warning: VDI line output DOES NOT compensate for pixel aspect ratio. That is, the dashes on a line will look twice as long drawn vertically on a medium-res ST screen as they do when drawn horizontally. The command for setting the pattern is:

 vsltype(vdihandle, style);

Style is a word with a value between 1 and 7. The styles selected are:

1 - Solid (the default) 2 - Long Dash 3 - Dot 4 - Dash, Dot 5 - Dash 6 - Dash, Dot, Dot 7 - (User defined style)

The user defined style is determined by a 16-bit pattern supplied by the application. A one bit in the pattern turns a pixel on, a zero bit leaves it off. The pattern is cycled through repeatedly, using the high bit first. To use a custom style, you must make the call:

 vsludsty(vdihandle, pattern);

before doing vsltype().

As I mentioned above, the line type Output Functions available are polyline, circular and ellliptical arc, and rounded rectangle. Each has its own calling sequence. The call for a polyline is:

 vpline(vdihandle, points, pxy);

Points tells how many vertices will appear on the polyline. For instance, a straight line has two vertices: the end and the beginning. A closed square would have five, with the first and last identical. (There is no requirement that the figure described be closed.)

The pxy array contains the X and Y raster coordinates for the vertices, with a total of 2 * points entries. Pxy[0] and pxy[1] are the first X-Y pair, and so on.

If you happen to be using the XOR drawing mode, remember that drawing twice at a point is equivalent to no drawing at all. Therefore, for a figure to appear closed in XOR mode, the final stroke should actually stop one pixel short of the origin of the figure.

You may notice that in the GEM VDI manual the rounded rectangle and arc commands are referred to as GDPs (Generalized Drawing Primitives). This denotation is historical in nature, and has no effect unless you are writing your own VDI bindings.

The rounded rectangle is nice to use for customized buttons in windows and dialogs. It gives a "softer" look to the screen than the standard square objects. The drawing command is:

 vrbox(vdihandle, pxy);

Pxy is a four word array giving opposite corners of the rectangle, just as for the vsclip() call. The corner rounding occurs within the confines of this rectangle. Nothing will protrude unless you specify a line thickness greater than one. The corner rounding is approximately

circular; there is no user control over the degree or shape of rounding. 

Both the arc and elliptical arc commands use a curious method of specifying angles. The units are tenths of degrees, so an entire circle is 3600 units. The count starts at ninety degrees right of vertical, and proceeds counterclockwise. This means that "3 o'clock" is 0 units, "noon" is 900 units, "9 o'clock" is 1800 units, and 2700 units is at "half-past". 3600 units take you back to "3 o'clock".

The command for drawing a circular arc is:

 varc(vdihandle, x, y, radius, begin, end);

X and y specify the raster coordinates of the center of the circle. Radius specifies the distance from center to all points on the arc. Begin and end are angles given in units as described above, both with values between 0 and 3600. The drawing of the arc ALWAYS proceeds counterclockwise, in the direction of increasing arc number. So values of 0 and 900 for begin and end would draw a quarter circle from

"three o'clock" to "noon". Reversing the values would draw the other three quarters of the circle. 

A varc() command which specifies a "full turn" is the fastest way to draw a complete circle on the screen. Be warned, however, that the circle drawing algorithm used in the VDI seems to have some serious shortcomings at small radii! You can experiment with the CIRCLE primitive in ST Logo, which uses varc(), to see what I mean.

Notice that if you want an arc to strike one or more given points on the screen, then you are in for some trigonometry. If your math is a bit rusty, I highly recommend the book "A Programmer's Geometry", by Bowyer and Woodwark, published by Butterworths (London, Boston, Toronto).

Finally, the elliptical arc is generated with:

 vellarc(vdihandle, x, y, xrad, yrad, begin, end);

X, y, begin, and end are just as before. Xrad and yrad give the horizontal and vertical radii of the defining ellipse. This means that the distance of the arc from center will be yrad pixels at "noon" and "half-past", and it will be xrad pixels at "3 and 9 o'clock". Again, the arc is always drawn counterclockwise.

There are a number of approaches to keeping the VDI's attributes "in sync" with the actual output operations. Probably the LEAST efficient is to use the Inquire Functions to determine the current attributes. For this reason, I have omitted a discussion of these calls from this column.

Another idea is to keep a local copy of all significant attributes, use a test-before-set method to minimize the number of Attribute Functions which need to be called. This puts a burden on the programmer to be sure that the local attribute variables are correctly maintained. Failure to do so may result in obscure drawing bugs. If your application employs user defined AES objects, you must be very careful because GEM might call your draw code in the middle of a VDI operation (particularly if the user defined objects are in the menu).

Always setting the attributes is a simplistic method, but often proves most effective. The routines plperim() and rrperim() in the download exhibit this approach. Modification for other primitives is straightforward. This style is most useful when drawing operations are scattered throughout the program, so that keeping track of the current attribute status is difficult. Although inherently inefficient, the difference is not very noticable if the drawing operation requested is itself time consuming.

In many applications, such as data graphing programs or "Draw" packages, the output operations are centralized, forming the primary functionality of the code. In this case, it is both easy and efficient to keep track of attribute status between successive drawing operations.


Solids

There are a wider variety of VDI calls for drawing solid figures. They include rectangle or bar, disk, pie, ellipse, elliptical pie, filled rounded rectangle, and filled polygonal area. Of course, filled figure calls also have their own set of attributes which you will need to set.

The fill color index determines what pen color will be used to draw the solid. It is set with:

 vsfcolor(vdihandle, color);

Color is just the same as for line drawing. A solid may or may not have a visible border. This is determined with the call:

 vsfperimeter(vdihandle, vis);

Vis is a Boolean. If it is true, the figure will be given a solid one pixel outline in the current fill color index. This is often useful to improve the appearance of solids drawn with a dithered fill pattern. If vis is false, then no outline is drawn.

There are two parameters which together determine the pattern used to fill your figure. They are called interior style and interior index. The style determines the general type of fill, and the index is used to select a particular pattern if necessary. The style is set with the command:

 vsfinterior(vdihandle, style);

where style is a value from zero through four. Zero selects a hollow style: the fill is performed in color zero, which is usually white. Style one selects a solid fill with the current fill color. A style of two is called "pattern" and a three is called "hatch", which are terms somewhat suggestive of the options which can then be selected using the interior index. Style four selects the user defined pattern, which is described below.

The interior index is only significant for styles two and three. To set it, use:

 vsfstyle(vdihandle, index);

(Be careful here: it is very easy to confuse this call with the one above due to the unfortunate choice of name.) The index selects the actual drawing pattern. The GEM VDI manual shows fill patterns corresponding to index values from 1 to 24 under style 2, and from 1 to 12 under style 3. However, some of these are implemented differently on the ST. Rather than try to describe them all here, I would suggest that you experiment. You can do so easily in ST Logo by opening the Graphics Settings dialog and playing with the style and index values there.

The user defined style gives you some interesting options for multi-color fills. It is set with:

 vsfudpat(vdihandle, pattern, planes);

Planes determines the number of color planes in the pattern which you supply. It is set to one if you are setting a monochrome pattern. (Remember, monochrome is not necessarily black). It may be set to higher values on color systems: two for ST medium-res mode, or four for low-res mode. If you use a number lower than four under low-res, the other planes are zero filled.

The pattern parameter is an array of words which is a multiple of 16 words long. The pattern determined is 16 by 16 pixels, with each word forming one row of the pattern. The rows are arranged top to bottom, with the most significant bit to the left. If you have selected a multi-plane pattern, the entire first plane is stored, then the second, and so on.

Note that to use a multi-plane pattern, you set the writing mode to replace using vswrmode(). Since the each plane can be different, you can produce multi-colored patterns. If you use a writing color other than black, some of the planes may "disappear".

Most of the solids Output Functions have analogous line drawing commands. The polyline command corresponds to the filled area primitive. The filled area routine is:

 vfillarea(vdihandle, count, pxy);

Count and pxy are just the same as for vpline(). If the polygon defined by pxy is not closed, then the VDI will force closure with a straight line from the last to the first point. The polygon may be concave or self-intersecting. If perimeter show is on, the area will be outlined.

One note of caution is necessary for both vfillarea() and vpline(). There is a limit on the number of points which may be stored in pxy[]. This limit occurs because the contents of pxy[] are copied to the intin[] binding array before the VDI is called. You can determine the maximum number of vertices by checking intout[14] after using the extended inquire function vqextnd().

For reasons unknown to this writer, there are TWO different filled rectangle commands in the VDI. The first is

 vrrecfl(vdihandle, pxy);

Pxy is a four word array defining two opposite corners of the rectangle, just as in vsclip(). Vrrecfl() uses the fill attribute settings, except that it NEVER draws a perimeter.

The other rectangle routine is vbar(), with exactly the same arguments as vrrecfl(). The only difference is that the perimeter setting IS respected. These two routines are the fastest way to produce a solid rectangle using the VDI. They may be used in XOR mode with a BLACK fill color to quickly invert an area of the screen. You can improve the speed even further by turning off the clip (if possible), and byte aligning the left and right edges of the rectangle.

Separate commands are provided for solid circle and ellipse. The circle call is:

 vcircle(vdihandle, x, y, radius);

and the ellipse command is:

 vellipse(vdihandle, x, y, xrad, yrad);

All of the parameters are identical to those given above for varc() and vellarc(). The solid analogue of an arc is a "pie slice". The VDI pie commands are:

 vpieslice(vdihandle, x, y, radius, begin, end);

for a slice from a circular pie, and

 vellpie(vdihandle, x, y, xrad, yrad, begin, end);

for a slice from a "squashed" pie. Again, the parameters are identical to those in varc() and vellarc(). The units and drawing order of angles are also the same. The final solids Output Function is:

 vrfbox(vdihandle, pxy);

which draws a filled rounded rectangle. The pxy array defines two two opposite corners of the bounding box, as shown for vsclip().

The issues involved in correctly setting the VDI attributes for a fill operation are identical to those in drawing lines. For those who want to employ the "always set" method, I have again included two skeleton routines in the download, which can be modified as desired.


To be continued

This concludes the first part of our expedition through basic VDI operations. The next issue will tackle the problems of drawing bit mapped text at a reasonable speed. This first pass will not attempt to tackle alternate or proportional fonts, or alternate font sizes. Instead, I will concentrate on techniques for squeezing greater performance out of the standard monospaced system fonts.