DEFINITION MODULE GKS;

(*
    Title: 	Graphical Kernel System Interface
    LastEdit:	"Tue Feb 26 15:04:46 1985"
    Author: 	jd
		Cambridge University Computer Laboratory
*)

FROM SYSTEM IMPORT WORD;

FROM Vector IMPORT RVEC, RBOX;

FROM GKSTypes IMPORT
    WS, ERRORPROC, RBOXPOINTER, TRANSFORM, SEGMENT,
    ATTRTYPE, ATTRIBUTE, GDPCODE, ESCAPECODE,
    PATH, PRECISION, LINESTYLE, MARKERSTYLE, FILLSTYLE;


EXPORT QUALIFIED
    OpenGKS, CloseGKS,

    Line, PolyLine, Marker, PolyMarker, Text, Fill, Pixels, Gdp, 

    SetPolyLineIndex, SetPolyLine,
    SetPolyMarkerIndex, SetPolyMarker,
    SetTextIndex, SetText,
    SetFillAreaIndex, SetFillArea, SetPattern,
    SetCharHeight, SetCharUpVector, SetCharExpand,
    SetCharPath, SetCharSpacing,
    SetPatternSize, SetPatternReferencePoint,
    SetColour,

    SelectNormalization, SetWindow, SetViewport,
    GetNormalizationIndex, GetNormalization, SetClipping,

    OpenWS, CloseWS, ActivateWS, DeactivateWS, ClearWS, UpdateWS, 
    SetDeferralState, Message, Escape, SetWSWindow, SetWSViewport,
    GetWSTransformation, GetWSDisplaySurface,

    GetActiveWS;

(* This interface describes an implementation of GKS, the Graphical Kernel
   System, which is a draft ISO standard graphics package proposed by the
   Rutherford Appleton Laboratories. The most recent definition is by
   F.R.A. Hopgood, "GKS-The First Graphics Standard", RL-82-007, Rutherford
   Appleton Laboratory, Chilton, Didcot, Oxon OX11 0QX, of which a copy is
   to be found in the Computer Laboratory library. This is the definition
   from which this implementation was written, and is the definitive 
   documentation for it. As this document is not exactly light reading, a
   tutorial in ten words or less is given here for those who just want to 
   draw pictures.
   
   GKS controls a number of "workstations", several of which may be open and
   active at any one time. In this implementation, output only is supported, 
   since input seems needlessly baroque, and is best done independently of
   GKS. Currently, up to two workstations may be open simultaneously, and
   if two are open, one of them must be a metafile output workstation. This
   means that it is possible to draw on one workstation and record the 
   picture in a file at the same time. The restriction to one "real"
   workstation will be removed when improvements in the Modula-2
   implementation permit. 

   There are six drawing primitives. PolyLine draws a line connecting a
   sequence of points. PolyMarker draws precisely positioned marks such as are
   needed in plotting graphs. Text draws characters according to a whole raft
   of user-defined parameters. Fill does area filling and Pixels allows the
   display of arbitrarily patterned areas. Gdp is a "Generalized Drawing
   Primitive", an escape to allow workstation-specific graphical functions to
   be implemented.

   Whenever a primitive is called, all workstations which are active are
   told to draw it. It may appear differently on the different workstations,
   because each workstation has its own set of "pens" which describe exactly
   how the primitives are to be drawn. Globally, the user selects e.g. line
   pen 6; this tells each workstation to use its own definition of what a 
   line of type 6 is to look like. There are, however, some global attibutes
   which determine how all workstations are to show some object. These are
   principally concerned with accurate placing of characters.

   GKS has an unusual way of handling transformations. There is a
   normalization transformation, which can be changed at will, which is first
   applied to user coordinates to transform them into "Normalized Device
   Coordinates" (NDC), a space in which only the unit box is potentially
   visible. NDC should be thought of as an abstract space in which the picture
   to be displayed is composed. Each workstation then shows a part of the NDC
   unit box on its viewing surface as defined by its workstation 
   transformation, so different workstations can be simultaneously displaying
   different parts of the same picture. Initially, the normalization 
   transformation is the identity function, and each workstation displays the
   unit box in NDC, mapping it onto the largest possible square area of
   its display surface.

   GKS also defines a stored picture representation in terms of segments. This
   is not currently implemented, but could be quite easily if someone can
   convince me that it is really useful.

   In the following, comments marked "Nonstandard" indicate those functions
   which do not behave exactly as the standard dictates, usually in the 
   interests of convenience.

*)


