Image File Render
=================

Introduction
------------

A number of graphics formats are supported natively by RISC OS. JPEG,
DrawFiles and Sprites are directly renderable, and PNGs are supported
through a number of conversion calls. Each of these formats, however, is
rendered using slightly different calls. The ImageFileRender module
simplifies rendering these (and potentially other third party) image files.


Overview
--------

All graphics formats have two things in common :
  1. They cover a region (even empty files must say what space they cover).
  2. They have a resolution at which they are drawn.

The region they cover is known as the 'bounding box'. For many graphics
formats, this will be aligned with the origin - for example a bitmap
graphic. For others, this bounding box may be elsewhere in the image - for
example vector formats such as DrawFiles.

The resolution at which they have been drawn describes how accurate the
images is stored. Usually this is stored in 'dots per inch' (DPI) along
with the image itself. Screen resolution is usually - this depends on the
eigenfactors for the screen mode in use - treated as 90 DPI. Some formats
may use much more accurate internal representations than this; for example
DrawFile's are stored at 2048 DPI.

For the purposes of rendering the image file, we ignore the colour depth
because the rendering process will generate its results in the most accurate
manner possible for output depth.

Images may be rendered using a number of transformation types, allowing them
to be rendered to fit a region, to a scale, or using a more general
transformation.

Within each image file there may be a number of individual images. These
can be accessed by a sequence number which indicates their logical location
within the file. The images may be related - as would be the case with
frames of an animation - or they may be unrelated - as would be the case
with a collection of resources.

When accessing images, additional information may be provided to the
renderer which may perform specific operation on the image. This extra
data is specific to the renderer and cannot be handled generically.



Technical details
-----------------

 Sequence numbers
 ----------------

Graphics files may contain multiple logical images which may either be
frames of an animation, alternate versions, or other image resources.
These images are accessed through a sequence number which must be supplied
to all images. A sequence number of 0 will render the 'default' image
within the file. This may be the first image in some formats, the last
in others, or some arbitrary image. A sequence number higher than that of
the last image should be treated as the last image. A sequence number of
1 indicates the first image should be processed.


 Rendering quality
 -----------------

Image files may contain data which is more accurate than can be represented
by the display. This is usually the case for bitmap images at high colour
depths and almost always the case for bitmap images. In order to allow some
control over the quality of the rendered image (and usually the rendering
speed) a 'quality' parameter can be provided to the renderer. This is a
value from 1 to a renderer specific limit (with a maximum of 15) and will
be bounded to the maximum that the renderer supports. Thus, if the highest
quality is required, a value of 15 should be supplied. If the lowest quality
is required, a value of 1 should be supplied. In the majority of cases,
however, the 'default' will be required. This is a value which the renderer
feels is suitable for most operations and does not require excessive
processing to complete. To request the default quality, a value of 0 should
be specified as the quality.


 Transformation types
 ---------------------

Graphics files may be transformed in a number of ways. This allows us to
provide a simpler interface for rendering based on the requirements of the
application. At present, there are three transformation types provided by
the module :

   0 : Render to fit
   1 : Render scaled
   2 : Render transformed

For all rendering types an x and y origin are supplied from which all
operations will be based. This allows the same details to be used for
the fit, scale or transform regardless of the images location on the
screen.


  Render to fit
  -------------

When rendering to fit, a width and height must be supplied by the
application. The image file will be scaled to fit within this region.
In addition, a border and angle may be provided to specify an area
around the image which should be left clear, and to specify the angle
through which the image should be rotated.

The fit block has the following structure :
  +0  width
  +4  height
  +8  border (to apply to all edges)
  +12 angle

width, height and border are in OS units.
angle is in degrees, as a 16.16 fixed point value.

  Render scaled
  -------------

When rendering scaled, a pair of multiplication and division factors
should be supplied which describe the scale at which the image should
be rendered. The scale block is a standard RISC OS scale block (as used
by SpriteExtend)

The scaling block has the following structure :
  +0  x multiplication factor
  +4  y multiplication factor
  +8  x division factor
  +12 y division factor

  
  Render transformed
  ------------------

Rendering images through a transformation matrix is the most flexible
method of rendering that the ImageFileRender module provides. Transformation
matrices are provided in standard RISC OS tranformation blocks (as used by
SpriteExtend, Draw, DrawFile and others).

The transformation has the following structure :
  +0  m00
  +4  m10
  +8  m01
  +12 m11
  +16 m20
  +20 m21
  
