

                              M a k e D r a w 
                              ===============
                              

MakeDraw version 1.00
(c) Copyright Chris Dennis, May 1991


The MakeDraw version 1.00 package consists of the following files:

  MakeDraw    Basic      : The MakeDraw Basic library
  MDDocn      Text       : Complete documentation for MakeDraw (this file)
  MDSetDir    Obey       : Obey file for setting MD$Dir
  Alpha       Basic      : Example programme
  AutoCurve   Basic      :      - " -
  ClosePath   Basic      :      - " -
  Inflation   Basic      :      - " -
  LineStyle   Basic      :      - " -
  Moving      Basic      :      - " -
  Spirell     Basic      :      - " -
  StarFract   Basic      :      - " -
  TextStyle   Basic      :      - " -

All files are dated 27-May-1991.
    

Conditions
==========

This software and accompanying documentation are Shareware.  This covers
the MakeDraw Basic library file itself as well as the example programmes
included in the package.

The software and documentation may be freely copied and distributed as a
complete package provided they are unchanged and include the copyright
notices.  Neither the software nor this documentation may be modified or
distributed in modified form (although you may change the example programmes
as much as you like for your own use).  Shareware distributors may charge
only for media and distribution expenses, not for the software itself,
although they may make an extra charge if the profit is to be given to a
registered charity.  

MakeDraw may be used commercially, but not included in any other commercial
product without written agreement from the author.  Diagrams (draw files)
created with this product become the property of the user and may be
distributed or sold without any further royalties being payable.

The software is offered "as is"; the author makes no warranty, express or
implied, of its fitness for any particular purpose.  In no circumstances
will the author be liable for any damage, loss of profits, time, or data, or
any indirect or consequential loss arising out of the use of this software
or inability to use this software, even if the author has been advised of
the possibility of such loss.  


Ugrades and Registration
========================              

I would be pleased to receive any comments about this software, or
suggestions for ways in which it could be improved.  Current plans for
improvements include support for sprites and text areas, the ability to use
the high-level routines such as PROCmdCircle from within a path, and a
relocatable module version that will be accessible from languages other than
Basic.

If you find this software useful, a contribution sent to the author at the
address below would be appreciated.  Contributions of at least NZ$20.00 (if
you live in New Zealand) or NZ$30.00/10.00 (if you live outside New
Zealand, to cover the extra costs of postage) will make you a registered
user, entitled to news of upgrades and other future products, as well as
technical support for MakeDraw.
            
Upgrades will be free to registered users who send a 3.5" disk (preferably
formatted).  If you prefer, I can supply a disk and a padded envelope for
NZ$4.00/1.50 - that way you will save a bit on the postage when you write
to me.  You should not send for an upgrade until you know that one is
available: I will contact registered users when upgrades are ready.

