> net#arf:$.a500.RiscOS+.doc.Fonts

Author:  Neil Raine
Status:  changes to Font Manager documentation for PRM
History:
    13-Nov-89  NRaine  File created.
    20-Nov-89  NRaine  19,r,g,b,R,G,B,max sequence added.
    23-Nov-89  NRaine  Changes to Font_FutureFont added.
     6-Dec-89  NRaine  Font_ReadFontMetrics added.
     9-Dec-89  NRaine  Changes to Font_CurrentFont added.
    23-Mar-90  NRaine  Font_CurrentFont R0 bit 31 moved to R3.
     8-Jan-91  NRaine  Added Font_FindFont new field type (inc. matrices)
     8-Jan-91  NRaine  Added new Font_ListFonts stuff
     8-Jan-91  NRaine  Added *LoadFontCache, *SaveFontCache

Unresolved issues
=================

I would like ColourTrans_SetFontColours to be changed so that it calls
Font_Paint with a 19,r,g,b,R,G,B colour change sequence.  This will avoid
the problems with Font_CurrentFont,Font_FuruteFont and
Font_SwitchOutputToBuffer described below.

Note that ColourTrans_ReturnFontColours will still be restricted, because it
must return a set of font colours suitable for passing to
Font_SetFontColours.


Not yet implemented
===================

Font_FindFont currently ignores the \N and \A fields, and Font_ListFonts
does not check for MessageXX files in the font directory, so all font names
must be equal to the identifiers.


==============================================================================


New control sequences in Font_Paint and Font_StringWidth
--------------------------------------------------------

19,r,g,b,R,G,B,max = ColourTrans_SetFontColours

    All quantities are unsigned bytes
    r,b,g = background colour (&00=black, &FF=white)
    R,G,B = foreground colour (&00=black, &FF=white)
    max = max font colour offset allowed (0..14)


Font_CurrentFont
Font_FutureFont
---------------

    Out:    R0 = font handle
            R1 = background logical colour       / background &BBGGRR00
            R2 = first foreground logical colour / foreground &BBGGRR00
            R3 bits 0..7 = font colour offset    / max colour offset
               bits 8..30 = reserved (ie. undefined)
               bit 31 = 0 => R1,R2,R3 bits 0..7 = logical colours
                      = 1 => R1,R2,R3 bits 0..7 = RGB colours

Bit 31 of R3 on exit indicates whether the last colour change was made in
terms of logical colours or RGB values: if the bit is clear, R0,R1,R2,R3 are
suitable for use with Font_SetFontColours, and if it is set, then R1,R2,R3
(bits 0..7) are suitable for use with ColourTrans_SetFontColours or for
putting into a Font_Paint 19,r,g,b,R,G,B,max sequence.

As before, Font_FutureFont is analogous to Font_CurrentFont, but should be
called after Font_StringWidth / Font_FindCaret / Font_StringBBox to find out
what the colours were at the point the scan terminated.

NB: If you call ColourTrans_SetFontColours instead of using the Font_Paint
    19,r,g,b,R,G,B,max sequence, Font_CurrentFont will return the absolute
    colours, as it doesn't know what the originals were.

    This also has implications for Font_SwitchOutputToBuffer: the RGB
    colours of the resulting draw object will not retain all the 24-bit
    palette information originally supplied if ColourTrans_SetFontColours is
    used.