where the matrix is constructed :
  { m00, m01, 0 }
  { m10, m11, 0 }
  { m20, m21, 1 }

m00, m01, m10, and m11 are 16.16 fixed point values.
m20 and m21 are 24.8 fixed point values.


 Arbitrary transformations
 -------------------------

Not all image formats support arbitrary transformations. Because of this,
certain formats will be unable to render when a complex transformation is
in use. A typical example of such limitations is that of JPEGs. The internal
renderer can only render JPEGs as a scaled object. If rotation, or other
complex transformations are applied to files which are not capable of those
transformations, an error will be returned.


 Clipping
 --------

All images will be clipped to the standard graphics rectangles. If an image
must not pass outside a region, a graphics window should be used. This can
be set through a VDU 24 sequence.


 Image file origins
 ------------------

Whilst most images are based at the origin, some images will have a bounding
box which are not. When the image is rendered 'to fit', the image origin
is implicitly ignored. When scaling and transforming however, the origin is
maintained and will be scaled with the image itself. Because this can make
manipulating such images more complex, this origin offset can be negated
by the ImageFileRender module. In this mode, the image can be treated as if
it does not have any offset from the origin.


 Colour mapping
 --------------

In order to provide highlighting and other colour manipulation on the image,
the ImageFileRender module can use colour mapping functions (as used by
SpriteExtend, DrawFile, and ColourTrans). These allow the colours in the
image to be manipulated to provide effects such as highlighting or shading.

 
 Extensions for more complex rendering
 -------------------------------------

The operations that can be provided in a generic manner by the
ImageFileRender module do not cover the full range of operations that might
be applied to every image file format. Because of this, extension data
may be provided which is specific to the renderer in use. Because each
renderer may provide specific data to enable it to render images, and there
may be multiple providers of rendering facilities, a 'magic' identifier is
allocated to each renderer. This is ensures the the renderer is not given
data in a form which it does not understand.

Where a magic identifier is supplied and a suitable renderer is available,
it will be used. If no suitable renderer can be found, the last registered
renderer will be used. This ensures that the where extension data is used
it is passed to the appropriate renderer, and falls back to using the most
recent renderer installed.

The extension data block must be word aligned, and the first word contains
the magic identifier for the render that it is intended for. The remainder
of the extension data block is specific to the renderer in use.

The magic identifier may be any 32bit value, but we recommend that these
are registered with RISCOS Ltd to ensure that there are no duplicated
identifiers. At present, allocations are of the form &6699ccii, where cc
indicates the company or individual producing the renderer, and ii is
some image format number at the company or individual's discretion.


  Sprite file extensions block
  ----------------------------

When rendering sprite files, by default the first sprite is rendered from
the file. This covers the majority of the situations that it will be
required, but where different sprites are required, the extension block
describes which to use. The identifier for the RISCOS Ltd sprite renderer
is &66990101. The named sprite will only be used when the sequence number
is left as 'default'.
    +0  &66990101
    +4  Sprite name, up to 12 characters
  


 Custom renderers
 ----------------

Custom renderers may be registered with the ImageFileRender module. These
renderers can provided additional rendering facilities for third party
filetypes, or provide additional facilities over those of the standard
renderers.

Renderers have four components :
  1) A routine which calculates the bounding box and resolution of an image
  2) A routine which renders an image
  3) A routine which declares fonts in a document (may be omitted)
  4) A routine which returned information about an image

In addition, they provide a number of informational fields which describe
the renderers capabilities :
  * The filetype that the renderer applies to
  * The name of the renderer (including the version and author)
  * A flags word that describes the renderers capabilities
  * The renderers 'magic' identifier (or 0 if it provides no special
    operations)


  Renderer name
  -------------

The renderer name provides details about the renderer in order that
diagnostics may be performed and information about the installed renderers
is available. The renderer name consists of three, tab (ASCII 9) separated,
fields :
  * The renderer name
  * The version number in the form x.xx
  * The authors (or publishers) name


  Renderer flags
  --------------