New Zealand prices quoted include GST; prices for users outside New Zealand
are exempt from GST (NZ's equivalent of VAT).  I will happily accept payment
in either New Zealand dollars or pounds sterling.

Technical support can also be provided free to registered users either by
phone or letter, although I don't suppose you will want to phone me from
outside New Zealand! (if you do, don't expect much support if it's the
middle of the night here - check your time zones).  You should include full
details of the version of MakeDraw you are using (as reported by a call to
PROCmdHelp) as well as the type of machine you are running it on and the
version of BBC Basic, and a complete description of your problem.

Please note that the time taken for airmail to get between New Zealand and
the UK can vary from a few days to a couple of weeks, so please be patient
if you do not get an immediate reply.  Surface mail takes at least two
months, so make sure anything you send is liberally plastered with airmail
stickers.
                                                                   
My address and telephone number are:

  Chris Dennis
  80 Catherine Crescent
  Paparangi
  Wellington 6004
  New Zealand

  Phone: New Zealand 0-4-786 632 (until 24 October 1991)
                     0-4-478 6632 (from 25 October 1991)


MakeDraw
========

MakeDraw is a library of Basic routines for the Archimedes which allows
DrawFiles to be created directly from Basic programmes.  The Draw files can 
then be displayed and printed using the standard !Draw application.

This approach has several advantages over the traditional method of creating drawings "by hand" using !Draw:
  - graphs can be created directly from data calculated or collected by the 
    programme (see example programme "Inflation").
  - drawings that require objects to have precise dimensions or positions 
    can be created - this is at best very tedious to do in !Draw.
  - repeated objects can be defined within a loop in very few statements.
  - automatic positioning of control points for bezier curves: !Draw places
    the control points for you when you first enter a curve, but does not 
    update them if you move the end point; MakeDraw allows curves to be 
    positioned with complete accuracy.                      
  - breaks can be made in automatically smoothed curves without interrupting
    the smooth shape of the curve.

The only features of !Draw that are not possible with the present version of
MakeDraw are the inclusion of text areas and sprites in diagrams.


Using MakeDraw
==============

BBC Basic V includes the facility for accessing libraries of routines (i.e.
procedures and functions) from your own programmes - this is described fully
in the Archimedes BBC Basic Guide or the older (pre-RiscOS) User Guide.

To use the MakeDraw library your programme must include the statement

  LIBRARY "[directory.]MakeDraw"

with [directory.] replaced by the name of the directory containing MakeDraw;
if MakeDraw will be in the current directory when the programme is run,
leave [directory.] out altogether.  This statement must occur before any
calls to MakeDraw routines.

The example programmes, together with the MDSetDir obey file, demonstrate
one method of ensuring that the MakeDraw library is available at run time.

Alternatively, you can use the INSTALL command, which will make the library
available to all programmes you run until the end of the Basic session.

In this documentation I am assuming that you are familiar with the !Draw
application, and its concepts of "diagram", "object", "path", "line
segment", "bezier curve", and "control point".  The chapter on !Draw in the
Archimedes User Guide explains them quite well.
 
You should also be aware of the difference between the !Draw application and
the Draw module, which is part of the operating system (in ROM).  The draw
module is the thing that actually displays objects on the screen, and has
capabilities beyond those used by !Draw.  What MakeDraw does is create files
in exactly the same format as !Draw creates them when you save a diagram.
These files can then be loaded into !Draw in the usual way, and from there
the diagrams can be displayed, manipulated, and printed just like any other
draw file.

Simple shapes - straight lines, rectangles, circles, and ellipses - can be
created by a single procedure call.  Other shapes are created by defining
the path one segment at a time.

If any of the objects in your diagram overlap, the ones defined first will
appear behind ones defined later.  Example programme "Spirell" gives a good
example of how objects are defined in order of decreasing size, so that the
small ones are not hidden by the big ones.

The MakeDraw library has been made as compact as possible, which is why all
comments and blank lines have been stripped from the code.  It is not
intended that you read the source code - the documentation should tell you
all you need to know about the routines.


Example Programmes
==================

A number of example programmes have been included with MakeDraw to show you
how easy it is to create quite complicated and precise diagrams.  Running
each programme will create a draw file with the same name as the programme
except for a "D" or a number on the end of the name.  The draw file can
then be displayed and printed by loading it into !Draw in the usual way.

The example programmes are best run from the desktop.  Before you do so, you
should run obey file MDSetDir, which sets operating system variable MD$Dir
to the directory containing the MakeDraw package and allows the programmes
to find the MakeDraw library.  Then all you have to do is double-click on
the example programmes themselves to run them.

Programme "StarFract" will prompt you for a number between 0 and 4: the
complexity of the diagram it creates depends on your response.  It saves its
output as "StarFract<n>", with <n> replaced by the number you chose, so all
five possible draw files can be created and compared.  All the other example
programmes simply create a single draw file and give a message telling you
that they have done so.


Naming Conventions
==================

To avoid clashes with your own names for variables and procedures, all
global names used in MakeDraw begin with either "md" or "_md".  

The procedures and functions that you will be using have names such as
PROCmdRectangle or FNmdDefineFont.  There are also some global "constants"
set up by PROCmdInitialise, for example mdInch%, which should be considered
"read-only" and not altered from their original values.

The MakeDraw routines also use some global variables which are considered
internal to the library and should be left well alone.  Their names begin
with "_md".


The !Draw Coordinate System
===========================

!Draw works in its own system of units, referred to here as "draw units".
There are 46,080 of these units per inch, which defines the maximum
resolution diagrams as 1/46080".  This apparently curious number is actually
180*256, and seems to have been chosen for its large number of factors -
46080 can be divided by 2, 3, 6, 12 etc. without leaving a remainder, which
is important because coordinates and lengths are stored as integers.

The coordinate system is very similar to that used for "ordinary" screen
graphics: the point (0,0), the "draw origin", is at the bottom left hand
corner of the diagram, and (46080,46080) is one inch above and to the right
of the origin.  The position of points relative to the origin in draw units
will be referred to as "draw coordinates".

Objects can have negative draw coordinates, such as (-46080,-92160), but
there is no way of pulling the scroll bars in !Draw across far enough to
display them.  Such objects can only be brought into view by grouping them
together with an object that is visible, and then dragging the whole group
up and to the right.  In general, you should avoid creating objects with
negative draw coordinates.

By default, MakeDraw works directly in draw coordinates but gives you the
option to work in more convenient units (such as inches or centimetres) and
to define your own origin, in the same way as "VDU 29" is used for setting
the origin for screen graphics.

The are two possible approaches to using your own units.  One way is to use
a multiplier on every value passed to a MakeDraw routine.  A number of
suitable multipliers are defined as "constants" when MakeDraw is
initialised.  These are:

  mdInch%     = 46080
  mdCM%       = mdInch% / 2.54
  mdMM%       = mdInch% / 25.4
  mdPoint%    = mdInch% / 72
  mdDrawUnit% = 1
                        
So a value of 1.75cm can be written as 1.75*mdCM%, or half an inch as
mdInch%/2.  If you wanted to work in tenths of an inch, you could create a
variable called tenths% and set it to mdInch%/10 (or 4608), and then use,
say, xpos%*tenths% as an x-coordinate.

Alternatively, you can tell MakeDraw what units you want to work in, so that
you do not have to worry about multipliers.  This is done by calling
PROCmdSetUnits, passing it the number of draw units that will make up one
"user unit".  For example, to work in millimetres, you would include the
statement

  PROCmdSetUnits(mdMM%)

All subsequent coordinate and size values passed to MakeDraw routines will
then be automatically multiplied by mdMM% for you before they are used.  For
example,

  PROCmdRectangle(200,200, 50,100, 0)

would create a rectangle 50mm by 100mm, with its lower left-hand edges 200mm
from the edge of the draw origin.

IMPORTANT: these two approaches to using units should not be mixed!  If for
example, you execute PROCmdSetUnits(mdInch%) and then try to use 10*mdCM% as
a coordinate value, the actual draw coordinate generated will be
mdInch%*10*mdCM%, which is too big to be held as a Basic integer and will
result in Basic error "Number too big".

Defining your own origin is achieved by calling PROCmdSetOrigin and passing
the new origin as parameters.  Coordinates passed to all subsequent calls to
MakeDraw routines will be considered to be relative to this user origin.
For example, to set the origin to a position 4 inches up from the draw
origin and 5 inches to the right, you would use

  PROCmdSetUnits(mdInch%)
  PROCmdSetOrigin(5,4)

A circle which touches the bottom edge of the diagram could then by created
with

  PROCmdCircle(0,0, 4)

The real draw origin would be at (-5,-4) in user coordinates.

        
Colours
=======

As in !Draw itself, colours are defined by setting each of the red, green,
and blue components to a value between 0 and 255.  The actual colour
displayed will be the nearest available in the current screen mode.

For reference, the standard settings used in 16-colour modes are set out
here:

   Colour            Red     Green      Blue
   -----------       ---     -----      ----
   White             255       255       255
   Grey 1            221       221       221
   Grey 2            187       187       187
   Grey 3            153       153       153
   Grey 4            119       119       119
   Grey 5             85        85        85
   Grey 6             51        51        51
   Black               0         0         0
   Dark blue           0        68       153
   Yellow            238       238         0
   Light green         0       204         0
   Red               221         0         0
   Cream             238       238       187
   Dark green         85       136         0
   Orange            255       187         0
   Light blue          0       187       255


Contexts
========
                                       
MakeDraw routines have to be called in a certain order to create a diagram.  This is mainly a matter of common sense, but the rules are set out here to make things clear.

  - PROCmdInitialise must be the first routine called because it sets a
    number of internal variables and initialises the buffer.  

  - PROCmdInitialise can only be called once in any programme.  If you want
    to create more than one diagram from a programme use PROCmdReinitialise.

  - all calls to FNmdDefineFont must be made immediately after
    PROCmdInitialise or PROCmdReinitialise.

  - the PROCmdSet... routines can be called at any time after 
    PROCmdInitialise: the settings remain in effect until the end of the
    programme or a call to PROCmdReinitialise (or another call to the same
    PROCmdSet... routine).

  - PROCmdTrace and PROCmdNoTrace can be called at any time after 
    PROCmdInitialise: the trace setting remains in effect until another call
    to one of these routines or the end of the programme.

  - PROCmdStartPath starts the definition of a path.  Until the path is 
    completed with PROCmdEndPath, the "high-level" routines PROCmdLine,
    PROCmdRectangle, PROCmdCircle, and PROCmdEllipse cannot be used (as they     create their own complete paths); nor can PROCmdText be used in this
    context.  In addition, a path cannot be closed until at least one line
    segment has been drawn - i.e. a path cannot consist entirely of moves
    (created either by PROCmdMoveTo or PROCmdAutoCurveTo(x,y,FALSE)).

MakeDraw will generate error 255 "<routine name> used out of context" if
these rules are not followed.

For example:

  PROCmdInitialise(2048,0)
  PROCmdLine(0,0, 10,10)
  f1% = FNmdDefineFont("Trinity.Medium"): REM Wrong!

will result in the error message "mdDefineFont used out of context" because
FNmdDefineFont should have been called before PROCmdLine.


Error Messages and Debugging
============================

If MakeDraw detects a mistake in any of the calls your programme makes to
MakeDraw routines, it either prints a warning message and continues, or
generates a Basic error, in which case the action taken will depend on any
"ON ERROR" statements in your programme.        

Basic errors can also occur if MakeDraw is used incorrectly, such as
"Unknown or missing variable" if PROCmdInitialise is not the first MakeDraw
routine called, or "Number too big" if an invalid coordinate value is passed
to a routine.

Because of the way Basic reports error messages when using libraries, the
line number is no help - it will just be the last line number in your
programme when it means a line in the library.  To help get round this
problem, MakeDraw includes a trace facility to help you track down any bugs.
Tracing is turned on by PROCmdTrace and turned off again by PROCmdNoTrace;
by default tracing is turned off by PROCmdInitialise.

Tracing will reveal some calls to routines that are made automatically, for
example PROCmdStartPath calls PROCmdMoveTo to set the current position, and
PROCmdRectangle makes various calls to the lower-level path routines.

Warnings
--------
 
"<n> group(s) had to be closed automatically"
Issued by PROCmdSaveDiagram if it finds that one or more groups have been
started but not ended.  All such groups will be closed, but the result will
not necessarily be what you intended.

"An extra straight line will be added to close the path"
Issued by PROCmdClosePath if the coordinates of the last line segment in the
section of the path being closed are not the same as those of the beginning
of the section.  The reason why a warning is needed in this situation is
given in the description of PROCmdClosePath below.

"Invalid cap height - ignored"
Issued by PROCmdSetLineStyle if the cap height parameter is not in the range
0 to 255.  The cap height setting will remain unchanged.

"Invalid cap width - ignored"
Issued by PROCmdSetLineStyle if the cap width parameter is not in the range
0 to 255.  The cap width setting will remain unchanged.

"Invalid cap height - ignored"
Issued by PROCmdSetLineStyle if the cap height parameter is not in the range 0 to 255.  The cap height setting will remain unchanged.

"Invalid endcap type - ignored"
Issued by PROCmdSetLineStyle if the endcap type parameter is not in the
range 0 to 3.  The endcap type setting will remain unchanged.

"Invalid font reference - zero assumed"
Issued by PROCmdSetTextStyle if the font id parameter is not a value
returned by a previous call to FNmdDefineFont or zero.  A value of zero will
be used instead which will mean the text will be displayed in the system
font.

"Invalid join type - ignored"
Issued by PROCmdSetLineStyle if the join type parameter is not in the range
0 to 2.  The join type setting will remain unchanged.

"Invalid startcap type - ignored"
Issued by PROCmdSetLineStyle if the startcap type parameter is not in the
range 0 to 3.  The startcap type setting will remain unchanged.

"Invalid winding rule type - ignored"
Issued by PROCmdSetFillStyle if the winding rule type parameter is not in
the range 0 to 1.  The winding rule type setting will remain unchanged.

"No groups open"
Issued by PROCmdEndGroup if there are no open groups to close, indicating
that your calls to PROCmdStartGroup and PROCmdEndGroup are not paired
correctly.  The call is ignored.

Errors
======

All error messages are given error number 255.

"<routine name> used out of context"
Issued if MakeDraw routines are used in the wrong order.  See the section
above on "Contexts" for details.

"Buffer too small"
Issued if the amount of memory set aside by PROCmdInitialise is not enough
to hold the diagram.  Increase the size of the buffer and run your programme
again.

"Groups nested too deeply"
Issued by PROCmdStartGroup if you attempt to open more than 64 groups at
once.



Procedures and Functions
========================

The procedures and functions included in the MakeDraw library are described
here in detail.  


Initialisation routines
-----------------------
            

PROCmdInitialise(memory%,pointer%)
----------------------------------

This procedure must be called first to initialise MakeDraw and set up an
area of memory (a "buffer") in which the other MakeDraw routines will create
the diagram.

Calling any other MakeDraw routine without first calling PROCmdInitialise
will result in an error, usually "Unknown or missing variable".

The first parameter is an integer indicating the number of bytes required -
this will be an estimate depending on how complex the diagram is going to
be.  A few thousand bytes will be enough for most diagrams.  If MakeDraw
runs out of memory before the diagram is complete, it will generate error
255 "MakeDraw: Buffer too small", in which case you will need to increase
the value of this parameter and re-run your programme.

There are two ways in which the required memory can be allocated.  If the
second parameter to PROCmdInitialise is zero, MakeDraw will execute its own
DIM statement; if required, the address of the buffer can be discovered by
calling PROCmdDiagramInfo.  For example:

  PROCmdInitialise(8192, 0): REM Ask MakeDraw to set up an 8k buffer

If there is not enough memory available for the size of buffer you request,
Basic error 11 "No room for this DIM" will occur.

Alternatively, you can use your own DIM statement to set aside an area of
memory, and pass its address as the second parameter.  For example:
                  
  buffer_size% = 4096
  DIM buffer% buffer_size%
  PROCmdInitialise(buffer_size%, buffer%)

If you do this, you must ensure that the buffer is as big as you say it is,
otherwise MakeDraw may overwrite part of Basic's workspace, leading to
obscure errors or even crashing the system.

This second method is useful if your programme creates more than one diagram
as the same buffer can be used for each.  Note that PROCmdInitialise can
only be called once in a programme: calling it again will give an error
because it dimensions some arrays of its own and the same variable cannot be
DIMed more than once.  Instead, PROCmdReinitialise must be called to start
the second and subsequent diagrams.  For example:
                  
  buffer_size% = 4096
  DIM buffer% buffer_size%
  PROCmdInitialise(buffer_size%, buffer%)
  ...(calls to other MakeDraw routines)
  PROCmdSaveDiagram("diagram1")
  PROCmdReinitialise(buffer_size%, buffer%)
  ...(calls to other MakeDraw routines)
  PROCmdSaveDiagram("diagram2")


PROCmdReinitialise(memory%,pointer%)
-------------------------------------

This routine resets MakeDraw's internal variables ready for a new diagram.
It can therefore only be called immediately after a call to
PROCmdSaveDiagram which indicates that the previous diagram is complete.

The parameters memory% and pointer% have the same meanings as in
PROCmdInitialise.  If pointer% is zero, MakeDraw uses the same buffer as it
did for the previous diagram.  If not, it is assumed to be the address of at
least memory% bytes that can be used as a buffer.

See the description of PROCmdInitialise for further details and an example
of the use of this routine.


High-level drawing routines
---------------------------


PROCmdLine(x1,y1, x2,y2)
------------------------

Draws a straight line from (x1,y1) to (x2,y2).

For example:

  PROCmdLine(0,0, 100,200)

This routine is simply a more convenient way to create a path with a single
line segment.  The example above is equivalent to 

  PROCmdStartPath(0,0)
  PROCmdLineTo(100,200)
  PROCmdEndPath


PROCmdRectangle(x,y, xsize,ysize, alpha)
----------------------------------------

Creates a closed path consisting of four straight lines to form a rectangle.
The lower left-hand corner will be at (x,y), and the width and height are
determined by xsize and ysize respectively.

The third parameter, alpha, specifies the angle (in radians) by which the
rectangle will be rotated from the horizontal: this should be zero if you
want the rectangle to be "straight".

For example, the following code fragment will draw twelve rectangles around
a central point:

  FOR alpha = 0 TO 2*PI-PI/6 STEP PI/6
    PROCmdRectangle(4,4, 2,1, alpha)
  NEXT alpha


PROCmdCircle(x,y, r)
--------------------

Draws a circle with centre at (x,y) and radius r.

For example:

  PROCmdCircle(100,200, 50)

This routine creates circles in exactly the same way as !Draw does - as a
closed path consisting of four curves with control points specially set to
form a circle.                                                  

PROCmdCircle actually calls PROCmdEllipse to do the work: it is provided as
a more convenient way of creating circles.  Exactly the same circle as in
the example above could be created with

  PROCmdEllipse(100,200, 50,0, 0)

                                 
PROCmdEllipse(x,y, r1,r2, alpha)
--------------------------------------

Draws an ellipse with center at (x,y).  The "radius" in one direction is r1,
and the "radius" in the other direction is r2.  In other words the length of
the ellipse is 2*r1 and the width is 2*r2 (although of course the width can
actually be greater than the length).  The whole ellipse is tilted at an
angle of alpha radians to the horizontal.

For example:

  PROCmdEllipse(100,200, 50,100, RAD(45))
                   

Low-level drawing routines
--------------------------


PROCmdStartPath(x,y)
--------------------

This must be called to define the beginning of a path which will be
completed by calls to PROCmdLineTo, PROCmdCurveTo, PROCmdAutoCurveTo,
PROCmdMoveTo, and PROCmdEndPath.  The "current position" is set to (x,y).

For example:

  PROCmdStartPath(0.5, 1.0)


PROCmdMoveTo(x,y)
-----------------

Creates an "invisible" segment in the current path from the current position
to (x,y).

For example:
                           
  PROCmdMoveTo(2.2, 1.0)

Moving allows a single path to include more than one line.  For example, a
rectangle with two holes in it can be created as follows (see example
programme "Moving").  Note how PROCmdClosePath can be used more than once
within a single path.

  PROCmdStartPath(1,4)
  PROCmdLineTo(1,1)                :REM Draw outer box
  PROCmdLineTo(6,1)
  PROCmdLineTo(6,4)
  PROCmdLineTo(1,4)
  PROCmdClosePath                  :REM Complete the outer box 
  PROCmdMoveTo(2,3)                :REM Move to a new position 
  PROCmdLineTo(2,2)                :REM Start the first inner box
  PROCmdLineTo(3,2)
  PROCmdLineTo(3,3)
  PROCmdLineTo(2,3)
  PROCmdClosePath                  :REM Complete it
  PROCmdMoveTo(4,3)                :REM Move to a new position
  PROCmdLineTo(5,3)                :REM Start the second inner box
  PROCmdLineTo(5,2)
  PROCmdLineTo(4,2)
  PROCmdLineTo(4,3)                :REM Complete it
  PROCmdClosePath
  PROCmdEndPath


PROCmdLineTo(x,y)
-----------------                                                        

Creates a straight line segment in the current path from the current
position to (x,y).

For example:

  PROCmdStartPath(0,0)
  PROCmdLineTo(2.2, 3.5)
  PROCmdEndPath


PROCmdCurveTo(x,y, xcp1,ycp1, xcp2, ycp2)
-----------------------------------------

Creates a curved line segment in the current path from the current position
to (x,y).  The control point for the beginning of the line is placed at
(xcp1,ycp1), and the control point for the end of the line at (xcp2,ycp2).
See the section "How curves work" in the chapter on !Draw for an explanation
of control points.

For example:
                          
  PROCmdStartPath(0,0)
  PROCmdCurveTo(4,5, 3,1, 5,4)
  PROCmdEndPath


PROCmdAutoCurveTo(x,y, drawflag%)
---------------------------------

Like PROCmdCurveTo, this procedure creates a curved line segment from the
current position to (x,y), but the positions of the control points are
calculated automatically to ensure that the joins between adjacent line
segments are smooth.
            
This works in the same way as entering a curved path in !Draw.

The line segment will only be drawn if drawflag% is TRUE.  Setting drawflag%
to FALSE is a bit like using PROCmdMoveTo, except that the control points
are positioned as though the line segment were drawn.  This allows you to
create smooth curves with breaks in them, which is something that cannot be
done easily in !Draw.

The following example demostrates the use of PROCmdAutoCurveTo and the
differnce between PROCmdAutoCurveTo(x,y, FALSE) and PROCmdMoveTo(x,y).  (See
example programme "AutoCurve").
                              
  REM Draw smooth curves with one segment missing:
  PROCmdStartPath(1,1)
  PROCmdAutoCurveTo(2,3, TRUE)
  PROCmdAutoCurveTo(3,1, TRUE)
  PROCmdAutoCurveTo(4,3, FALSE)
  PROCmdAutoCurveTo(5,1, TRUE)
  PROCmdEndPath
  PROCmdStartPath(1,3)
  PROCmdAutoCurveTo(2,5, TRUE)
  PROCmdAutoCurveTo(3,3, TRUE)
  PROCmdMoveTo(4,5)
  PROCmdAutoCurveTo(5,3, TRUE)
  PROCmdEndPath

Paths can include both straight and curved lines.  PROCmdAutoCurve smooths
the joins between straight and curved lines, as well as the final join in
closed paths (see PROCmdClosePath).

It is possible to mix the use of PROCmdCurve (where you calculate the
positions of the control points) and PROCmdAutoCurve, but the join between
the two types of line will be smoothed as though the "non-auto" curve were a
straight line.  This is unlikely to be a problem in practice, as you will
probably want to calculate the control points for all curves if you do for
any of them.


PROCmdClosePath
---------------

Joins the current position to the start position of the current path to
create a closed loop.

For example:
                       
  REM Draw a triangle:
  PROCmdStartPath(100,100)
  PROCmdLineTo(200,100)
  PROCmdLineTo(200,200)
  PROCmdLineTo(100,100)
  PROCmdClosePath
  PROCmdEndPath 

If the first and/or last line segments in the section of the path being
closed were defined with PROCmdAutoCurveTo, the final join will be smoothed
as though it were in the middle of the path.

Sections of paths that contain moves (defined with PROCmdMoveTo or
PROCmdAutoCurveTo(x,y, FALSE)) behave like separate paths when it comes to
closing the path - the closure goes back to the first point in the current
continuous section of the path.  This is a feature of the way the draw
module itself renders the line.  For example, the following code (see
example programme "ClosePath") creates four separate curved shapes within a
single path:

  PROCmdStartPath(2,3)
  PROCmdAutoCurveTo(2,4, TRUE)
  PROCmdAutoCurveTo(1,4, TRUE)
  PROCmdAutoCurveTo(1,3, TRUE)
  PROCmdAutoCurveTo(2,3, TRUE)
  PROCmdClosePath
  PROCmdMoveTo(3,3)
  PROCmdAutoCurveTo(3,4, TRUE)
  PROCmdAutoCurveTo(4,4, TRUE)
  PROCmdAutoCurveTo(4,3, TRUE)
  PROCmdAutoCurveTo(3,3, TRUE)
  PROCmdClosePath
  PROCmdMoveTo(3,2)
  PROCmdAutoCurveTo(3,1, TRUE)
  PROCmdAutoCurveTo(4,1, TRUE)
  PROCmdAutoCurveTo(4,2, TRUE)
  PROCmdAutoCurveTo(3,2, TRUE)
  PROCmdClosePath
  PROCmdMoveTo(2,2)
  PROCmdAutoCurveTo(2,1, TRUE)
  PROCmdAutoCurveTo(1,1, TRUE)
  PROCmdAutoCurveTo(1,2, TRUE)
  PROCmdAutoCurveTo(2,2, TRUE)
  PROCmdClosePath
  PROCmdEndPath

Note that all three sides of the triangle in the first example above are
drawn before the path is closed: this is how !Draw expects a closed path to
be created.  It is possible to close a path without explicitly creating the
final line segment and the draw module will display the path as expected,
but strange things will happen if you then try to edit the path within
!Draw.  The results will be even more strange if you are using
PROCmdAutoCurveTo, as MakeDraw will calculate the control points as though
the path had been closed properly.

For example:

  REM Another way to draw a triangle - NOT RECOMMENDED!
  PROCmdStartPath(100,100)
  PROCmdLineTo(200,100)
  PROCmdLineTo(200,200)
  PROCmdClosePath          :REM creates the final segment "implicitly"
  PROCmdEndPath
                                                                      

PROCmdEndPath
-------------

Completes the current path.  This procedure must be used when all the line
segments have been defined, and before another path (or any other type of object)
is started.

For example:

  PROCmdStartPath(0,0)
  ...
  PROCmdEndPath


Text routines
-------------


PROCmdText(x,y, t$)
-------------------

Positions a text object at (x,y) using the current text style and colour.
The coordinates define the position of the left-hand end of the base line of
the text - any descenders will extend below this position.     

The text should not contain any control characters: if it does an error will
occur when trying to load the draw file into !Draw.

For example:

  PROCmdText(100,200, "This text is at (100,200)")


Grouping routines
-----------------


PROCmdStartGroup
----------------
               
When using !Draw, objects are created first and then grouped together if
required.  With MakeDraw, you have to plan ahead a little bit and decide
where a group will start and end.  PROCmdStartGroup is used to indicate that
all the following objects, until the corresponding PROCmdEndGroup, should be
grouped together.

Groups can be nested to a maximum of 64 levels.  All groups should be
explicitly closed before the diagram is completed (if they are not, they
will be closed for you, and a warning will be issued).

In the following example, group 2 contains a rectangle and two diagonal
lines, and group 1 contains a circle and group 2:

  PROCmdStartGroup                  : REM Start of group 1
  PROCmdCircle(250,250, 100)
  PROCmdStartGroup                  : REM Start of group 2
  PROCmdRectangle(0,0, 500,500, 0)
  PROCmdLine(0,0, 500,500)
  PROCmdLine(0,500, 500,0)
  PROCmdEndGroup                    : REM End of group 2
  PROCmdEndGroup                    : REM End of group 1


PROCmdEndGroup
--------------

Marks the end of a group that was started with PROCmdStartGroup.

See the description of PROCmdStartGroup for details and examples.
                 
 
Drawing option routines
-----------------------


PROCmdSetLineColour(red%,green%,blue%)
--------------------------------------

Sets the foreground colour to be used by later calls to line drawing
procedures (PROCmdLine etc.).  The setting remains in effect until another
call to PROCmdSetLineColour or until MakeDraw is reset by
PROCmdReinitialise.

See the section above on the use of colour for details of how to choose
values for red%, green%, and blue%.

The default line colour is black, i.e. (0,0,0).

For example:

  PROCmdSetLineColour(238,238,0): REM Standard desktop yellow
  PROCmdCircle(100,200, 50)

  
PROCmdSetLineStyle(join%, startcap%,endcap%, capwidth%,capheight%, dashed%)
---------------------------------------------------------------------------

Sets various line drawing options to be used by later calls to line drawing
procedures (PROCmdLine etc.).  The setting remains in effect until another
call to PROCmdSetLineStyle or until MakeDraw is reset by PROCmdReinitialise.
                       
The parameters have the following meanings:

  join% specifies how line segments are joined together:
            0 = mitred
            1 = rounded
            2 = bevelled
  The difference between these join styles is only noticable on fairly thick
  lines, and has no effect at all on thin lines.

  startcap% and endcap% specify the appearance of the beginning and ends of
  lines:
            0 = butted (no cap)
            1 = rounded
            2 = square
            3 = triangle (arrow head)
  The difference between these cap styles is only noticeable on fairly
  thick lines, and has no effect at all on thin lines.  The round, square,
  and triangular caps increase the length of the line.

  capwidth% and capheight% specify the size of the arrow head relative to 
  the line width as a number from 0 to 255; they are ignored for other cap
  styles.  A value of 16 corresponds to one line width; 8 equals half the
  width of the line; 32 would be twice the line width (in other words,
  multiply the value that you would specify in !Draw by 16).  The width
  setting actually refers to HALF the width of the arrow head, so specifying
  8 gives a triangle which is the same width as the line.  The default
  arrow shape used by !Draw has width 16 and height 32. 

  dashed% specifies whether the line should be continuous or dashed:
            0 = continuous (not dashed)
            1 = standard !Draw dash style 1
            2 = standard !Draw dash style 2
            3 = standard !Draw dash style 3
            4 = standard !Draw dash style 4
        other = pointer to user defined dash style - see below.

The default line style is mitred, butted, continuous, i.e. (0, 0,0, 0,0, 0).

For example:

  REM Draw a dashed line with a square start, an arrow at the end, and
  REM rounded corners:    
  PROCmdSetUnits(mdInch%)
  PROCmdSetLineWidth(0.25)
  PROCmdSetLineStyle(1, 1,3, 16,32, 1)
  PROCmdStartPath(1,1)
  PROCmdLineTo(4,1)
  PROCmdLineTo(4,5)
  PROCmdLineTo(1,5)
  PROCmdEndPath

!Draw provides four styles of dashed line, but the draw module itself can
cope with a much wider variety of dash styles.  With MakeDraw you can create
your own dash styles and !Draw will quite happily display them, but if you
try to edit the dash style within !Draw will treat it as an undashed line.

A dash style is defined by specifying the lengths (in draw units) of each
segment of the pattern.  For example, suppose you wanted a dashed line that
was "on" for half an inch, "off" for half an inch, then "on" for quarter of
an inch and "off" for quarter of an inch.  The pattern would look like  "--
- ", where each character represents a quarter of an inch, and the whole
pattern would repeat every one and a half inches.  The lengths you would
need to specify would be mdInch%/2, mdInch%/2, mdInch%/4, mdInch%/4.

The pattern can consist of as many "off" and "on" segments as you like.  The
first segment is always "on", the second "off", and so on, so it you would
usually have an even number of segments.  You can also specify the offset
(in draw units) into the pattern at which to start drawing.

The whole pattern is set up in a block of memory, with each value taking up
four bytes, and it is the address of this block that is passed as the
dashed% parameter of PROCmdSetLineStyle.  The pattern above could be
specified as follows:

  DIM dashpattern% 24          :REM = 8 + number_of_segments*4
  dashpattern%?0  = 0          :REM Offset - none required for this pattern
  dashpattern%?4  = 4          :REM The number of segments in the pattern
  dashpattern%?8  = mdInch%/2  :REM Length of the 1st ("on") segment
  dashpattern%?12 = mdInch%/2  :REM Length of the 2nd ("off") segment
  dashpattern%?16 = mdInch%/4  :REM Length of the 3rd ("on") segment
  dashpattern%?20 = mdInch%/4  :REM Length of the 4th ("off") segment      
  PROCmdSetLineStyle(1, 0,3, 16,32, dashpattern%)

Note that the offset and lengths must always be specified in draw units,
even if you have used PROCmdSetUnits to set your own units, because the
block of memory is passed directly to !Draw.

Example programme "LineStyle" also has examples of defining dash patterns.
  

PROCmdSetLineWidth(width)
-------------------------

Sets the width of line to be used by later calls to line drawing procedures
(PROCmdLine etc.).  The setting remains in effect until another call to
PROCmdSetLineWidth or until MakeDraw is reset by PROCmdReinitialise.

If width is zero, "thin" lines are drawn, otherwise the line width is set
according to the current units.

The default value is zero.

For example:

  REM Really chunky lines:
  PROCmdSetUnits(mdInch%)
  PROCmdSetLineWidth(1)
  PROCmdRectangle(3,1, 5,4, PI/3)
              

PROCmdSetFillColour(red%,green%,blue%)
--------------------------------------

Sets the fill colour to be used by later calls to line drawing procedures
(PROCmdLine etc.).  The setting remains in effect until another call to
PROCmdSetLineColour or until MakeDraw is reset by PROCmdReinitialise.

Shape filling must be turned on by PROCmdSetFillStyle for filling to occur.

If the path is not closed (by PROCmdClosePath), it will be filled as though
there were a straight line segment from the first point to the last.

See the section above on the use of colour for details of how to choose
values for red%, green%, and blue%.

The default fill colour is black, i.e. (0,0,0).

For example:

  PROCmdSetFillColour(255,187,0): REM Standard desktop orange
  PROCmdSetFillStyle(TRUE, 0)
  PROCmdCircle(100,200, 50)


PROCmdSetFillStyle(fillflag%, windingrule%)
-------------------------------------------

Sets the shape filling options for use by later calls to line drawing
procedures.  These settings remain in effect until another call to
PROCmdSetFillStyle or until MakeDraw is reset by PROCmdReinitialise.

The parameters have the following meanings:

  fillflag% determines whether (TRUE) or not (FALSE) shapes will be filled.

  windingrule% specifies the way complex objects are filled, as explained in
  the Archimedes User Guide:
            0 = non-zero winding
            1 = even-odd winding

The default is for objects not to be filled.

For example:

  PROCmdSetFillColour(255,0,0)
  PROCmdSetFillStyle(TRUE, 1)
  PROCmdStartPath(1,1)
  PROCmdLineTo(3,1)
  PROCmdLineTo(3,3)
  PROCmdLineTo(2,3)
  PROCmdLineTo(2,2)
  PROCmdLineTo(4,2)
  PROCmdLineTo(4,4)
  PROCmdLineTo(4,1)
  PROCmdLineTo(1,1)
  PROCmdClosePath
  PROCmdEndPath

Example programme "Moving" also demonstrates filling and the effect winding
rules.
                       

Text option routines
--------------------
 

PROCmdSetTextSize(width, height)
--------------------------------

Sets the character size to be used by later calls to PROCmdText.  The
setting remains in effect until another call to PROCmdSetTextSize or until
MakeDraw is reset by PROCmdReinitialise.

The width and height are always specified in points (1/72", or 640 draw
units), irrespective of the units defined by PROCmdSetUnits.         

The default values for width and height are 6.40 points and 12.80 points
respectively; text usually looks best if the characters are higher than they
are wide.

For example:

  PROCmdSetTextSize(36,72)
  PROCmdText(0,0, "THESE LETTERS ARE ONE INCH HIGH!")


PROCmdSetTextColour(red%,green%,blue%)
--------------------------------------

Sets the foreground colour to be used by later calls to PROCmdText.  The
setting remains in effect until another call to PROCmdSetTextColour or until
MakeDraw is reset by PROCmdReinitialise.

See the section above on the use of colour for details of how to choose
values for red%, green%, and blue%.

The default text colour is black, i.e. (0,0,0).

For example:

  PROCmdSetTextColour(221,0,0)
  PROCmdText(0,0, "This text is in the 'standard' desktop shade of red")


PROCmdSetTextStyle(fontid%, red%,green%,blue%)
----------------------------------------------

Sets the font and background colour to be used by later calls to PROCmdText.
The setting remains in effect until another call to PROCmdSetTextStyle or
until MakeDraw is reset by PROCmdReinitialise.
                                                                       
fontid% must be either zero (to use the system font) or a value returned by
FNmdDefineFont to select an anti-aliased font.
                                             
The background colour, defined by red%, green%, and blue%, is only relevant
for anti-aliased fonts: it should normally be set to the colour of the
background that will be behind the text, although interesting effects can be
created if another colour is used.  See the section above on the use of
colour for details of how to choose values for red%, green%, and blue%.

The default setting for text style is system font, white background, i.e.
(0, 255,255,255).
                             
For example (see example programme "TextStyle"):
                                    
  PROCmdSetUnits(mdInch%)
  font1% = FNmdDefineFont("Trinity.Medium")
  font2% = FNmdDefineFont("Corpus.Medium")
  PROCmdSetTextSize(20,20)

  PROCmdSetTextColour(0,0,0)
  PROCmdSetTextStyle(0, 255,255,255)                       
  PROCmdText(1,1, "System font, black on white")
  
  PROCmdSetFillColour(0,0,0)       : REM Draw black rectangle
  PROCmdSetFillStyle(TRUE, 0)
  PROCmdRectangle(1,2, 6,1, 0)                    
  PROCmdSetTextColour(255,255,255)
  PROCmdSetTextStyle(font1%, 0,0,0)
  PROCmdText(1,2.5, "Trinity.Medium, white on black")
  
  PROCmdSetTextColour(0,255,0)
  PROCmdSetTextStyle(font2%, 0,0,255)
  PROCmdText(1,4, "Corpus.Medium, green on white with blue edges")


FNmdDefineFont(fontname$)
-------------------------

This function defines an anti-aliased font so that it can be selected later
by a call to PROCmdSetTextStyle.  The value returned must be saved and used
as the font identifier for the font.

No checking is done to ensure that fontname$ is a valid font name.  If !Draw
finds that the font specified is not available for any reason when the
diagram is displayed, it will use the system font instead.

All fonts that will be used in the diagram must be defined immediately after
the call to PROCmdInitialise or PROCmdReinitialise, i.e. before calls to any
routines that create objects or groups.

For example,

  f1% = FNmdDefineFont("Portrhouse.Standard")

A fuller example is given in the description of PROCmdSetTextStyle.

                               
Coordinate system routines
--------------------------          

See the section above on the !Draw coordinate system for more information on
units and the origin.


PROCmdSetUnits(drawunits%)
--------------------------

Specifies the unit of measure to be used by subsequent calls to MakeDraw
routines (PROCmdSetTextSize is an exception - it always takes values
expressed in points (1/72")).  The setting remains in effect until another
call to PROCmdSetUnits or until MakeDraw is reset by PROCmdReinitialise.

The value passed to PROCmdSetUnits is the number of draw units to be
considered as one "user" unit.  So if you want to work in inches, you would
use

  PROCmdSetUnits(mdInch%)

 
PROCmdSetOrigin(x,y)
--------------------

Sets the position of the origin from which subsequent coordinates will be
measured.

The x,y coordinates are specified in the current units and are always
absolute - i.e. they are not affected by previous calls to PROCmdSetOrigin.

The setting remains in effect until another call to PROCmdSetOrigin or until
MakeDraw is reset by PROCmdReinitialise.

The default origin is at (0,0).

For example:

  REM Place the origin at the centre of a piece of A4 paper:
  PROCmdSetUnits(mdMM%)
  PROCmdSetOrigin(210/2, 297/2)


Diagnostic routines
-------------------
                                                    

PROCmdHelp
----------

Prints the MakeDraw version number and copyright notice, and a list of all
the MakeDraw routines and their parameters.

It is designed to provided a quick "on-line" reminder of the syntax for
calling MakeDraw routines.


PROCmdTrace
-----------

Turns on the MakeDraw tracing facility.  This produces output showing the
routines being called and the parameters passed to them.  Tracing continues
until turned off by PROCmdNoTrace; the tracing status is not reset by
PROCmdReinitialise.

PROCmdTrace can be called at any time, but there is no point in calling it
before PROCmdInitialise, as this routine sets the tracing status to off.

The trace output for many routines includes the calls that are automatically
made to other routines.

For example,                                     

  PROCmdTrace
  PROCmdRectangle(0,0, 100,200, 0)
  PROCmdNoTrace

would produce screen output as follows:

  <Trace><Rectangle(0,0,100,200,0)><StartPath(0,0)><MoveTo(0,0)>
  <LineTo(100,0)><LineTo(100,200)><LineTo(0,200)><LineTo(0,0)><ClosePath>
  <EndPath><NoTrace>
 

PROCmdNoTrace
-------------

Turns tracing off.  See the description of PROCmdTrace for further details.

PROCmdNoTrace can be called at any time.


PROCmdDiagramInfo(RETURN start%,RETURN length%)
-----------------------------------------------

This routine is provided to supply information about the diagram being
created.  It sets start% to the address of the buffer containing the
diagram, and length% to the number of bytes of the buffer that have been
used so far.  It can be called at any time after PROCmdInitialise, but is
only really useful when the diagram is complete - just before you call
PROCmdSaveDiagram.

For example, 

  PROCmdDiagramInfo(s%, l%)
  PRINT "Buffer is at &";~s%;", size of diagram is ";l%

might produce as output:

  Buffer is at &10E30, size of diagram is 864

This information is useful if you want to check that there is sufficient
space on a disk to save the diagram, or if you want to use your own method
of saving the diagram (such as a RISC OS-compatible method).


Filing routines
---------------


PROCmdSaveDiagram(filename$)
----------------------------
            
Saves the current diagram in file filename$, which must be a valid file
name.  No checking is done on this parameter, and the *save command is used
to save the buffer as a file, so the same errors may occur as if your own
program had issued a *save command, such as "Not found" or "Disk full".  The
file is given file type AFF (Draw file).

You can use PROCmdDiagramInfo to determine the current size of the diagram
(which will be the same as the file size) to make sure that there is room on
the disk (or other filing medium) to save the file.

For example,

  PROCmdSaveDiagram(":0.Etchings.Mastrpiece")

               

[End of MakeDraw documentation]
