render.c
--------

History
-------
26th October 1992  J R C  Started

   All the functions to do the work of rendering a draw file are in this
souece file, with the exception of the text area stuff, which is large
enough to need its own file.

   The calls to this file are made via the |callback_| module, and this is
how the substitution of system text for scalable text is made when the
scalable text fails in some way: the functions |render_(transformed_)?text|
return FALSE if any of their Font Manager calls returns an error: this
results in a call to |render_(transformed_)?text_system|.

   The module has one data structure: a |State| to be psssed to each
rendering function. This contains an object pointer, the diagram pointer
(used only for calculating object offsets in error messages), the font table
pointer (when known), an error pointer (not used really), the flags the SWI
was invoked with, and the transformation and clip rectangle to be used.

   The main entry point, invoked by the SWI handler in |main_swi| is
|render|. This calculates the clipping rectangle in draw file coordinates
for use in source-level clipping, initialiseds the |State| structure, and
then makes calbacks for all the top-level objects.

   The rendering functions are: |render_font_table| (which just saves the
font table pointer into the global state structure),
|render_text(_system)?|, |render_path|, |render_sprite|, |render_group|
(which uses the same callback list to proess all the members of the group,
after checking that the bounding box overlaps the clip region),
|render_tagged| (which renders the enclosed object), |render_text_area|
(which calls |textarea_render|), |render_trfm_text(_system)?| and
|render_trfm_sprite|.

   There are also three support functions: |Sprite| renders a sprite through
a transformation, using |colourtrans_select_table| and |osspriteop_put_-
sprite_trfm|; Text_System does the same for system-font text; |Bbox| renders
a bounding box (as a red dotted rectangle). It is used if the bit
DrawFile_RenderBboxes is set on the SWI call.

Future development
------ -----------
   It would be a major leap forward in the usability of this module if the
interface included a way of registering rendering functions with it. The
best to do this would be to export the callback data structure, and to allow
applications to copy it into their own address space, modify it, and then
use the DrawFile module with the new callback list. This would allow an
application to supply its own code for rendering a certain object type, even
if that was a composite object possibly consisting both of objects defined
in the application and of objects already known to the DrawFile module. It
would also allow an application to replace DrawFile code, if it wanted to
display an object in a different way.

   In this way, Draw would also be able to use the module: the major
problems here are

         the fact that Draw has to render bounding boxes only for those
      objects which comprise the current selection; and
  
         the fact that during editing of a path, the default appearance is
      replaced by an outline that drags in a "rubber band" style under null
      events.

   The first problem would be solved by replacing all of the rendering
functions with ones that draw the bounding box if necessary, then call the
original function as well; the second by replacing the path-rendering
function with one that either calls the original (for paths other than the
selected one), or else does nothing; and then having a function that
cooperates with Wimp_UpdateWindow to paint the rubber-band path in whatever
style is required.

   All this requires that the DrawFile module can call back to user-supplied
functionsd; this implies that it runs in user mode itself. I think it is an
important part of the architecture of the Toolbox that we explore this
alternative soon. There are two possible approaches:

         DrawFile can be a module, as at present, but one that drops into
      user mode when it is called. This can be done by setting up a RISC O S
      callback handler remembering the contents of the previous callback
      handler, the SWI number called and the workspace pointer, calling 
      OS_SetCallback to set the callback flag, and returning from the SWI
      with V clear and all other registers preserved. It means that its
      SWI's can only be called from user mode with a flat SVC stack and
      interrupts enabled, which is probably not a problem; or

         we can adopt A P C S 3, which has provision for a static data
      pointer to be passed into called functions, and therefore allows "true
      sharable libraries." This approach would be better in the long term,
      since the call time is much shorter - it's a BL rather than a SWI, so
      never goes into supervisor mode at all.