PROCEDURE OpenGKS (p: ERRORPROC);
    (* NonStandard: no call needed unless error procedure is to be changed -
       there is an implicit call at the start of day.
    *)

PROCEDURE CloseGKS ();
    (* NonStandard: closes all workstations as necessary *)

PROCEDURE OpenWS (type, instance: ARRAY OF CHAR): WS;
    (* The valid arguments are:
       type        instance                      meaning

       GKSM        filetitile       open an output metafile workstation to
                                    record picture changes in the named file
       anything       not           open the "real" workstation whose type
       else        significant      was determined when the program was linked
       
       Beware: a newly opened workstation will not draw any pictures until
       it is activated!
    *)

PROCEDURE CloseWS (ws: WS);
    (* NonStandard: the WS need not be inactive *)

PROCEDURE ActivateWS (ws: WS);
    (* the workstation will take note of all future picture changes *)

PROCEDURE DeactivateWS (ws: WS);
    (* the workstation will ignore future picture changes *)

PROCEDURE ClearWS (ws: WS; obligatory: BOOLEAN);
    (* clear the viewing surface; if NOT obligatory, then the ws can ignore
       if it believes the surface to be already clear
    *)

PROCEDURE UpdateWS (ws: WS);
    (* ensure that it has taken account of the most recent picture change *)

PROCEDURE SetDeferralState (ws: WS; AllowUpdateDeferral,
    AllowImplicitRedraw: BOOLEAN);
    (* IF AllowUpdateDeferral, then the ws is permitted to delay showing
       picture changes in the interests of efficiency. IF AllowImplicitRedraw,
       then GKS will clear and redraw the ws on some stored picture changes.
       Nonstandard: when a ws is opened, it sets sensible values for these
       parameters automatically.
    *)

PROCEDURE Message (ws: WS; s: ARRAY OF CHAR);
    (* Display the characters in a convenient place on the viewing surface *)

PROCEDURE Escape (ws: WS; function: ESCAPECODE; VAR w: WORD; 
        VAR a: ARRAY OF WORD);
    (* a non-graphical escape function used to control peculiar device
       characteristics
    *)

PROCEDURE SetWSWindow (ws: WS; r: RBOX);
    (* defines the box in NDC which is to be visible. This will be
       displayed in the largest box of the same aspect ratio which
       fits inside the current workstation viewport.
    *)

PROCEDURE SetWSViewport (ws: WS; r: RBOX);
    (* defines the box in metres which is to be used as the drawing
       surface. Not all of this box may be usable since
       a) it may be bigger than the device's physical viewing surface.
       b) the workstation is constrained to draw in a box of the
          same aspect ratio as its workstation window; the largest such
          box will be chosen.
    *)

PROCEDURE GetWSTransformation (ws: WS; VAR window, viewport: RBOX);
    (* returns the values last set for the workstation *)

PROCEDURE GetWSDisplaySurface (ws: WS; VAR r: RBOX);
    (* the physical device limits in meters *)

PROCEDURE PolyLine (count: INTEGER; points: ARRAY OF RVEC);
    (* connect the first count points with a line in the current style *)

PROCEDURE Line (from, to: RVEC);
    (* the simple case of PolyLine *)

PROCEDURE PolyMarker (count: INTEGER; points: ARRAY OF RVEC);
    (* draw marks of the current type at the first count points *)

PROCEDURE Marker (at: RVEC);
    (* the simple case of PolyMarker *)

PROCEDURE Text (at: RVEC; text: ARRAY OF CHAR);
    (* write text in current style at given point *)

PROCEDURE Fill (count: INTEGER; points: ARRAY OF RVEC);
    (* fill an area defined by the first count points in the current style *)

PROCEDURE Pixels (in: RBOX; rows, columns: INTEGER;
    pixels: ARRAY OF CARDINAL);
    (* fill a box with pixels of colour given by entries of the array
       which is stored by row, then by column within row
    *)