Not all renderers have the same capabilities, as stated earlier. The
flags provide details to ImageFileRender of the capabilities of the
renderer. This is a bit field, structured :

  bit 0-1: Renderer transformation capabilities:
            0 - Renderer cannot draw anything but identity scaling
                and translation
            1 - Renderer can translate and scale, but scaling must
                be by identical factors
            2 - Renderer can translate and scale by any values in
                both axes
            3 - Renderer supports any form of transformation 
         These bits should be set to the capabilities of the renderer
         Attempts to render files of which the capabilities word 
         indicates are not possible by the renderer will be faulted
         by ImageFileRender module.
  bit 2: Renderer supports colour mapping
         This bit should be set if the renderer can perform colour
         mapping. If unset, attempts to use colour mapping on this
         file type will be faulted by ImageFileRender.
  bit 3: Renderer can draw irregular shapes so must be called to
         calculate bounding boxes.
         This bit should be set if transforming a shape using a complex
         matrix (eg skew or rotate) may result in a different bounding
         box than that which would be generated for a rectangular area.
         If unset, the renderer will be called to calculate the bounds
         of an identity transform only. ImageFileRender will perform
         the remainder of the calculations.
         If a renderer can only render rectangular areas then leaving
         this bit clear simplifies the implementation.
  bits 4-7:  Maximum number of 'quality' levels supported (1-15)
         The highest quality level which is supported by the renderer.
         If the quality level requested by a client exceeds this, the
         renderer will be called with this value.
  bits 8-11: Default 'quality' level to use (1-15)
         Where quality settings are omitted (ie when 'default' quality
         is selected) the default quality will be passed to the renderer.
         A value of 0 means that quality levels are ignored.


Services
--------

 Service_ImageFileRender_Started (&80D40)
 -------------------------------
=> R0 = api version (102 at present)
   R1 = &80D40

This service is issued after the ImageFileRender module has initialised.
Renderers should register themselves with the module.


 Service_ImageFileRender_Dying (&80D41)
 -----------------------------
=> R0 = api version (102 at present)
   R1 = &80D41

This service is issued as the ImageFileRender module finalises to notify
clients that it is no longer providing rendering facilities.


 Service_ImageFileRender_RendererChanged (&80D42)
 ---------------------------------------
=> R0 = api version (102 at present)
   R1 = &80D42
   R2 = filetype affected

This service is issued when a renderer registers or deregisters with the
ImageFileRender module. Clients which have cached details of other renderers
should re-read any renderer values necessary after checking whether the
filetype matches those which they are interested in.



SWIs
----

 ImageFileRender_Render
 ----------------------
=> R0 = rendering flags :
          b0-2: transformation type:
                    0 : Render to fit
                    1 : Render scaled
                    2 : Render transformed
          b3: colour mapping function supplied
          b4: ignore document origin
          b5: reserved, must be 0
          b6-b8: quality to render at :
                    0 : Use default quality
                    1 : Lowest quality
                    2-14 : Renderer specific values
                    15 : Highest quality
          b9-16: reserved for future expansion, must be 0
          b17-31: reserved for future expansion, must be 0
   R1 = filetype
   R2 = pointer to data to render
   R3 = length of data
   R4 = pointer to extension data, or 0 if none
   R5 = image sequence number, or 0 for default image
   R6 = x coord for origin
   R7 = y coord for origin
   R8 = transformation data:
          0: pointer to size
                +0 width
                +4 height
                +8 border to use
                +16 angle to use (degrees<<16)
             image file origin is ignored
          1: pointer to scale block
                +0 x mult
                +4 y mult
                +8 x div
               +12 y div
          2: pointer to transformation matrix:
               standard draw transformation matrix format
   R9 = pointer to colour map descriptor

<= All registers preserved

This SWI is used to render an image file.


 ImageFileRender_BBox
 --------------------
=> R0 = rendering flags :
          b0-2: transformation type:
                    0 : Render to fit
                    1 : Render scaled
                    2 : Render transformed
          b3: reserved, must be 0
          b4: ignore document origin
          b5: return in OS units (otherwise bounding box will be returned
              in draw units)
   R1 = filetype
   R2 = pointer to data to render
   R3 = length of data
   R4 = pointer to extension data, or 0 if none
   R5 = image sequence number, or 0 for default image
   R6 = pointer to transformation data (see above)
   R7 = pointer to bounding box to fill in

This SWI is used to calculate the bounding box for a transformation
operation. As a side effect, it also returns information about the DPI
of the image and colour depth.


 ImageFileRender_Transform
 -------------------------
