
                               A GUIDE TO GEM
                                    
                            by: Mrten Lindstrm

                     Chapter 2: General output - the VDI
                     -----------------------------------

 Through the AES alone, some things can be  drawn on screen, as we could see
 when we called up  alert  boxes  and  file  selector. More general dialogue
 boxes or icon maps etc. are  also  possible without leaving the AES library
 (through the call OBJC_DRAW) - though  for  that  we need to know something
 about GEM objects, object trees and resources.

 For completely general screen output, however, (and for GEM output to other
 devices) we need the functions of the VDI library.


                          VDI calls to be avoided:
                          ------------------------

 Before going into the details of  opening  and  using the VDI, let's have a
 quick overview of its various functions. A  great many of them can actually
 be forgotten by the self-controlled  GEM  programmer, one reason being that
 the VDI is sub-ordinate to  the  AES,  and contain features better accessed
 through this higher system, another reason being that the VDI in ROM is not
 complete (see GDOS later) and a  third  reason  simply being the history of
 GEM.

 The following VDI calls should generally be avoided:

     V_HARDCOPY (works only with  ST  resolutions),  VS_PALETTE (for IBM CGA
     palettes), V_CELLARRAY and VQ_CELLARRAY plus any VDI calls dealing with
     the following:

     - mouse/keyboard input or manipulation of mouse cursor   (leave to AES)
     - vector changing (the VEX_xxxx calls)              (forget completely)
     - the alpha text mode                     (at least not under MultiTOS)

     ... and, as long as we don't use GDOS, any call dealing with:

     - physical workstations and other devices than screen   (requires GDOS)
     - fonts (loading, changing etc.)                        (requires GDOS)
     - bezier curves                            (requires FONTGDOS or above)
     - outline fonts                            (requires FSM or SpeedoGDOS)


 When not under MultiTOS,  the  alpha  text  mode (equivalent to BIOS/GEMDOS
 character output) could  be  entered  by  a  GEM  program  for  instance in
 preparation for execution of a non-GEM (.TOS) program. But MultiTOS has its
 own way of dealing with such programs. The  normal way for a GEM program to
 output text is with V_GTEXT - preferably in a window.

 Input and mouse cursor handling should, as already mentioned, be dealt with
 through the AES rather than  the  VDI,  and  any  vector changes at all are
 generally no business  for  a  clean  GEM  program  (leave  this  to memory
 resident AUTO folder programs).

 Note that although the font cannot be  changed without GDOS, the text style
 as well as the size can be. The  built  in 6x6, 8x8 and 8x16 character sets
 are considered different sizes of the  same  font, and are therefore always
 possible to switch between.


 "USABLE" VDI CALLS:

 This essentially leaves us with the calls  for copying image blocks and for
 drawing text, lines (and line-based objects), filled areas (including flood
 fill) and "markers". Plus functions to control various attributes for these
 operations and of course the calls to open and close virtual workstations.



                      Opening a VDI virtual workstation
                      ---------------------------------

 Before we can use the VDI library we need to open a VDI "workstation".

 The AES  itself,  for  its  own  use,  at  bootup  opens  a  "physical" VDI
 workstation on the screen, and  this  is  how  the  AES box drawing is made
 possible (as well as all the AES input functions).

 Since there can only be one  physical  workstation  open on any device, our
 own workstation on the screen  has  to  be  a  "virtual"  one. (There is no
 practical difference between physical and  virtual workstations except that
 different calls are used to open  and  close  them.  - We will elaborate on
 this matter later in connection with GDOS).

 (Again, some programming packages - like  GFA Basic - incorporate start and
 end sequences that internally opens  and  closes  a virtual workstation, so
 that you may forget all about the  workstation concept - unless you want to
 open an extra virtual workstation or you want to use GDOS for output to the
 printer).

 You CAN open more than one virtual  workstation  on the screen, if you want
 the system to keep track of different sets of drawing attributes. If you do
 that, however, you should try  to  make  sure that the virtual workstations
 are closed in the reverse order that they were opened. A bug in several TOS
 versions may otherwise cause strange things to happen to the output.

 As you must already have  guessed,  it  is  also  possible to open PHYSICAL
 workstations on devices other than the screen, but for that GDOS is needed.

 

 GRAF_HANDLE (an AES call) returns  the  physical  VDI workstation handle of
             the AES to be used  as  input  to  V_OPNVWK. (It also, for some
             reason, returns the width  &  height  of  a  character cell and
             minimum width and height for a BOXCHAR object - see objects).

 V_OPNVWK    opens a virtual workstation  +  gives  lots  of  info about the
             "device" (the screen) and its  VDI  driver (most of which isn't
             particularly interesting). It takes, as an input parameter, the
             physical VDI workstation  handle  of  the  AES  and returns the
             handle of our new virtual workstation - or zero = error.

 VQ_EXTND    gives more info about the workstation (device and driver)
             (There seems to be no GFA Basic binding for this call).

 V_CLSVWK    closes the virtual workstation.

 

 V_OPNVWK may seem to be more complicated than it is, due to the vast amount
 of input and output possible. In reality all the input is usually to follow
 a fixed template, and most of the output can be ignored.

 Important: Note that no binding that  I  have  seen gives the new handle as
 the primary (function) return value (i.e. in register D0 in assembler), but
 instead deals with it as follows:

 The HANDLES (both input and output) are traditionally written to /read from
 a single variable "handle" (word size) given as a parameter to V_OPNVWK.
     (In Devpac read/write word at label "current_handle").
     (In GFA Basic both input and output handles for V_OPNVWK are taken care
     of internally. The output handle can be accessed via V~H).

 At the lowest level of all function  bindings  the handle is written to and
 read from the internal  VDI  contrl  array:  contrl(6)  -  or in assembler:
 address contrl+12.
 An output handle = 0 means that  a workstation couldn't be opened (possibly
 because of lack of memory).

 The REST of the V_OPNVWK input and output is traditionally organized in two
 word arrays called WORK_IN and WORK_OUT:

 WORK_IN (11 words) (Devpac users write to label "intin"; GFA Basic V_OPNVWK
 input parameters are actually the individual elements of WORK_IN):

     WORK_IN should be set according to:  GETREZ+2,1,1,1,1,1,1,1,1,1,2

     I.e. the first word of WORK_IN is  to  be set to GETREZ+2 (= the return
     value of XBIOS(4) + 2),  the  following  9  words should be filled with
     ones and the ending word set to 2.

     The use of XBIOS in a  GEM  context  is,  as  strange as it is, now the
     officially authorized way to  find  the  value  for  the  first word of
     WORK_IN. This  is  the  device-driver  (&  font-set)  ID  which  is  of
     importance only with GDOS installed.
     (Originally a 1 was  intended  to  be  used  here  for a default screen
     driver to be converted by GDOS, but the Atari GDOS never performed this
     conversion and let the 1 stand.)

     The "2" (last word)  stands  for  RC  ("Raster  Coordinates"), i.e. the
     familiar pixel based coordinate type,  and  is  the only possible value
     without GDOS. With GDOS installed "0"  could  instead be chosen for NDC
     ("Normalized Device  Coordinates")  with  the  Y-axis  pointing  up and
     coordinates scaled so that both X and  Y take values 0-32767 (for left-
     right and bottom-top respectively of screen).

     The rest of the WORK_IN  parameters  (the ones) set drawing attributes,
     which you shouldn't normally try to change here (since V_OPNVWK on some
     TOS versions is bugged  I  think,  or  maybe  it  was  just  a faulty C
     binding), but change as need be via the VDI functions for this purpose.


 WORK_OUT (57 words) (Devpac users read  first  45 words from label "intout"
 and then 12 words from "ptsout"; GFA  Basic users can access a system array
 WORK_OUT() at any time, even if no explicit call of V_OPNVWK has been made,
 because GFA internally makes one at start-up anyway.) :-

     The most interesting values are:

     WORK_OUT(0):  Screen width  - 1  (in pixels)
     WORK_OUT(1):  Screen height - 1  (in pixels)

     WORK_OUT(3):  Width of 1 pixel in microns (= millionths of a metre =
     WORK_OUT(4):  Height of 1 pixel  - " -     = micrometres, m or just )
     (Actually these values seem not to be reliable as absolute measures but
     serve in relation to each other to determine the aspect ratio).

     WORK_OUT(13): Number of "pen colours" (=  Same as max. colours possible
     on screen except for high/true colour modes which use "only" 256 here).

     (Devpac users double array element number  to  get the offset to add to
     the label "intout". E.g. WORK_OUT(13) is found at intout+26.)


 A work_out array is also used for  the  output of VQ_EXTND. This call takes
 an input flag word, which if zero causes the same output as V_OPNVWK, while
 if =1 will cause VQ_EXTND to give the extended information.

     The most interesting VQ_EXTND generated values are:

     WORK_OUT(4): Number of bitplanes
     WORK_OUT(5): Palette table flag (0=mono OR high/true colour, 1=palette)
     If the palette flag = 0  AND  the "number of pen colours" - see above -
     is >2 then high or true colour is used.

 (The Atari Compendium suggests a new binding for V_OPNVWK which - by making
 implicit calls of GRAF_HANDLE and XBIOS GETREZ  - does away with ALL input,
 except a pointer to a single output  array, where all the output, including
 the virtual workstation handle plus the output of VQ_EXTND, is written).


                                Using the VDI
                                -------------

 The (virtual) workstation handle  returned  by  V_OPNVWK, is in traditional
 VDI bindings to be used as the  first  parameter of each and every VDI call
 thereafter (including VQ_EXTND and V_CLSVWK).

 Some library bindings, however,  like  the  one  of  Devpac (and apparently
 Hisoft Basic) and GFA Basic, does away with this by saving the handle in an
 internal storage place from which it is  then implicitly read and used with
 each VDI call. On those rare occasions  when  you want to switch to another
 workstation you can write  the  handle  of  this  into the internal storage
 place (with the Devpac library to  the word at label "current_handle", with
 GFA Basic use the "variable" V~H).

                               ---------------

 The four basic graphic elements  -  text,  markers,  lines and fills - each
 have a number of individually  adjustable  attributes. (E.g. one colour can
 be individually set for each of these  four,  to be used only the next time
 that something of its particular  kind  is  drawn.)  Whether to set all the
 related attributes before each and every  drawing operation, or to remember
 and change them only when needed, must be left to the personal taste of the
 programmer, and perhaps  also  dependent  on  the  type  of  program  he is
 writing. (See  below  for  explanations  of  some  specific  attributes and
 operations.)

 In addition there are a few functions controlling general settings:

     VS_COLOR  - Input: VDI "colour pen" index and then RGB in VDI format
     VQ_COLOR  - Input: VDI pen, flag (0=exact 1=actual); Returns RGB colour
     VS_CLIP   - Input: clipping-flag (0=off, 1=on), VDI-rectangle
     VSWR_MODE - Input: writing mode (0,1,2 or 3 - see below)

 VS_COLOR sets the colour of a VDI "drawing pen". This on a high/true colour
 screen means just that. No effects will be visible until that "pen" is used
 to draw something, and once the workstation is closed the setting will have
 no meaning any more. On palette based screens, on the other hand, each "VDI
 pen" corresponds of course to a  hardware  palette register which means the
 change will globally affect all  screen  workstations and will last exactly
 until the next time someone changes that pen/register.

 The value of each RGB component should  be 0-1000, and the numbering of the
 VDI pens do NOT correspond  to  the  hardware  register  numbers - see more
 below. (Which pen to actually  use  for  lines  and which ones for markers,
 fills  and  text  is  determined  with  VL_COLOR,  VM_COLOR,  VF_COLOR  and
 VT_COLOR.)

 VQ_COLOR asks what colour is set for a  pen. If the second parameter is set
 to 1 the colour actually  displayed  will be returned (hardware dependent),
 and this could be used to determine  how many intensity levels the hardware
 is capable of (by trying out - with VS_COLOR - various intensity values and
 seeing with - VQ_COLOR flag=1 - what intensities are actually displayed).

 VS_CLIP sets a clipping  rectangle  within  which  all  VDI  output will be
 constrained. This is normally to precede each drawing operation such as the
 updating of (part of) a window,  in  order to avoid corrupting screen parts
 owned by other processes.  (Turning  the  clipping  off  could speed up the
 drawing - if you really know where you are drawing!)

 VSWR_MODE sets the writing mode  which  determines  how  to use source data
 (the things we draw) on the destination screen.

 Writing mode:     ... operates for each source bit 1/0 thus on destination:
   1 (replace) = default    1: uses set colour pen  0: uses pen 0* (white)
   2 (transparent)          1: uses set colour pen  0: leaves it
   3 (XOR)                  1: inverts its colour   0: leaves it
   4 (inverse transparent)  1: leaves it            0: uses set* colour pen

 (* = With VRT_CPYFM - see below -  not  one but two colour pens are set and
 the special 0-bit pen used in modes 1 and 4.)

 NOTE: Where either replace or transparent  modes would give the same result
 - i.e. for solid lines/shapes - replace is preferable for speed.


                   Image copying - to and from the screen
                   --------------------------------------

 For copying image  rectangles  to  or  from  the  screen,  the  VDI "raster
 operations" VRO_CPYFM and VRT_CPYFM are used.

 VRT_CPYFM   can copy "mono" (= two-colour) images on to any screen.

 VRO_CPYFM   is used to copy between  images  (or  screen)  of any number of
             colours as long as the number  of  colour bitplanes is the same
             in both images.
             (Scrolling can be implemented by copying from screen to screen)

 These functions depart from other VDI output operations in that they aren't
 affected by the  writing  mode  of  VSWR_MODE  (but  they  ARE  affected by
 VS_CLIP). Instead they take a  writing  mode  of  their own as a parameter,
 which for VRT_CPYFM uses the  same  values  as  the  one for VSWR_MODE (see
 above) but for VRO_CPYFM is as follows:-

 VRO_CPYFM mode:     writes:       corresponds to VRT_CPYFM / VSWR_MODE:
   0 (clear)         - 0
   1                 - source AND destination
   2                 - source AND (NOT destination)
   3 (replace)       - source                           1
   4 (erase)         - (NOT source) AND destination
   5 (No OPeration)  - destination
   6 (XOR)           - source XOR destination          (3 on mono screen)
   7 transparent     - source OR destination           (2 on mono screen)
   8                 - NOT (source OR destination)
   9                 - NOT (source XOR destination)
  10 (invert)        - NOT destination
  11                 - source OR (NOT destination)
  12                 - NOT source
  13                 - (NOT source) OR destination     (4 on mono screen)
  14                 - NOT (source AND destination)
  15 (fill)          - 1

 Further parameters  of  VRO_CPYFM  and  VRT_CPYFM  define  the  source  and
 destination images (or screen)  plus  the  coordinates  (in both source and
 destination) and size of the rectangle to copy. VRT_CPYFM in addition takes
 two colour pen numbers to be used for 1-bits and 0-bits in image data.

 The source and destination are  specified  by  pointers NOT directly to the
 image/screen but to MFDB's (Memory Form Definition Blocks):

     MFDB (20 bytes):
       L: Pointer to image, or 0 if screen is referred to
       W: Width in pixels
       W: Height
       W: Width in words  = (width in pixels +15)/16 truncated
       W: Format flag:  1 for device independent  0 for device specific
       W: Number of planes
      3W: 0 (reserved)

 An MFDB for the screen need not or  should not be filled in. Just make sure
 that its first longword is zero,  and  the  VDI will do the rest. (Actually
 the rest of the MFDB will not be touched  or  used at all, but to be on the
 safe side let the zero longword be followed by four more, uninitialised but
 free-to-use, longwords.)

 DEVICE SPECIFIC DATA (flag=0) are organized  like  in screen memory. If you
 want to program cleanly  you  shouldn't  let  anything  but  the VDI raster
 functions touch an image on  this  format  (since  you don't know how every
 graphic card  etc.  organizes  its  memory).  VRO_CPYFM  and  VRT_CPYFM are
 currently unable  to  deal  with  anything  else,  whether  for  source  or
 destination, but with VR_TRNFM you can transform between this and ...

 DEVICE INDEPENDENT DATA (flag=1) are bitplane-separated.
     - For a palette-based image, this  means  that  bit 0 for all pixels of
     the image come first in  a  'bitplane  0',  followed by bitplane 1 etc.
     (Together all a pixel's bits  RIGHT-TO-LEFT  form a colour index number
     into the palette.)
     - For an RGB  high/true  colour  image,  I   assume  (from the IMG file
     organization described in Atari Compendium  (AC) that bitplanes come in
     the order that their bits will  be  used  LEFT-TO-RIGHT in RGB words or
     byte-triplets: RRRRRGGGGGGBBBBB  for  high  or RRRRRRRRGGGGGGGGBBBBBBBB
     for true colour (A Falcon user might confirm this?).

 In any case the pixel bits IN EACH BITPLANE come in the natural order left-
 to-right and then top-to-bottom as you would write binary numbers and image
 bitmaps in any (ST) programming language. Important: Each new pixel line in
 a plane always begins at a word boundary.

 An image that is to be saved/loaded or manipulated in any other way than by
 VDI operations MUST (in a clean program) be in device independent format.

 VR_TRNFM    is the call with which to  transform between formats. Note that
             it takes pointers to  both  a  source  and  a destination MFDB.
             These CAN be  the  same  (to  save  space)  but  that makes the
             transformation slow. VR_TRNFM will look  at the format flag for
             the source MFDB only and invert this in the destination MFDB.


                Colour palettes in GEM. The V_GET_PIXEL call
                --------------------------------------------

 Whenever we want to set up or  use  a  palette  in GEM (with images of more
 than 2 colours) we need to take the difference between VDI colour numbering
 and bitplane-related ("hardware") colour numbering into consideration.

 For each pixel  we  will,  by  combining  right-to-left  one  bit from each
 bitplane, get the colour index for  that  pixel  to use into a palette, but
 the imbecile programmers of Atari  GEM  decided  in their wisdom - probably
 while hysterically giggling - that these index numbers were NOT be equal to
 the VDI pen numbers. And this means  that  we are forced to translate every
 palette colour number we want to access  into  a VDI pen number to use with
 VS_COLOR. (There are many GEM programs which use XBIOS instead of VS_COLOR,
 but that may lead to incompatibility problems; Hyperpaint is one example).

 The only really compatible way to  create  a translation table from palette
 colour numbers to VDI colour pens, is to do it on-the-fly while running the
 actual video hardware with which the table is to be used (because there ARE
 graphic cards where VDI pen numbers = palette indices).

 A routine for such a runtime  table  creation  is described below, based on
 the function V_GET_PIXEL whose first return value is the palette colour and
 the second one is the VDI pen  for  a  specified pixel. (In Devpac read the
 first and second elements of intout array).
 Both the marker type and writing mode  are  assumed  to be = 1 (the default
 value):

  1) With VSM_COLOR set the VDI colour pen to use with markers
  2) With V_PMARKER write pixel (0,0)   (assumes marker type = wr.mode = 1)
  3) With V_GET_PIXEL read pixel (0,0) and  use  the first return value (the
     palette colour) as an index into the table to enter the VDI pen number.
  4) Go back to 1) and do next VDI pen.

 (Of  course  you  should  restore  the   original  colour  of  pixel  (0,0)
 afterwards.)

 NOTE: The above of course doesn't  apply  to RGB screens where there exists
 no relation at all between pixel data  and  VDI colour pens. (On a palette-
 based screen the colours of pixels can  change when a pen colour is changed
 but this never happens on an  RGB  screen). Here V_GET_PIXEL's first return
 value will be (the lower  word  of)  the  RGB  value  for the pixel and the
 second value will be zero for high colour  or contain the red bits for true
 colour (according to AC).

                      Marker attributes and operations
                      --------------------------------

 The only thing to be said about this  is that marker type #1 (=the default)
 is a single  pixel  and  is  not  affected  by  the  marker  size  set with
 VSM_HEIGHT.

 V_PMARKER with marker type set  to  1  is  the  fastest  way in GEM to draw
 single pixels.

                       Line attributes and operations
                       ------------------------------

 V_PLINE ("polyline") could also be  used  for plotting pixels (it evidently
 is by the GFA Basic command PLOT) but  it is slower, and two points need to
 be specified, with equal coordinates for "a line that is a point".

 Note that the line width, set  with  VSL_WIDTH, only takes odd values (even
 numbers are decreased by 1) and that  the  line type set with VSL_TYPE only
 is used when line width =  1  (for  all  wider  lines  a solid type will be
 used). (This pertains to  the  normal  screen  driver. With VQ_EXTND you'll
 find out if any other rules applies.)

 There is a line-based (=unfilled) rectangle drawing operation - V_RBOX - to
 draw a rectangle WITH  ROUNDED  CORNERS  (no  control  over roundness), but
 curiously none for a simple box with  angular corners, so V_PLINE will have
 to be used for that.  (GFA  Basic  defines  its  own BOX command apparently
 based on V_PLINE).

 Contrary to what is suggested  in  the  AC,  the line attributes affect the
 purely line based operations only - NOT any fill perimeter (see below).

                       Fill attributes and operations
                       ------------------------------

 The fill style is  determined  with  one  main  setting and two subordinate
 ones:

 VSF_INTERIOR determines the main fill style:
     0 = "hollow"      - 0-bits = pen 0 (white) or hollow - see write mode
     1 = "solid"       - 1-bits = the fill colour pen set with VSF_COLOUR
     2 = "patterned"   - Above two colours
     3 = "hatched"     - Above two colours
     4 = user defined  - Above two colours  OR  any of colours on screen

 VSF_STYLE determines a sub-style used with  patterned or hatched fill only.
 (Takes a number: 1-24 for patterned, 1-12 for hatched styles.)

 VSF_UDPAT determines the user defined  16x16  fill  pattern (used when main
 style = 4). It takes two parameters:
     1) a pointer to the pattern and
     2) the number of bitplanes (or 32 for true/high colour patterns)

     (The Devpac macro requires  you  to  write  the  pattern into the intin
     array and (the number of planes * 16) to address contrl+6.)

     The number of  planes  can  always  be  set  =  1   for  a mono pattern
     regardless of colours on screen.
     The other option is to use  the  number  of planes on screen (except if
     this runs in true or high colour when 32 must be used).

     The pattern itself is formed by 16  words per bitplane (first all words
     for plane 0, then for plane 1  etc.) - except for true/high colour when
     a "pixel-packed" format is used (for  each pixel a longword: $00RRGGBB,
     16*16 = 256 longs = 1K total).

     Regarding relations between bitplanes and GEM colour pens - see above.

                               ---------------

 VSF_PERIMETER is used to  determine  whether  we  want filled objects drawn
 with an outline or not. (The fill colour  pen is used, NOT the line colour,
 and no other line attributes are  used  either). Note that VR_RECFL (filled
 rectangle) never uses the perimeter.  But the otherwise entirely equivalent
 V_BAR does (and so do other filled shapes).

 V_FILLAREA is analogous to V_PLINE (polyline) but will automatically bridge
 any gap between first and last  point,  resulting in a filled polygon being
 drawn.

 V_CONTOURFILL takes three parameters - x, y  and borderpen - and performs a
 flood fill, starting at the given  point  and spreading until pixels in the
 colour of the given pen are found.  (Will work in high/true colour too). By
 specifying a border colour pen = -1,  the  spread will instead be halted by
 pixels in any other colours than that of the start pixel.

                       Text attributes and operations
                       ------------------------------

 Once again, change of font with VST_FONT is NOT possible without GDOS.

 VST_ROTATION sets the text angle in units of 10ths of degrees:

           900
            |         0 = Normal left-to-right
     1800 --+-- 0   900 = Bottom-to-top
            |      1800 = Upside-down right-to-left
          2700     2700 = Top-to-bottom

 NOTE: These right angles are the only  ones possible with the normal screen
 driver. (Outline fonts with FSM/SpeedoGDOS should  be possible to rotate in
 other angles). VQ_EXTND tells you the rotation capabilities of any device.

 VST_ALIGNMENT simply determines the  reference  point  within a text string
 printed with V_GTEXT or  V_JUSTIFIED.  The  latter  operations, by default,
 write the text string so  that  its  left  edge  and  baseline are on given
 coordinates x,y, but this can be changed.

 Parameter  Reference point at:
    1)      0 = Left edge of text string
            1 = Centre      -  "  -      - recognized only by V_JUSTIFIED
            2 = Right edge  -  "  -      -            -  "  -
    2)      0 = Baseline (= bottom of most letters)
            1 = Half line (= top of most lowercase letters)
            2 = Ascent line (= top of normal uppercase letters)
            3 = Bottom of text string
            4 = Descent line (= bottom of descending letters: g,j,p,q,y)
            5 = Top of text string

 Usually you  probably  want  to  use  VST_ALIGNMENT(0,5  ...)  to  set  the
 reference point in the upper  left  corner  the  way most other objects are
 referenced by the AES and VDI.

 But note that if we rotate  the  text,  the reference point will be rotated
 with it, so that we must use VST_ALIGNMENT(0,3 ...) for top left point of a
 text rotated by 2700. (For  the  angles  900  and  1800 we'd have to change
 alignment to right  edge  of  text  but  that  would  unfortunately  not be
 recognized by V_GTEXT. Luckily these angles are less useful).

 VST_HEIGHT and VST_POINT both set  the  text  size.  They each take a size,
 supposedly in pixels for VST_HEIGHT  and  points (1/72 inch) for VST_POINT,
 but since this measure isn't simply  referring  to the actual height of the
 character bitmap but rather to  some  mysteriously (to me) defined internal
 character height I think the below table might be of use:

 VST_HEIGHT  VST_POINT  System font size
      4           8          6x6
      6           9          8x8
     13          10          8x16
      -          16         12x12 (6x6 doubled)
     12          18         16x16 (8x8 doubled)
     27          20         16x32 (8x16 doubled)

 The real difference between these calls is that VST_POINT only gives us the
 above sizes  while  VST_HEIGHT  scales  sizes  in  between  (yes,  even for
 bitmapped fonts). From this you might  think  that VST_HEIGHT is the one to
 prefer, but I would say it  is  precisely  the  other way around, since the
 scaled bitmapped fonts are terribly  ugly.  Use of VST_POINT will guarantee
 that a decent looking  size  is  always  selected.  (The doubled sizes look
 blocky of course, but if you  desperately  need an easy-to-get big font the
 doubled 8x8 or 16x32 sizes might perhaps be of some use.)

 Both calls  return  (in  four  extra  parameters  or  in  the  PTSOUT array
 depending on the binding) the set "character" widths and heights and "cell"
 ditto in pixels. The "character"  dimensions  are  the same kind of useless
 garbage that VST_HEIGHT takes for  input,  while  the "cell" dimensions are
 the real character bitmap dimensions.

 In addition, the primary  return  value  of  VST_POINT  is the actually set
 "point size" - which will differ  from  any "illegal" point size requested.
 (For more general programming - useful with GDOS - this feature may be used
 to find out how many sizes there are.)

 When using GDOS, VST_POINT will  give  us  the  point  sizes defined in the
 ASSIGN.SYS file only. (With Speedo and FSM_GDOS there exists an alternative
 call for outline fonts -  VST_ARBPT  -  with  which  to  set point sizes in
 between.)

                               ---------------

 VQT_EXTENT is a call that  might  need  some  explanation.  It takes a text
 string as input and calculates a rectangle  big enough to surround the text
 string (if written with current VDI text settings including rotation). This
 can be used for instance to draw an  outline box around the text or to draw
 a  background  colour  (as  a  filled  box)  before  writing  the  text  in
 transparent mode.

 Unfortunately VQT_EXTENT doesn't simply return the  width and height of the
 rectangle, as I think would have  been  the most convenient, but gives four
 coordinate pairs (= 8 words) specifying each  of the four corners - the top
 left one always being (0,0).

 For unrotated text, coordinate pairs 0 to 3 correspond to corners according
 to:
      x0,y0 --- x1,y1    x0,y0 = 0,0
        |         |
        |         |
      x3,y3 --- x2,y2

 (Most TOS books - including the AC - are incorrect about this).

 For rotated text however, the order  of the coordinates will vary, probably
 in a (failed) attempt by the TOS creators  to rotate them with the text. On
 the other hand, they will always come  in  some clockwise order, and can be
 used for "poly-operations" - such as V_PLINE  to  draw  a box - if you just
 add the coordinates of  (the  upper  left  corner  of)  the text string and
 repeat the first coordinate pair as a fifth one.

 And since the VDI seems to understand  any diagonally opposite corners as a
 rectangle, I think you can always use the first and third pair with various
 box operations such as VR_RECFL (again after adding text coordinates).