PROCEDURE Gdp (function: GDPCODE; data: WORD; count: INTEGER;
    points: ARRAY OF RVEC);
    (* generalized drawing primitive for any other kinds of graphical
       operations which you can think of
    *)

PROCEDURE SelectNormalization (index: CARDINAL);
    (* make a normalization transformation current *)

PROCEDURE SetWindow (index: CARDINAL; r: RBOX);
    (* set a window (in arbitrary real coordinates) for a normalization
       transformation
    *)

PROCEDURE GetNormalizationIndex (): CARDINAL;
    (* returns the currently selected normalization index *)

PROCEDURE GetNormalization (index: CARDINAL; VAR window, viewport: RBOX);
    (* returns the window and viewport of the specified transformation *)

PROCEDURE SetViewport (index: CARDINAL; r: RBOX);
    (* set a viewport (in NDC) for a normalization transformation. Only the
       part contained within the unit box will be visible on any 
       workstation
    *)

PROCEDURE SetClipping (on: BOOLEAN);
    (* default FALSE. If true, then the normalization transformation defines
       not only a geometric transformation, but also a clipping box for
       all graphical primitives
    *)

PROCEDURE SetPolyLineIndex (index: CARDINAL);
    (* select current line "pen" number *)

PROCEDURE SetPolyMarkerIndex (index: CARDINAL);
    (* select current marker "pen" number *)

PROCEDURE SetTextIndex (index: CARDINAL);
    (* select current text "pen" number *)

PROCEDURE SetFillAreaIndex (index: CARDINAL);
    (* select current fill area "pen" number *)

PROCEDURE SetPolyLine (ws: WS; index, style, colour: CARDINAL; width: REAL);
    (* define a line pen number for a workstation *)

PROCEDURE SetPolyMarker (ws: WS; index, style, colour: CARDINAL; size: REAL);
    (* define a marker pen number for a workstation *)

PROCEDURE SetText (ws: WS; index, font, colour: CARDINAL;
    precision: PRECISION);
    (* define a text pen number for a workstation *)

PROCEDURE SetFillArea (ws: WS; index, style, pattern, colour: CARDINAL);
    (* define a fill area pen number for a workstation *)

PROCEDURE SetPattern (ws: WS; index: CARDINAL; rowhigh, columnhigh: INTEGER;
    pattern: ARRAY OF CARDINAL);
    (* define a fill area style number for a workstation *)

PROCEDURE SetColour (ws: WS; index: CARDINAL; red, green, blue: REAL);
    (* define a colour pen number for a workstation *)

PROCEDURE SetCharHeight (h: REAL);
    (* set current character height in world coordinates. Initially .01,
       so that 100 rows of text will appear in the default window (!)
    *)

PROCEDURE SetCharUpVector (v: RVEC);
    (* define vertical direction of character - magnitude unimportant *)

PROCEDURE SetCharExpand (e: REAL);
    (* define a modification of the font width/height ratio as determined
       by the selected font. Initially 1, meaning no modification
    *)

PROCEDURE SetCharPath (d: PATH);
    (* set the direction of writing relative to the vertical character
       direction. Default RIGHT.
    *)

PROCEDURE SetCharSpacing (s: REAL);
    (* Adjust the amount of white space between characters. 
       NonStandard: this is given as a fraction of the desired character
       size, not as a fraction of the nominal font height. Thus spacing of
       1.0 means leave enough space between characters to allow insertion
       of one whole character between them. Default 0.0, meaning that 
       characters abut in the direction of writing.
    *)

PROCEDURE SetPatternSize (sx, sy: REAL);
    (* define size of fill area pattern to be used when filling with a
       user-defined pattern
    *)

PROCEDURE SetPatternReferencePoint (p: RVEC);
    (* define origin for replication of patterns when area filling with
       a user-defined pattern
    *)

PROCEDURE GetActiveWS (VAR a: ARRAY OF WS; VAR c: INTEGER);
(*  returns the set of active workstations in a[0], a[1], ... a[c-1]
    with the total number of active stations returned in c		  *)


END GKS.