=> R0 = rendering flags :
          b0-2: transformation type:
                    0 : Render to fit
                    1 : Render scaled
                    2 : Render transformed
          b3: reserved, must be 0
          b4: ignore document origin
   R1 = filetype
   R2 = pointer to data to render
   R3 = length of data
   R4 = pointer to extension data, or 0 if none
   R5 = image sequence number, or 0 for default image
   R6 = pointer to transformation data (see above)
   R7 = pointer to output transformation block to fill in
<= R0 = x DPI
   R1 = y DPI

This SWI is used to calculate the transformation matrix that would be used
for an operation without performing that operation. 


 ImageFileRender_DeclareFonts
 ----------------------------
=> R0 = flags (reserved, must be 0)
   R1 = filetype
   R2 = pointer to data to render
   R3 = length of data
   R4 = pointer to extension data, or 0 if none
   R5 = image sequence number
   R6 = flags to pass to PDriver_DeclareFont

This SWI should be used when printing images using the ImageFileRender
module before any printing operations begin. Refer to the section 'Declare
the fonts your document uses' in the chapter on Printing for more details.



 ImageFileRender_Info
 --------------------
=> R0 = flags (reserved, must be 0)
   R1 = filetype
   R2 = pointer to data to render
   R3 = length of data
   R4 = pointer to extension data, or 0 if none
   R5 = image sequence number
   R6 = query type :
              &00000000: Base details
              &00000001-&0000FFFF: Reserved for system use
              &00001000-&00FFFFFF: Reserved for developers
              &00FF0000-&00FFFFFF: Reserved for private use
              Others reserved for future expansion
   R7 = pointer to query block
   R8 = length of query block
<= R8 = if error returned:
           -length of block required
           or +ve value if length cannot be determined (or was not the error)
        length of block used

This SWI should be used to find out information which is not provided by
the generic APIs. It may be used (for example) to read the time between
frames for a custom renderer, or to read additional information about the
image which would otherwise not be available.

  Base details query (0)
  ----------------------
    +0 = sequence number
    +4 = x DPI
    +8 = y DPI
   +12 = colour type :
          0 unspecified colour type (usually 'free' colour selection)
          1 1bpp RGB
          2 2bpp RGB
          3 4bpp RGB
          4 8bpp RGB
          5 16bpp RGB
          6 24bpp RGB
          7 CMYK
        others reserved
   +16 = image flags :
          bit 0  if set, the image is solid and covers the entire bounding
                 box described
                 if clear, the image may have sections which reflect the
                 background colour
          others reserved

This query is used to get generic information on an image in the file which
was not necessary for the rendering of the file. This call is most commonly
used to find the sequence number of the default and last logical image
within a file. The sequence number may be set to &FFFFFFFF to indicate that
the sequence number is not known. This might be the case if the format
has no indication of the number of images present.

The image flags provide additional information about the image which might
be useful to renderers. The only defined flag at present is that indicating
if the image is 'solid' or not. This can be used by clients to decide
whether drawing a background behind the image is necessary or not.


 ImageFileRender_RendererInfo
 ----------------------------
=> R0 = flags (must be 0)
   R1 = filetype
   R2 = magic identifier (or 0 for information on the generic renderer)
<= R0 = pointer to definition block
   R1 = pointer to renederer name

This SWI is used to return information about a renderer.



 ImageFileRender_Register
 ------------------------
=> R0 = flags (reserved, must be 0)
   R1 = pointer to definition (all will be copied):
            +0 API version (102)
            +4 renderer flags
            +8 filetype
           +12 magic value, or 0 if none
           +16 pointer to name
           +20 workspace value for r12
           +24 pointer to 'start' entry point, or 0 if none
           +28 pointer to 'stop' entry point, or 0 if none
           +32 pointer to render entry point
           +36 pointer to bounding box entry point
           +40 pointer to declare fonts entry point, or 0 if none
           +44 pointer to information entry point
        or 0 to return just the API version
<= R1 = API version (even if an error occurs)
   All other registers preserved

This SWI is used to register a new renderer.



 ImageFileRender_Deregister
 --------------------------
=> R0 = flags (reserved, must be 0)
   R1 = filetype
   R2 = pointer to name to be copied in format :
          <name><tab><version x.xx><tab><author>
   R3 = magic value to match (must be the same as when registered)
<= All registers preserved

This SWI is used to deregister a renderer.


Image renderers
---------------

 Image descriptor block
 ----------------------

