home *** CD-ROM | disk | FTP | other *** search
/ Computer Club Elmshorn Atari PD / CCE_PD.iso / pc / 0600 / CCE_0628.ZIP / CCE_0628.PD / ALW2 / CHAP5 / ASSM5SW.TXT next >
Text File  |  1993-09-07  |  30KB  |  827 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9. CHAPTER 5: INTRODUCING THE VDI
  10. -------------------------------
  11.  
  12. [NOTE: Words enclosed in asterisks (i.e. *word*) should be 
  13. read as italicized text. This text file is copyright 1993 by 
  14. Clayton Walnum. All rights reserved.]
  15.  
  16. GEM (Graphics Environment Manager) is made up of many 
  17. libraries of functions, each of which handles certain 
  18. portions of the system's activities. These libraries are 
  19. grouped into two major units, called the AES (Applications 
  20. Environment Services) and the VDI (Virtual Device 
  21. Interface). The AES, which we've been using since the 
  22. beginning of the book, contains the functions we need to 
  23. handle windows, dialog boxes, menu bars, and event 
  24. processing. The VDI controls most of the ST's graphic 
  25. capabilities and provides some mouse and cursor control 
  26. functions, as well.
  27.     The VDI plays an important role in making your graphics 
  28. programs operate on many different devices. Unfortunately, 
  29. one of the crucial elements in the graphics interface, GDOS 
  30. (Graphics Device Operating System), is not built into the 
  31. current operating system. GDOS is the portion of the VDI 
  32. that links the graphics functions to the drivers needed to 
  33. assure that the graphics operate properly on all graphics 
  34. devices. GDOS also makes it possible to load different fonts 
  35. into your ST, using the standard VDI functions.
  36.     At this time, however, we're concerned only with one 
  37. device: the screen.
  38.  
  39. --The VDI functions--
  40.  
  41. The VDI provides a series of functions that let us quickly 
  42. draw many graphic shapes. This simplifies the development of 
  43. programs that rely heavily on graphics. If you programmed an 
  44. 8-bit Atari (or still do), think of all the work involved in 
  45. drawing a circle. The VDI provides a function that will draw 
  46. any size circle we want--with a single call. There are also 
  47. functions for drawing ellipses, lines, rectangles, rounded 
  48. rectangles, arcs, pie slices and a number of other useful 
  49. graphics.
  50.     And it doesn't stop there. Each graphic function has a 
  51. group of related attributes that may be set before the 
  52. graphic is drawn, allowing various types of lines, fills and 
  53. colors.
  54.  
  55. --The Program--
  56.  
  57. This chapter's sample program shows how to set up your 
  58. program to use the VDI. It also includes a demonstration of 
  59. some of the VDI's graphics capabilities. Specifically, when 
  60. the program is run, you will see the different types of line 
  61. styles available through the VDI. To exit the program, press 
  62. your Return key.
  63.  
  64. --The VDI Arrays--
  65.  
  66. Calling VDI functions is a lot like calling AES functions. 
  67. In both cases, you must place appropriate values into 
  68. control and input arrays, and then call the function by 
  69. using a *trap #2* instruction. Look at the data section of 
  70. this chapter's sample program. There, you'll find the usual 
  71. AES parameter block (*apb*). Right below that, you'll see 
  72. something called *vpb*. Yep. That's a VDI parameter block. 
  73. Although these parameter blocks work the same way--that is, 
  74. they both tell the OS where to find the arrays it needs--
  75. they contain different values. The VDI, for example, doesn't 
  76. use the *addr_in* or *addr_out* arrays. Let's look at the 
  77. *vpb* in detail.
  78.     The first value is the address of a control array. In 
  79. our *apb* we have a 0 in this location because we found it 
  80. easier to have different control arrays for each function, 
  81. and then plug the address of the appropriate array into the 
  82. *apb* when we needed it. But because the values in the VDI 
  83. control array vary from one function call to another, it's 
  84. clumsy to try to set them up ahead of time.
  85.     The *int_in* and *int_out* arrays are the same as those 
  86. in the *apb*. We can use the same arrays for either an AES 
  87. or VDI call. But the VDI *apb* has something a little 
  88. different, arrays called *pts_in* and *pts_out*. These 
  89. arrays usually contain coordinates for the VDI's drawing 
  90. functions. For example, the starting and ending screen 
  91. coordinates for a line would go into the *pts_in* array 
  92. before calling the function.
  93.  
  94. --Initializing the VDI--
  95.  
  96. When we use the VDI in our programs, we must set up 
  97. something called a virtual workstation. To do this, we do 
  98. the following:
  99.  
  100. 1) Get a handle to the physical screen.
  101. 2) Open a virtual workstation.
  102. 3) Clear the virtual workstation.
  103.  
  104. Look at this chapter's program listing. After the usual 
  105. program initialization, which concludes with the call to 
  106. *appl_init*, we begin the VDI initialization. The first step 
  107. is performed by calling the AES function #77, *graf_handle*, 
  108. like this:
  109.  
  110. move.l  #graf_handle,apb
  111. jsr     aes
  112. move    int_out,gr_handle
  113.  
  114.     This returns the handle for the currently open device 
  115. (the screen) or workstation, as well as the size of the 
  116. system font. Because GEM is capable of having many programs 
  117. in memory at once, each requires some identification, to 
  118. keep commands for one program from corrupting another. This 
  119. is accomplished by assigning each program a handle. The 
  120. variable *gr_handle* in the above call is an integer value 
  121. that identifies the current workstation. After the call, 
  122. this value is found in the first element of the *int_out* 
  123. array.
  124.     The *graf_handle* call also returns some information 
  125. about the system font. The width of a character cell will be 
  126. in *int_out+2*, the cell height will be in *int_out+4*, the 
  127. width of a box that can enclose a character will be in 
  128. *int_out+6*, and the height of the box will be in 
  129. *int_out+8*. We won't be using any of this character 
  130. information now, but you should know where to find it when 
  131. you need it.
  132.  
  133. --The Virtual Workstation--
  134.  
  135. The *graf_handle* call returns the handle to the physical 
  136. workstation. What we really need for our program is a handle 
  137. to a virtual workstation. It's kind of tough to explain the 
  138. difference, but I'll give it a shot.
  139.     A particular device may have many virtual workstations, 
  140. but only one physical workstation. The physical workstation 
  141. is directly associated with the device itself, usually the 
  142. screen. You can think of a virtual workstation as a 
  143. "pretend" device. It has its own section of memory and keeps 
  144. its data and status completely separate from all other 
  145. virtual workstations. When you activate an application (such 
  146. as clicking on a desk accessory), it becomes bound to the 
  147. physical workstation. In a sense, it becomes the physical 
  148. workstation.
  149.     We get the handle for our virtual workstation with a 
  150. call to the VDI function #100, *v_opnvwk*, like this:
  151.  
  152.     move    #100,contrl
  153.     clr     contrl+2
  154.     move    #11,contrl+6
  155.     move    gr_handle,contrl+12
  156.     movea.l #int_in,a5
  157.     move    #9,d5
  158. loop:
  159.     move    #1,(a5)+
  160.     dbra    d5,loop
  161.     move    #2,int_in+20
  162.     jsr     vdi
  163.     move    contrl+12,vws_handle
  164.  
  165.     This function expects the system attributes to be in 
  166. the *int_in* array. (In this example, we're loading the 
  167. values into *int_in* using a loop.) These attributes 
  168. determine default values for system attributes such as 
  169. default colors, fill patterns, and line styles. (For those 
  170. of you familiar with C, the *int_in* array in this call 
  171. serves the same function as C's *work_in* array.) In the 
  172. above example, we place a 1 in elements 1 through 10 of the 
  173. *int_in* array, and a 2 in the eleventh element of the 
  174. *int_in* array. This is the standard way to initialize these 
  175. attributes.
  176.     You should note the manner in which the control array 
  177. is used, since all VDI calls require similar parameters in 
  178. this array. The first element of the control array must 
  179. contain the opcode for the VDI function we wish to call. 
  180. *Contrl+2* must contain the number of point pairs that will 
  181. be found in the *pts_in* array, in this case, 0. *Contrl+6* 
  182. must contain the number of integer values that are in the 
  183. *int_in* array. In this function call, *int_in* will contain 
  184. 11 values, so we place an 11 in *contrl+6*. Finally, 
  185. *contrl+12* must contain the device handle. In most VDI 
  186. calls, this value will be the handle to our virtual 
  187. workstation. However, because we don't yet have that handle, 
  188. we use the graphics handle that was returned by the call to 
  189. *graf_handle*.
  190.     After the call to *v_opnvwk*, our *int_out* and 
  191. *pts_out* arrays will contain much information about the 
  192. virtual device's current attributes, as follows:
  193.  
  194.     control+4 -- 6 = # of point pairs in pts_out
  195.     control+8 -- 45 = # of integers in int_out
  196.     control+12 -- Device handle (0 if no device opened)
  197.  
  198.     int_out, work_out[0] -- Maximum horizontal screen coord.
  199.     int_out+2, work_out[1] -- Maximum vertical screen coord.
  200.     int_out+4, work_out[2] -- Device coordinate units flag:
  201.         0 = Device can display a precisely scaled image.
  202.         1 = Device cannot display a precisely scaled image.
  203.     int_out+6, work_out[3] -- Width of a pixel in microns.
  204.     int_out+8, work_out[4] -- Height of a pixel in microns.
  205.     int_out+10, work_out[5] -- Number of font heights:
  206.         0 = continuous scaling.
  207.     int_out+12, work_out[6] -- Number of line types.
  208.     int_out+14, work_out[7] -- Number of line widths:
  209.         0 = Continuous scaling.
  210.     int_out+16, work_out[8] -- Number of marker styles.
  211.     int_out+18, work_out[9] -- Number of marker sizes:
  212.         0 = Continuous scaling.
  213.     int_out+20, work_out[10] -- Number of supported text fonts.
  214.     int_out+22, work_out[11] -- Number of pattern styles.
  215.     int_out+24, work_out[12] -- Number of hatch styles.
  216.     int_out+26, work_out[13] -- Number of available colors.
  217.     int_out+28, work_out[14] -- Number of generalized drawing 
  218.                         primitives.     
  219.     int_out+30 to int_out+48
  220.     work_out[15] to work_out[24] -- Code numbers for available      
  221.                         generalized drawing primitives:
  222.         1 = filled bar.
  223.         2 = arc.
  224.         3 = pie slice.
  225.         4 = filled circle.
  226.         5 = filled ellipse.
  227.         6 = elliptical arc.
  228.         7 = elliptical pie slice.
  229.         8 = rounded rectangle.
  230.         9 = filled rounded rectangle.
  231.         10 = justified graphics text.
  232.         -1 = end of GDP list.
  233.     int_out+50 to int_out+68
  234.     work_out[25] to work_out[34] -- Code numbers for graphics
  235.                 operations available to the GDPs:
  236.         0 = lines.
  237.         1 = markers.
  238.         2 = graphics text.
  239.         3 = fills.
  240.         4 = none.
  241.     int_out+70, work_out[35] -- Color flag:
  242.         0 = no colors available on device.
  243.         1 = colors available on device.
  244.     int_out+72, work_out[36] -- Text rotation flag:
  245.         0 = device cannot rotate text.
  246.         1 = device can rotate text.
  247.     int_out+74, work_out[37] -- Fill flag:
  248.         0 = device cannot fill areas.
  249.         1 = device can fill areas.
  250.     int_out+76, work_out[38] -- Cell array flag:
  251.         0 = device not capable of cell array operation.
  252.         1 = device capable of cell array operation.
  253.     int_out+78, work_out[39] -- Number of available colors:
  254.         0 = more than 32,767.
  255.         1 = Black and white
  256.         2 or more = Number of colors available.
  257.     int_out+80, work_out[40] -- Locator input devices:
  258.         1 = keyboard.
  259.         2 = keyboard and mouse (or other device)
  260.     int_out+82, work_out[41] -- Valuator input devices:
  261.         1 = keyboard.
  262.         2 = other device.
  263.     int_out+84, work_out[42] -- Choice devices:
  264.         1 = function keys.
  265.         2 = other keypad.
  266.     int_out+86, work_out[43] -- Text input devices:
  267.         1 = keyboard.
  268.     int_out+88, work_out[44] -- Type of workstation:
  269.         0 = output.
  270.         1 = input.
  271.         2 = input and output.
  272.         3 = reserved
  273.         4 = metafile output.
  274.     pts_out, work_out[45] -- Minimum character width.
  275.     pts_out+2, work_out[46] -- Minimum character height.
  276.     pts_out+4, work_out[47] -- Maximum character width.
  277.     pts_out+6, work_out[48] -- Maximum character height.
  278.     pts_out+8, work_out[49] -- Minimum line width.
  279.     pts_out+10, work_out[50] -- 0.
  280.     pts_out+12, work_out[51] -- Maximum line width.
  281.     pts_out+14, work_out[52] -- 0.
  282.     pts_out+16, work_out[53] -- Minimum marker width.
  283.     pts_out+18, work_out[54] -- Minimum marker height.
  284.     pts_out+20, work_out[55] -- Maximum marker width.
  285.     pts_out+22, work_out[56] -- Maximum marker height.
  286.  
  287.     Don't let all this information intimidate you. Right 
  288. now, we're only concerned with the three values returned in 
  289. *contrl+4*, *contrl+8*, and *contrl+12*. *Contrl+12* will 
  290. contain the handle to our virtual workstation, *contrl+4* 
  291. will contain the number of points (two values each) returned 
  292. in *pts_out*, and *contrl+8* will contain the number of 
  293. integers returned in *int_out*. For this function call, 
  294. *contrl+4* should contain a 6 after the call, which mean six 
  295. pairs of integers have been returned in *pts_out*, and 
  296. *contrl+8* should contain a 45, the number of integers 
  297. returned in *int_out*. For every VDI call, *contrl+4* and 
  298. *contrl+8* are used the same way. You can always check them 
  299. to see how many values have been returned by a VDI function.
  300.     Finally, in the above example, notice that we are 
  301. calling a subroutine called *vdi* to perform a VDI function. 
  302. The *vdi* subroutine works similarly to the *aes* 
  303. subroutine, setting up the VDI function and then doing a 
  304. *trap #2*.
  305.  
  306. --Clearing the Workstation--
  307.  
  308. The last step in getting the VDI initialized is to clear the 
  309. workstation. Clearing a workstation ensures that all the 
  310. devices have been flushed and the screen has been erased. In 
  311. other words, it presents us with a blank slate upon which 
  312. our program can begin to operate. To clear a workstation, we 
  313. call VDI function #3, *v_clrwk*, like this:
  314.  
  315. move    #3,contrl
  316. clr     contrl+2
  317. clr     contrl+6
  318. move    vws_handle,contrl+12
  319. jsr     vdi
  320.  
  321.     As you can see, this function has no special 
  322. parameters, nor does it return any values. It simply does 
  323. its business and returns control to the program. Notice 
  324. again, how we're using the control array. Because we have no 
  325. values in the *pts_in* and *int_in* arrays, we set both 
  326. *contrl+2* and *contrl+6* to 0. When calling a VDI function, 
  327. you also must be sure that the virtual workstation handle is 
  328. in *contrl+12*. In the above example, we show the 
  329. workstation handle being placed in *contrl+12*. However, in 
  330. the sample program, this instruction is missing. Why? 
  331. Because the handle is already in *contrl+12*, where it was 
  332. placed by the call to *v_opnvwk*. The handle will stay in 
  333. *contrl+12*, right where we want it, until we overwrite it.
  334.  
  335. --Polylines--
  336.  
  337. Now that we've got our workstation set up, we can get down 
  338. to business. The first graphic we'll experiment with is the 
  339. polyline. Those of you who are up on your linguistics know 
  340. that the prefix "poly" means "many." A polyline is one or 
  341. more lines connected from point to point, which allows the 
  342. programmer to draw complex shapes with a single function 
  343. call.
  344.     But before we draw our polylines, we need to set some 
  345. line attributes, like color, width, and end style. Any lines 
  346. drawn after we've set the attributes will use those 
  347. attributes. Also, the line attributes stay in effect until 
  348. we change them again.
  349.     To set a line's color, we use a call to VDI function 
  350. #17, *vsl_color*, like this:
  351.  
  352. move    #17,contrl
  353. clr     contrl+2
  354. move    #1,contrl+6
  355. move    vws_handle,contrl+12
  356. move    color,int_in
  357. jsr     vdi
  358.  
  359.     Here, *color* is an integer from 0 to the device 
  360. maximum (low resolution=15, medium resolution=3, and high 
  361. resolution=1). If we use a number higher than the maximum, 
  362. the function will default to color 1. On the ST, the default 
  363. color palette, starting with 0 and ending with 15, is white, 
  364. black, red, green, blue, cyan, yellow, magenta, white, 
  365. black, light red, light green, light blue, light cyan, light 
  366. yellow and light magenta. The actual color value set is 
  367. returned in *int_out*.
  368.      When we're drawing lines, we can also choose an end 
  369. style with a call to VDI function #108, *vsl_ends*:
  370.  
  371. move    #108,contrl
  372. clr     contrl+2
  373. move    #2,contrl+6
  374. move    vws_handle,contrl+12
  375. move    ends,int_in
  376. move    ends,int_in+2
  377. jsr     vdi
  378.  
  379. In this case, *ends* is an integer value from 0 to 2. A 
  380. value of 0 will yield a square end, 1 will get us an arrow, 
  381. and 2 will result in a rounded end. Here we're using *ends* 
  382. as both the beginning and ending line style, but each end of 
  383. the line can have a different end style if we like. To do 
  384. this, we'd put the first end style in *int_in* and the 
  385. second end style in *int_in+2*. This function returns no 
  386. values.
  387.      Finally, we can set the thickness of our lines with a 
  388. call to VDI function #16, *vsl_width*:
  389.  
  390. move    #16,contrl
  391. move    #1,contrl+2
  392. clr     contrl+6
  393. move    vws_handle,contrl+12
  394. move    width,pts_in
  395. clr     pts_in+2
  396. jsr     vdi
  397.  
  398.     The variable *width*, which is placed into the first 
  399. element of *pts_in*, must be an odd positive integer. The 
  400. line will be set to the closest width less than or equal to 
  401. the value of *width*. Notice that, for some strange reason, 
  402. *pts_in+2* must contain a 0. The actual width set is 
  403. returned in the first element of *pts_out*.
  404.     Once we have the attributes set, we can draw our first 
  405. line. We do this with a call to VDI function #6, *v_pline*:
  406.  
  407. move    #6,contrl
  408. move    #2,contrl+2
  409. clr     contrl+6
  410. move    vws_handle,contrl+12
  411. move    x1,pts_in
  412. move    y1,pts_in+2
  413. move    x2,pts_in+4
  414. move    y2,pts_in+6
  415. jsr     vdi
  416.  
  417.     In this call, *x1* and *y1* are the X and Y coordinates 
  418. of one end of the line. The integers *x2* and *y2* are, of 
  419. course, the X and Y coordinates of the other end of the 
  420. line. In the example program, we're using *v_pline* to draw 
  421. only single lines. However, as we said before, this function 
  422. can be used to draw many connected lines. For example, to 
  423. extend the above example so that it draws two connected 
  424. lines, we could do something like this:
  425.  
  426. move    #6,contrl
  427. move    #3,contrl+2
  428. clr     contrl+6
  429. move    vws_handle,contrl+12
  430. move    x1,pts_in
  431. move    y1,pts_in+2
  432. move    x2,pts_in+4
  433. move    y2,pts_in+6
  434. move    x3,pts_in+8
  435. move    y3,pts_in+10
  436. jsr     vdi
  437.  
  438.     Notice that we are now loading a 3 into *contrl+2*, 
  439. because the *pts_in* array now contains three points. 
  440. (Remember, a point is really two values.) We've also loaded 
  441. the values *x3* and *y3* (the new point) into the next two 
  442. elements of the *pts_in* array. These values are the next 
  443. point to which the *v_pline* function should draw. We could 
  444. continue drawing lines by adding more and more points to the 
  445. *pts_in* array. We just must be sure that the value in 
  446. *contrl+2* is the total number of points in the array, 
  447. otherwise the function will ignore some of the points.
  448.      If we're drawing a polyline at the smallest width, we 
  449. can choose between six system line types with a call to VDI 
  450. function #15, *vsl_type*:
  451.  
  452. move    #15,contrl
  453. clr     contrl+2
  454. move    #1,contrl+6
  455. move    vws_handle,contrl+12
  456. move    type,int_in
  457. jsr     vdi
  458.  
  459. Here, *type* is an integer value from 1 to 7 as follows:
  460.  
  461.      1 solid        ________________
  462.      2 long dash    ___ ___ ___ ___
  463.      3 dots         ...............
  464.      4 dash dot     __.__.__.__.__.
  465.      5 dash         __ __ __ __ __ __
  466.      6 dash dot dot __..__..__..__..__
  467.      7 user defined
  468.  
  469.     Type 7 lets you set up your own line types, but we're 
  470. not going to get into that now. This function returns, in 
  471. *int_out*, the actual line type set.
  472.     Now that we've covered the basics of setting up the VDI 
  473. and calling graphics functions, let's take a quick look at 
  474. some of the other graphics you can draw with the VDI.
  475.  
  476. --Rectangles--
  477.  
  478. We can use *v_pline* to draw a standard square-cornered box, 
  479. but the VDI also supplies a function that will let us draw 
  480. rectangles with rounded corners. To do this, we call VDI 
  481. function #11, sub-function #8, *v_rbox*:
  482.  
  483. move    #11,contrl
  484. move    #2,contrl+2
  485. clr     contrl+6
  486. move    #8,contrl+10
  487. move    vws_handle,contrl+12
  488. move    x1,pts_in
  489. move    y1,pts_in+2
  490. move    x2,pts_in+4
  491. move    y2,pts_in+6
  492. jsr     vdi
  493.  
  494.     Here, we must supply the pixel coordinates of the 
  495. upper-left and lower-right corners. We place these values 
  496. into the *pts_in* array. Also note that this function call 
  497. requires that you place a sub-function number (8) into 
  498. *contrl+10*. The line attributes--color, style and width--
  499. are used with *v_rbox*, allowing a wide variety of 
  500. rectangles. This function returns no values.
  501.     You can also draw a filled rounded rectangle, using VDI 
  502. function #11, sub-function #9, *v_rfbox*:
  503.  
  504. move    #11,contrl
  505. move    #2,contrl+2
  506. clr     contrl+6
  507. move    #9,contrl+10
  508. move    vws_handle,contrl+12
  509. move    x1,pts_in
  510. move    y1,pts_in+2
  511. move    x2,pts_in+4
  512. move    y2,pts_in+6
  513. jsr     vdi
  514.  
  515.     This function uses the currently active fill pattern, 
  516. which we'll learn to set later on.
  517.     To draw a filled rectangle with square corners, use VDI 
  518. function #11, sub-function #1, *v_bar*:
  519.  
  520. move    #11,contrl
  521. move    #2,contrl+2
  522. move    #0,contrl+6
  523. move    #1,contrl+10
  524. move    vws_handle,contrl+12
  525. move    x1,pts_in
  526. move    y1,pts_in+2
  527. move    x2,pts_in+4
  528. move    y2,pts_in+6
  529. jsr     vdi
  530.  
  531.     As you may suspect, this function, too, uses the 
  532. current fill pattern.
  533.  
  534. --Circles, Ellipses, and Arcs--
  535.  
  536.      GEM's VDI provides several functions for drawing 
  537. various types of curved lines and shapes. If you'd like to 
  538. draw a filled circle, just use VDI Function #11, sub-
  539. function #4, *v_circle*:
  540.  
  541. move    #11,contrl
  542. move    #3,contrl+2
  543. move    #0,contrl+6
  544. move    #4,contrl+10
  545. move    vws_handle,contrl+12
  546. move    centerx,pts_in
  547. move    centery,pts_in+2
  548. move    #0,pts_in+4
  549. move    #0,pts_in+6
  550. move    radius,pts_in+8
  551. move    #0,pts_in+10
  552. jsr     vdi
  553.  
  554.     Here, *centerx* and *centery* are the X and Y 
  555. coordinates of the circle's center, and *radius* is the 
  556. circle's radius. Note that *pts_in+4*, *pts_in+6*, and 
  557. *pts_in+10* all contain dummy arguments of 0. The *v_circle* 
  558. function, like *v_rfbox*, uses the current fill attributes.
  559.     You can draw ellipses, too. An ellipse looks something 
  560. like a squashed circle or a solid oval and is drawn by a 
  561. call to VDI function #11, sub-function 5, *v_ellipse*:
  562.  
  563. move    #11,contrl
  564. move    #2,contrl+2
  565. move    #0,contrl+6
  566. move    #5,contrl+10
  567. move    vws_handle,contrl+12
  568. move    x,pts_in
  569. move    y,pts_in+2
  570. move    hrad,pts_in+4
  571. move    vrad,pts_in+6
  572. jsr     vdi
  573.  
  574.     Here, the parameters *x* and *y* denote the ellipse's 
  575. center point, and *hrad* and *vrad* are the X and Y radiuses 
  576. in pixels. Once again, the active fill attributes are used. 
  577. No values are returned from the function.
  578.     Arcs are curved lines and are easy to draw with VDI 
  579. function #11, sub-function #2, *v_arc*:
  580.  
  581. move    #11,contrl
  582. move    #4,contrl+2
  583. move    #2,contrl+6
  584. move    #2,contrl+10
  585. move    vws_handle,contrl+12
  586. move    angle1,int_in
  587. move    angle2,int_in+2
  588. move    x,pts_in
  589. move    y,pts_in+2
  590. move    #0,pts_in+4
  591. move    #0,pts_in+6
  592. move    #0,pts_in+8
  593. move    #0,pts_in+10
  594. move    rad,pts_in+12
  595. move    #0,pts_in+14
  596. jsr     vdi
  597.  
  598.     The parameters *x*, *y*, and *rad* are the X,Y-
  599. coordinates of the center and the radius, respectively. The 
  600. integers *angle1* and *angle2* are the beginning and ending 
  601. angles of the arc, in tenths of degrees (that is, values 
  602. from 1 to 3600). Note that *pts_in+4*, *pts_in+6*, 
  603. *pts_in+8*, *pts_in+10*, and *pts_in+14* all contain dummy 
  604. arguments that must contain zeroes. No value is returned 
  605. from the function.
  606.     The final call in this family of functions allows you 
  607. to draw pie slices, which help you to draw pie charts. To 
  608. draw a pie slice, use a call to VDI function #11, sub-
  609. function #3, *v_pieslice*:
  610.  
  611. move    #11,contrl
  612. move    #4,contrl+2
  613. move    #2,contrl+6
  614. move    #3,contrl+10
  615. move    vws_handle,contrl+12
  616. move    angle1,int_in
  617. move    angle2,int_in+2
  618. move    x,pts_in
  619. move    y,pts_in+2
  620. move    #0,pts_in+4
  621. move    #0,pts_in+6
  622. move    #0,pts_in+8
  623. move    #0,pts_in+10
  624. move    rad,pts_in+12
  625. move    #0,pts_in+14
  626. jsr     vdi
  627.  
  628.     The parameters here are the same as those for the arc 
  629. function. However, the body of the pie slice will be colored 
  630. by whatever fill pattern is active. This function returns no 
  631. values.
  632.  
  633. --Polymarkers--
  634.  
  635.      Polymarkers are a number of predefined shapes you can 
  636. use in your graphics. To draw them, you call VDI function 
  637. #7, *v_pmarker*:
  638.  
  639. move    #7,contrl
  640. move    #3,contrl+2
  641. move    #0,contrl+6
  642. move    vws_handle,contrl+12
  643. move    x1,pts_in
  644. move    y1,pts_in+2
  645. move    x2,pts_in+4
  646. move    y2,pts_in+6
  647. move    x3,pts_in+8
  648. move    y3,pts_in+10
  649. jsr     vdi
  650.     
  651.     The parameter placed in *contrl+2* is the number of 
  652. markers you want to draw. The X,Y coordinates for the 
  653. markers are stored in the *pts_in* array. The above example 
  654. shows three markers being drawn, but you can draw as many as 
  655. you need. This function returns no values.
  656.      What do these markers look like? You have a choice of 
  657. six predefined shapes which (from 1 to 6, respectively) are 
  658. dot, plus sign, asterisk, square, diagonal cross, and 
  659. diamond. To set the polymarker type, call VDI function #18, 
  660. *vsm_type*:
  661.  
  662. move    #18,contrl
  663. move    #0,contrl+2
  664. move    #1,contrl+6
  665. move    vws_handle,contrl+12
  666. move    type,int_in
  667. jsr     vdi
  668.  
  669.     Here, *type* is a value from 1 to 6. If you should 
  670. choose a value out of this range, the function will select 
  671. the asterisk as a default. The value chosen will be returned 
  672. in *int_out*.
  673.      There are two other attributes that affect polymarkers: 
  674. color and height. Color is set with a call to VDI function 
  675. #20, *vsm_color*:
  676.  
  677. move    #20,contrl
  678. move    #0,contrl+2
  679. move    #1,contrl+6
  680. move    vws_handle,contrl+12
  681. move    color,int_in
  682. jsr     vdi
  683.  
  684.     Here, *color* is a value from 0 to the device maximum. 
  685. All the rules of the *vsl_color* call apply in this case. 
  686. The actual color set is returned in *int_out*.
  687.      You can change the size of all polymarkers, except the 
  688. dot (which always appears in the smallest size), with a call 
  689. to VDI function #19, *vsm_height*:
  690.  
  691. move    #19,contrl
  692. move    #1,contrl+2
  693. move    #0,contrl+6
  694. move    vws_handle,contrl+12
  695. move    #0,pts_in
  696. move    height,pts_in+2
  697. jsr     vdi
  698.  
  699.     The parameter *height* is the polymarker's size on the 
  700. Y-axis. The actual height will be the greatest height 
  701. available on the device, less than or equal to the height 
  702. parameter. This will be returned in *pts_out+2*. Note that, 
  703. in the above function call, *pts_in* is always 0, with the 
  704. requested height being placed in *pts_in+2*.
  705.  
  706. --Fill Patterns--
  707.  
  708. GEM supplies many patterns we can use to fill our figures. 
  709. There's a series of functions to let us set these patterns 
  710. up the way we want them. The first step is a call to VDI 
  711. function #23, *vsf_interior*:
  712.  
  713. move    #23,contrl
  714. move    #0,contrl+2
  715. move    #1,contrl+6
  716. move    vws_handle,contrl+12
  717. move    pattern,int_in
  718. jsr     vdi
  719.  
  720.     Here, *pattern* is a value from 0 to 4. The values are 
  721. interpreted as follows:
  722.  
  723.  0  Hollow (background color)
  724.  1  Solid
  725.  2  Pattern
  726.  3  Hatch
  727.  4  User-defined
  728.  
  729.     The actual pattern set is returned in *int_out*.
  730.     If you choose style 0 or 1, you need go no further, but 
  731. style 2 allows you to choose between 24 different patterns, 
  732. and style 3 provides 12 hatch styles. You choose the pattern 
  733. you wish to use, with a call to VDI function #24, 
  734. *vsf_style*:
  735.  
  736. move    #24,contrl
  737. move    #0,contrl+2
  738. move    #1,contrl+6
  739. move    vws_handle,contrl+12
  740. move    fill,int_in
  741. jsr     vdi
  742.  
  743. Here, *fill* is a value from 0 to 23. Consult your reference 
  744. manual to see what these styles look like. The fill that was 
  745. actually set is returned in *int_out*.
  746.      The color of the fill is selected with a call to VDI 
  747. function #25, *vsf_color*:
  748.  
  749. move    #25,contrl
  750. move    #0,contrl+2
  751. move    #1,contrl+6
  752. move    vws_handle,contrl+12
  753. move    color,int_in
  754. jsr     vdi
  755.  
  756.     All the rules for the *vsl_color* function apply here, 
  757. also, with the actual color that was set returned in 
  758. *int_out*.
  759.      Finally, you can choose between a visible or invisible 
  760. border for your fill with a call to VDI function #104, 
  761. *vsf_perimeter*:
  762.  
  763. move    #104,contrl
  764. move    #0,contrl+2
  765. move    #1,contrl+6
  766. move    vws_handle,contrl+12
  767. move    flag,int_in
  768. jsr     vdi
  769.  
  770.     Here, a *flag* value of 0 will give you an invisible 
  771. border. Any other value will cause the border to be drawn in 
  772. the current fill color.
  773.  
  774. --Conclusion--
  775.  
  776.      Now that you've been introduced to many of the graphics 
  777. functions available to you through the VDI, study the sample 
  778. program to see them in action, then take some time and 
  779. experiment with the VDI on your own. See if you can write a 
  780. program to draw a simple picture, or maybe a graph.
  781.  
  782. --Summary--
  783.  
  784. * The VDI (Virtual Device Interface) controls most of the 
  785. ST's graphic capabilities and provides some mouse and cursor 
  786. control functions, as well.
  787.  
  788. * You call VDI functions much like you call AES functions, 
  789. by placing appropriate values into control and input arrays, 
  790. and then calling the function by using a *trap #2* 
  791. instruction.
  792.  
  793. * To initialize the VDI, you must get a handle to the 
  794. physical screen, open a virtual workstation, and finally 
  795. clear the workstation.
  796.  
  797. * The AES function #77, *graf_handle*, obtains a handle to 
  798. the physical workstation and returns information about the 
  799. system font.
  800.  
  801. * The VDI function #100, *v_opnvwk*, obtains a handle to a 
  802. virtual workstation.
  803.  
  804. * The VDI function #3, *v_clrwk*, clears a workstation, 
  805. flushing all devices and clearing the screen.
  806.  
  807. * The VDI functions *vsl_color* (#17), *vsl_ends* (#108), 
  808. *vsl_width* (#16), and *vsl_type* (#15) set various line 
  809. attributes.
  810.  
  811. * The VDI function #6, *v_pline*, draws polylines.
  812.  
  813. * Other shapes can be drawn using the VDI functions *v_rbox* 
  814. (#11,8), *v_rfbox* (#11,9), *v_bar* (#11,1), *v_circle* 
  815. (#11,4), *v_ellipse* (#11,5), *v_arc* (#11,2), and 
  816. *v_pieslice* (#11,3).
  817.  
  818. * Polymarkers are drawn by VDI function #7, *v_pmarker*.
  819.  
  820. * The polymarker attributes can be set by the VDI functions 
  821. *vsm_type* (#18), *vsm_color* (#20), and *vsm_height* (#19).
  822.  
  823. * The current fill pattern's attributes can be set by the 
  824. VDI functions *vsf_interior* (#23), *vsf_style* (#24), 
  825. *vsf_color* (#25), and *vsf_perimeter* (#104).
  826.  
  827.