Font_SwitchOutputToBuffer
-------------------------

    Font_SwitchOutputToBuffer
    In:     R0 = flags:
               if R1 <= 0, then bits 0..31 are reserved (must be 0)
               if R1 > 0:
                 bit 0 set => update R1, but don't store anything
                 bit 1 set => apply 'hints' to the outlines
                 bit 2 set => include skeleton lines if required        ; NYI
                 bit 3 set => produce sprites for bitmapped characters  ; NYI
                 bit 4 set => give error if bitmapped characters occur
                              (this bit overrides bit 3)
                 bits 5..31 reserved (must be 0)
            R1 -> word-aligned buffer,
               or 8 initially to count the space required for a buffer
               or 0 to switch back to normal
               or -1 to leave state unaltered (ie. enquire about current status)
               if buffer, [R1,#0]=0, [R1,#4] = size remaining from R1+8 onwards
    Out:    R0 = previous flag settings
            R1 = previous buffer pointer (updated)

After this call, any calls to Font_Paint will be redirected into the buffer,
as a Draw file structure.  Each letter painted will be treated as a separate
filled object, with the colours specified in the paint command.

If R0 bit 0 is set, output is not actually sent to the buffer, but the
pointer is updated.  This allows the size of the required buffer to be
computed properly before allocating the space for it.  Note that if R0 bit 0
is set, R1 must be greater than 0 initially (a value of 8 is suitable, since
the buffer must allow space for the terminator and free space counter on the
end).  After filling the buffer, the data is between (original R1) and
(final R1 minus 1), ie. on exit [ R1 -> 0, <size remaining> ] and these two
words do not form part of the output data itself.

The rubout box(es) and any underlining are also sent to the buffer as a
series of filled outlines.  These will be in the correct order so as to be
behind any characters which overlap them.  The output will also take into
account matrix transformations, font and colour changes, explicit movements,
justification and kerning.

If R0 bit 1 is set, the character outlines have hints applied to them (at
the current size) - this means that they are not really suitable for scaling
later on.

If R0 bit 2 is set, the character objects consist of a group of two objects
- one is the filled outline, and the second is the stroked skeleton.

Any characters which are only available as bitmaps will either be errored
(if R0 bit 4 is set), ignored (if R0 bit 3 is clear), or represented as
bitmap objects in the output (either 1-bpp or 4-bpp, with a palette to match
the output colours).

In this way !Draw should be able to turn on buffering, then proceed to draw
an arbitrary text column in the appropriate position and size, ending up
with a series of Draw objects which represent the same thing.

The set of objects that the Font Manager produces could easily be converted
into a group by wrapping them suitably.


Font_FindFont
-------------

    Font_FindFont
    In:     R1 -> font name, with optional style(s) added
            R2 = x-point size * 16
            R3 = y-point size * 16
            R4 = x-dots per inch (-1 => use current)
            R5 = y-dots per inch (-1 => use current)
    Out:    R0 = font handle

    The font "name" string can now have various qualifiers added to it,
    which are a "\" followed by an identifying letter and the value
    associated with the qualifier.  If the string does not start with a "\",
    it is assumed that the first element is a font identifier.

    The possible qualifiers are:

        \I<identifier>  font identifier (as for old Font_FindFont)
        \N<hex2><name>  territory (country) number of font name, followed by
                        the font name in the alphabet of the territory
                        (terminated by end-of-string).
        \A<hex2>        alphabet number (0 => default for this territory)
        \M<matrix>      transformation matrix to apply to this font

    where <hex2>   is a 2-digit hex number (each digit is 0..9 or A..F).

          <matrix> is a set of 6 signed decimal integers which represent the
                   values of the 6 words that go into making a draw-type
                   matrix: the first four numbers are in fact 16-bit fixed
                   point, and the last two are offsets in 1/1000th of an em.

    The font identifier is the name of the font directory without the
    Font$Path prefix, and is invariant in any territory.  The font name is
    the name of the font (ie. the one displayed to the user) in the given
    territory.

    If Font_FindFont fails to find the font, an error message "Font '<name>'
    not found" is returned, where <name> is the font name if the current
    territory is the same as the one in the string, and is the font
    identifier otherwise.

    It is recommended that applications store the entire string returned
    from Font_DecodeMenu in the document, so that if the user loads the
    document without having the correct fonts available, the font name
    (rather than the identifier) can be returned (as long as he is in the
    same territory).

    The alphabet number indicates the appropriate encoding for the font
    itself.  If the alphabet number is zero, the default for the current
    territory is used.  If the font has an alphabet number of 0, it will
    ignore the encoding requested and use its own (eg. if it is a symbol
    font).

    Note that Font_DecodeMenu will return a font identifier of the following
    form:
                \I<fontid>\N<hex2><fontname>

    To apply a particular alphabet to a font, always put the alphabet
    qualifier on the front, since the font name must always go on the end:

                \A<hex2>\I<fontid>\N<hex2><fontname>


*FontInstall
------------

    Syntax: *FontInstall [<prefix>]

    This call alters Font$Path so that the given prefix appears at the
    front.  It also eliminates any other occurrences of the prefix.

    It also rescans the given prefix, even if it was already known to the
    Font Manager.

    *FontInstall on its own causes all prefixes in Font$Path to be
    rescanned.  Service_FontsChanged is issued whenever a prefix is scanned.


*FontLibrary
------------

    Syntax: *FontLibrary <directory path>

    This call alters Font$Prefix to the given value, and ensures that
    "<Font$Prefix>." appears on the front of Font$Path.

    Note that the next call to *FontLibrary will cause the previous font
    library to be removed from the list of directories scanned.


*FontRemove
-----------

    Syntax: *FontRemove <prefix>

    This call removes any occurrences of the prefix from Font$Path.


Font_ListFonts
--------------

    SWI Font_ListFonts (&40091)
    In:   R2 bits 0..15 = counter (0 on first call)
          R2 bits 16..31 = 0 => old-style: treat R2 as bits 16,18 set, R3 = 40
             bit 16 = 1 => return font identifier in [R1..] or return size
             bit 17 = 1 => return font name in [R4..] or return size
             bit 18 = 1 => return strings terminated with 13, else 0
             bit 19 = 1 => return font menu in [R1..] and [R4..] or return sizes
             bit 20 = 1 => put "System font" at head of menu
             bit 21 = 1 => tick font indicated by R6
             bits 22..31 reserved (must be 0)
             NB: R2 bit 19 = 0 => R2 bits 20,21 = 0
                 R2 bit 19 = 1 => R2 bits 16,17 = 0
          If R2 bits 16 or 19 set:
             R1 = 0 => return size of buffer
                <>0 => R1 -> buffer for font identifier or menu
             R3 = size of buffer in R1 (if R1 <> 0)
          If R2 bit 17 or 19 set:
             R4 = 0 => return size of buffer
                <>0 => R4 -> buffer for font name or menu indirected data
             R5 = size of buffer in R4 (if R4 <> 0)
          If R2 bit 21 set:
             R6 -> identifier of font to tick (also ticks submenu parent)
             R6=1 => tick "System font"
             R6=0 => don't tick anything

    Out:  R2 = -1 => no more font names/identifiers
                     font identifier/name is invalid in this case
                     font menu preserves R2 and does it all in one go
          R2 = counter/flags for next time
          If R2 bit 16 or 19 set on entry:
             If R1<>0 on entry, then [R1..] = font identifier or menu
             R3 = size of buffer required (if menu, 0 => no entries in menu)
          If R2 bit 17 or 19 set on entry:
             If R4<>0 on entry, then [R4..] = font name or menu data
             R5 = size of buffer required

          If R2 bit 19 set on entry then R2 is preserved on exit.  Note that
          in this case Font_ListFonts need only be called once to measure the
          length of buffer required, and once more to construct the actual
          menu.

          If R2 bit 19 set, bit 20 clear, then R3=0 on exit => null menu.

          If R2 bits 16..31 are clear on entry, then this is treated as though
          R2 bits 16 and 18 were set and R3=40 on entry.
          On exit R2 = R2+1 (bits 16..31 clear) or R2=-1.

    Errors:
          "Buffer overflow" (R3 or R5 were too small)
          "Bad parameters" (R2 flag bits invalid)
          If an error is returned, R2=-1 (listfonts terminated)

    This call returns the list of fonts known to the font manager, which is
    also cached.  The names are returned in alphabetical order, regardless
    of which prefix they are found under.


Font_DecodeMenu
---------------

    In    R1 -> menu definition
          R2 -> menu selections (word array)
          R3 -> buffer to contain answer (0 => just return size)
          R4 = size of buffer (if R3<>0)
    Out   R2 -> rest of menu selections (if R3<>0 on entry)
          [R3..] = string to pass to Font_FindFont (if R3<>0 on entry)
          R4 = size of buffer required to hold output string
             = 0 => no font selected

    If the chosen font has a name as well as an identifier, then the string
    is returned in the form "\I<id>\N<territory number> <name>", otherwise
    just the identifier is returned.

    Since Font_DecodeMenu works by comparing the string in the menu against
    the Font Manager's known font names, in the case of "System font" being
    selected from a menu that contained it, R4 would be returned as 0.  To
    distinguish this from the "no font selected" case, check for [R2]=0 on
    entry, since "System font" is always the first menu entry if present.


Font_ReadFontMetrics
--------------------

  Font_ReadFontMetrics
  In:   R0 = font handle
        R1 = 0 or -> buffer to contain bbox info
        R2 = 0 or -> buffer to contain xwidth info
        R3 = 0 or -> buffer to contain ywidth info
        R4 = 0 or -> buffer to contain miscellaneous info
        R5 = 0 or -> buffer to contain kerning info
        R6 = 0
        R7 = 0
  Out:  R0 = file flags:
                bit 1 set => kern pairs don't have x-offsets
                bit 2 set => kern pairs don't have y-offsets
                bit 4 set => there are more than 255 kern pairs
                other bits are undefined
        R1-R5 = size of data (0 if not present in file)
                data copied to buffer if pointer was non-zero
                (ie. set pointers to 0 to find out size)
        R6,R7 undefined
 
Currently this call is not permitted on fonts which have a transformation
matrix applied to them.  It is recommended that the call is made on the
untransformed version of the font, and the results then transformed
appropriately.  Note that when transforming bounding boxes, the resulting
box is that which bounds all 4 transformed bounding box corners.  When
transforming x and y offsets (ie. character widths), the last 2 numbers in
the matrix (the offsets) should be ignored, since the new origin is also
moved by these amounts, and they therefore cancel out.

The format of the data in the buffers is as follows:

Except where otherwise stated:

        All units are 1/72000"
        All 2-byte and 4-byte numbers are little-endian, signed
        A "word" is a 4-byte quantity

R1 -> BBox info:
        array[256] of groups of 4 words (x0,y0,x1,y1)

R2 -> XWidth info:
        array[256] of words

R3 -> YWidth info:
        array[256] of words

R4 -> Miscellaneous data:

        8       font bounding box (signed x0,y0,x1,y1)
        2       default x-offset per char (if flags bit 1 set)
        2       default y-offset per char (if flags bit 2 set)
        2       italic h-offset per em (-1000 * TAN(italic angle))
        1       underline position (signed, in 1/256th of an em)
        1       underline thickness (unsigned, in 1/256th of an em)
        2       CapHeight
        2       XHeight
        2       Descender
        2       Ascender
        4       reserved field (must be 0)
        n       Encoding name, terminated by 0

R5 -> Kern data:

        4       x multiplier
        4       y multiplier
        4       x divisor
        4       y divisor

                Kern pair hash table index is given by:
                        (first letter) EOR (second letter ROR 4)
                where the rotate happens in 8 bits.

        256     low-byte of kern pair index
        1       low-byte of number of kern pairs
        256     high-byte of kern pair index (if flags bit 4 set)
        1       high-byte of number of kern pairs (if flags bit 4 set)

                This table indicates the point in the list of kern pairs
                following the table to start looking for a given kern pair. 
                The index must be multiplied by the size of a kern pair
                entry (3 if flags bit 1 or 2 set, 5 if both clear) to find
                the offset.  The entries are consecutive, so each list
                finishes as the next one starts.

                Kern pairs:
        1       second letter of pair
        2       x-kern amount (if flags bit 1 clear) (x-design units)
        2       y-kern amount (if flags bit 2 clear) (y-design units)

    Note that the kern offsets must be scaled by the x and y multipliers and
    divisors in order to give the correct answer in 1/72000".


*SaveFontCache
--------------

This command saves the current contents of the font cache, with certain
extra header information, to a file of type &FCF (FontCache).  The Run
alias for this filetype executes *LoadFontCache.


*LoadFontCache
--------------

This commands loads a font cache file previously saved using *SaveFontCache
back into the font cache.

An error will be returned if there are any font currently claimed, or if the
font cache format cannot be read by the current font manager (ie. it was
created by a version of the font manager that used an incompatible font
cache format.

The size of the font cache slot will be increased if necessary to
accommodate the new cache data, but will not be decreased if the new cache
data is smaller than the current cache slot size.

These commands are useful for setting up the font cache to a predefined
state, to save time later on.