The image descriptor block is provided to all image renderers and provides
the core information required for all the processing routines. Before any
calls are made to the major processing routines in the renderer, a call is
made to the 'start' entry point. This allows clients to cache any relevant
data in the image descriptor block such that processing by other routines
may be performed without repeatedly requiring that such data be calculated.
For example, a sprite renderer might cache a translation table, or a pointer
to the sprite. The 'stop' entry point will be called to destroy the cached
data held in the 'private image data' entry.

The image descriptor block has the following format :

   +0 pointer to data to render
   +4 length of data
   +8 pointer to extension data, or 0 if no data
  +12 image sequence number
  +16 private image data

The first four of these entries will be supplied by the ImageFileRender
module. The last will be initialised to zero and may be set to any value by
the 'start' entry point. For certain image formats, the caching of data
through the 'start' and 'stop' operations can improve the rendering speed by
not requiring repeated calculation of values. A simple example might be
the 'Render to fit' operation, which requires the calculation of a bounding
box before the actual rendering. For a complex image, this information might
be cached to aid rendering.


 'Start' routine
 ---------------
=> R0 = API version * 100 (102 in this version)
   R1 = pointer to image descriptor :
          +0 pointer to data to render
          +4 length of data
          +8 pointer to extension data, or 0 if no data
         +12 image sequence number
         +16 private image data, 0 initially but may be updated
   R2 = 0
   R12 = workspace value on entry to ImageFileRender_Register

The 'start' routine is called before any operations are applied to a
particular image. This allows clients to cache relevant data for an
image.


 'Stop' routine
 --------------
=> R0 = API version * 100 (102 in this version)
   R1 = pointer to image descriptor :
          +0 pointer to data to render
          +4 length of data
          +8 pointer to extension data, or 0 if no data
         +12 image sequence number
         +16 private image data, 0 initially but may be updated
   R2 = 0
   R12 = workspace value on entry to ImageFileRender_Register

The 'stop' routine is called after any operations have been completed (even
if one of the operations generated an error). This allows clients to release
cached data.


 Bounding box calculation routine
 --------------------------------
=> R0 = API version * 100 (102 in this version)
   R1 = pointer to image descriptor
   R2 = pointer to bounding box descriptor :
          +0 flags (0)
          +4 transformation matrix to apply (standard format)
         +28 bounding box to fill in (standard format)
   R12 = workspace value on entry to ImageFileRender_Register

The bounding box routine is called to calculate the bounding box for a
given transformation. If the image data is not recognised, it should be
faulted. Errors should be reported by setting V and returning an error
block in R0. The bounding box should be returned in draw coordinates for
the images extent. That is, OS units * 256.


 Rendering routine
 -----------------
=> R0 = API version * 100 (102 in this version)
   R1 = pointer to image descriptor
   R2 = pointer to rendering descriptor :
          +0 flags :
            b3: colour mapping function supplied
            b6-b8: quality to render at :
                      0 : Use default quality
                      1 : Lowest quality
                      2-14 : Renderer specific values
                      15 : Highest quality
            b9-16: reserved for future expansion, must be 0
         
          +4 transformation matrix to apply (standard format)
         +28 clipping rectangle in external coordinates (standard format)
         +44 pointer to colour mapping routine
         +48 workspace for colour mapping routine
   R12 = workspace value on entry to ImageFileRender_Register

The rendering routine is called to render an image using a given
transformation. If the image data is not recognised, it should be faulted.
Errors should be reported by setting V and returning an error block in R0.


 Font declaration routine
 ------------------------
=> R0 = API version * 100 (102 in this version)
   R1 = pointer to image descriptor
   R2 = pointer to declare fonts descriptor :
          +0 flags (0)
          +4 flags to pass to PDriver_DeclareFont

The font declaration routine need only be provided by renderers which
use fonts. The renderer should call PDriver_DeclareFont with the names
of all fonts and the flags passed in R4. If the image data is not
recognised, it should be faulted. Errors should be reported by setting V and
returning an error block in R0.


 Information routine
 -------------------
=> R0 = API version * 100 (102 in this version)
   R1 = pointer to image descriptor
   R2 = pointer to declare fonts descriptor :
          +0 query type
          +4 query data length
          +8 pointer to data block to take details from/fill in
<= If VSet, R0 = pointer to error,
            or 1 for an 'invalid query type'
            or 2 for an 'invalid query length'

The information routine should be provided by renderers to query information
about the images. The routine should fault invalid queries and invalid query
lengths.
