> Fonts.Methods

Summary
-------

        Font$Path and Font$Prefix
        Changing the font path
        Summary of font files
        Aliased fonts
        Rules for cacheing
        Font_MakeBitmap
        Font_UnCacheFile
        Font_SetFontMax / Font_ReadFontMax
        Font_ReadFontPrefix

Font$Path and Font$Prefix
-------------------------

The old font manager allowed access to a single directory of fonts, whose
name was held in the variable Font$Prefix.  All calls to Font_FindFont went
through this variable, and also Font_ListFonts (or *FontCat).

The new font manager gets its fonts via Font$Path, rather than Font$Prefix,
allowing separate libraries of fonts to be added to the system.  When
Font_FindFont is called, the font manager looks up the name via Font$Path,
using the first directory it finds which has the correct name, as long as it
contains an IntMetrics file.

For compatibility, the Font Manager on initialisation looks to see if
Font$Path is already defined - if not, it initialises it as follows:

        *SetMacro Font$Path <Font$Prefix>.

Note the "." on the end - this is required because Font$Path is a path,
whereas Font$Prefix was just a directory name, rather than a prefix.

Font_ListFonts and *FontCat now accept an optional path string rather than a
directory name, for example:

        *FontCat                      ; uses <Font$Path>
        *FontCat adfs:$.Fonts.,net:   ; each path element is a prefix

If more than one occurrence of the same font is discovered, only the first
one will be reported.  This allows an application calling Font_ListFonts to
be sure that all font names reported are unique.


Changing the font path
----------------------

Applications which allow the user access to fonts should call Font_ListFonts
repeatedly to discover the list of fonts available.  This is normally done
when the program starts up.

However, it often happens that families of fonts are to be found in separate
font "application" directories, whose !Run file RMEnsures the correct font
manager module from within itself and then either adds itself to Font$Path or
resets Font$Path and Font$Prefix so that it is the only directory referenced.

In order to ensure that the user can access the new fonts available,
applications should check whether the value of Font$Path or Font$Prefix has
changed since the list of fonts was last cached, and recache the list if so. 
A BASIC program could accomplish this as follows:

  size% = &200
  DIM buffer% size%        : REM this could be a scratch buffer

  ...

  SYS "OS_GSTrans","<Font$Prefix> and <Font$Path>",buffer%,size%-1 TO ,,length%
  buffer%?length% = 13    :REM ensure there is a terminator (13 for BASIC)
  IF $buffer%<>oldfontpath$ THEN
    oldfontpath$ = $buffer%
    PROCcache_list_of_fonts
  ENDIF

Note that if the buffer overflows the string is simply truncated, so it is
possible that the check may miss some changes to Font$Prefix.  However, since
new elements are normally added to the front of Font$Path, this will probably
not matter.

The application could scan the list of fonts when it started up, remembering
the value of Font$Path and Font$Prefix in oldfontpath$, and then make the
check described above just before the menu tree containing the list of fonts
was about to be opened.

Alternatively the application could scan the list of fonts only when
required, by setting oldfontpath$="" when it started up, and checking for
Font$Path changing only when the font submenu is about to be opened (using
the Message_MenuWarning message protocol.)


Summary of Font Files
---------------------

The font files relating to a font are all contained in a single directory:

        IntMetrics              ; metrics information (character widths etc)
        x90y45                  ; old format pixel file (4-bpp)
        f9999x9999              ; new format pixel file (4-bpp)
        b9999x9999              ; new format pixel file (1-bpp)
        Outlines                ; new format outline file

Note that the '9999's referred to above mean 'any decimal number in the
range 1..9999'.  They refer to the pixel size of the font contained within
the file, which is equal to:

        (font size in 1/16ths of a point) * dots per inch / 72

so, for example, a file containing 4-bpp 12 point text at 90 dots per inch
would be called f240x240, because 12*16*90/72 = 240.

The minimal requirement for a font is that it should contain an IntMetrics
file and an x90y45 or Outlines file.  In addition, it can have any number of
f9999x9999 or b9999x9999 files, to speed up the cacheing of common sizes.

If outline data or scaled 4-bpp data is to be used as the source of font
data it is first loaded into a 'master' font in the cache, which can be
shared between many 'slave' fonts at various sizes.  There can be only one
master font for a given font name, regardless of size, whereas each size of
font requires a separate slave font.  If the data is loaded directly from
the disc into the slave font, the master font is not required.


Aliased fonts
-------------

Where you are using an external printer (eg. PostScript) which has a larger
range of fonts than those available on the screen, it can often be useful to
use a similar-looking font on the screen, using the appropriate metrics (ie.
spacing) for the printer font.

The font manager provides a facility whereby a font can be created which has
its own IntMetrics file, matching the appropriate font on the printer, but
uses another font's characters on the screen.

This is done by putting a file called 'Outlines' in the font's directory
which simply contains the name of the appropriate screen font to use.  The
font manager will use the IntMetrics file from the fonts own directory, but
will look in the other font's directory for any bitmap or outline
information.


Rules for cacheing
------------------

Where several font files exist in the same directory, the Font Manager must
decide which file is most suitable as the data source for a particular font
in a particular size and number of colours.

The number of colours to be used is determined by the 'font colour offset'
supplied in the Font_SetFontColours call:

        SWI Font_SetFontColours:
        R0 = font handle (0 ==> no change)
        R1 = background colour
        R2 = first foreground colour
        R3 = font colour offset

Here the font foreground colour is given by R2+R3, with R3 intermediate
shades being used to provide anti-aliasing.  If R3 is zero, the font is
being painted in monochrome.  When painting, the same font handle can be
used for monochrome as for anti-aliased text, but the font manager may have
different sets of data in its cache for the two cases.

In addition to the number of colours being used, the font manager also takes
note of various 'user thresholds' which can be configured in CMOS RAM to
reflect the preferences of the user.  These determine the maximum font size
for which a particular action will be taken: for example, you can set a font
size threshold above which no anti-aliasing will be performed, even if
Font_SetFontColours indicates otherwise.

The various thresholds are set up as follows:

        *Configure FontSize <n>k  ; min size of cache
        *Configure FontMax  <n>k  ; max size of 'auto-grow' cache
        *Configure FontMax1 <h>   ; max size of non-exact font from x90y45
        *Configure FontMax2 <h>   ; max size of anti-aliased outlines
        *Configure FontMax3 <h>   ; max size of cached outlines
        *Configure FontMax4 <w>   ; max size of horizontally-subpixeled font
        *Configure FontMax5 <h>   ; max size of vertically-subpixeled font

where <h> refers to the maximum font pixel height (pixel height = point
height * dpi / 72), and <w> to the maximum font pixel width.

FontSize / FontMax
------------------

FontSize refers to the initial cache size, which is asserted when the font
manager is initialised or *RMReInit'ed.  The minimum cache size can also be
changed from the Task Manager, by dragging the font cache bar directly,
although this is not remembered when the font manager is re-initialised.

If FontMax is bigger than the minimum font size, the font manager will
attempt to expand the cache if it cannot obtain enough cache memory by
throwing away unused blocks (ie. ones that belong to fonts which have had
Font_FindFont called on them more often than Font_LoseFont).  Once the cache
has expanded up to FontMax, the font manager will throw away the oldest
block found, even if it is in use. This can result in the font manager
'thrashing', since during a window redraw it is possible that all fonts will
have to be thrown away and recached in turn.

Note that the cache will only grow to accommodate claimed fonts, which means
that applications should keep fonts claimed while they are likely to be
needed again: ie. as long as there are any windows being displayed which
contain those fonts.

FontMax1
--------

If a font has both an x90y45 file and an Outlines file, the font manager is
in something of a quandary.  It would rather use the outlines file in all
cases, since it always produces results at least as good as the scaled
bitmaps, but unfortunately it does take longer.

The solution is that the font manager will use the x90y45 version of a font
either if the exact size required is contained in the file, or if the font
size required is less than or equal to the value specified in FontMax1.

Note that the f9999x9999 (or b9999x9999, as appropriate) will always be
preferred if the exact size is found, and it is also possible to scale from
an f9999x9999 file, by creating an x90y45 file which contains only the name
of the f9999x9999 file.  In the latter case, the same rules apply concerning
FontMax1, if there is also an Outlines file.

FontMax2
--------

If the font size required is larger than this value, then the font manager
will never convert from outlines to 4-bpp bitmaps (it will use 1-bpp
instead).  It will use an f9999x9999 or x90y45 version of the font if the
exact size is found or the font size is less than or equal to FontMax1.

FontMax3
--------

If the font size required is larger than this value, the font manager will
not store the results of converting from outlines to bitmaps, but will
instead draw the data directly onto the destination, cacheing the outlines
themselves instead.  Note that in this case the text is not drawn
anti-aliased, since the Draw module is used to draw the outlines directly.

NB: The font manager sets up the appropriate GCOL and TINT settings when
    drawing the outlines, but it resets them afterwards.

FontMax4
--------

If the font width is less than or equal to FontMax4, the font manager will
try to use the outlines file rather than x90y45, and will construct 4
bitmaps for each character, corresponding to 4 possible subpixel positions
on the screen.  When painting the text, it will use the bitmap which
corresponds most closely to the required horizontal subpixel position.

Note that if there is an f9999x9999 file of the appropriate size, this will
take precedence over the settings of FontMax4 and FontMax5.  This bitmap may
however have been constructed with subpixel positioning already performed
(see Font_MakeBitmap).

FontMax5
--------

This is similar to FontMax4 except that the font height determines whether
it is performed, and it constructs bitmaps for each of 4 possible vertical
subpixel alignments.

Note that if both horizontal and vertical subpixeling are performed, there
will be 16 bitmaps for each character.


Font_MakeBitmap
---------------

        SWI Font_MakeBitmap
        R1 = font handle, or
             R1 -> font name
             R2,R3 = x/y point size * 16
             R4,R5 = x/y dpi (or 0,0 for default)
        R6 = flag word:
             bit 0 set => construct f9999x9999 (else b9999x9999)
             bit 1 set => do horizontal subpixel positioning
             bit 2 set => do vertical subpixel positioning
             bit 3 set => just delete old file, without replacing it
             bits 4..31 reserved (must be 0)

This call allows a particular size of a font to be pre-stored in the font's
directory so that it can be cached more quickly.  It is especially useful if
subpixel positioning is to be performed, since this takes a long time if
done directly from outlines.

Once a font file has been saved, its subpixel scaling will override the
setting of FontMax4/5 currently in force (so eg. if the font file had
horizontal subpixel scaling, then when a font of that size is requested,
horizontal subpixel scaling will be used even if FontMax4 is set to 0).


Font_UnCacheFile
----------------

        SWI Font_UnCacheFile
        R1 -> full filename of file to be removed
        R2 = recache flag (0 or 1 - see below)

If an application such as !FontEd wishes to overwrite font files without
confusing the font manager, it should call this SWI to ensure that any
cached information about the file is deleted.

The filename pointed to by R1 must be the full filename (ie. in the format
used by the Filer), and must also correspond to the relevant name as it
would have been constructed from Font$Path and the font name.  This means
that each of the elements of Font$Path must be proper full pathnames,
including filing system prefix and any required special fields (eg.
net#fileserver:$.fonts.).

The SWI must be called twice: once to remove the old version of the data,
and once to load in the new stuff.  This is especially important in the case
of IntMetrics files, since the font cache can get into an inconsistent state
if the new data is not read in immediately.

The 'recache' flag in R2 determines whether the new data is to be loaded in
or not:

        SYS "Font_UnCacheFile",,"<filename>",0
        <replace old file with new one>
        SYS "Font_UnCacheFile",,"<filename>",1


Font_SetFontMax / Font_ReadFontMax
----------------------------------

        Font_SetFontMax
        In:  R0 = new value of FontMax (bytes)
             R1-R5 = new values of FontMax1..FontMax5 (pixels * 72 * 16)
             R6,R7 = 0 (reserved)

        Font_ReadFontMax
        Out: R0 = value of FontMax (bytes)
             R1-R5 = values of FontMax1..FontMax5 (pixels * 72 * 16)
             R6,R7 = 0 (reserved)

The two calls can be used to set and read the values of FontMax and
FontMax1..FontMax5.  Changing the configured settings will also change these
internal settings, but Font_SetFontMax does not affect the configured
values, which come into effect on ctrl-break or when the font manager is
re-initialised.

Calling Font_SetFontMax also causes the font manager to search through the
cache, checking to see if anything would have been cached differently if the
new settings had been in force at the time.  If so, the relevant data is
discarded (it will be reloaded using the new settings when next required).


Font_ReadFontPrefix
-------------------

        Font_ReadFontPrefix (SWI &4009D)
        In:   R0 = font handle
              R1 -> buffer to receive prefix
              R2 = length of buffer
        Out:  R1 -> terminating 0 of prefix
              R2 = bytes remaining in buffer
        Error "Buffer overflow" if buffer too small

This call may be used to find out the directory prefix relating to a given
font handle (ie. the prefix which indicates where the font's 'IntMetrics'
file is (eg. "adfs::4.$.!Fonts.Trinity.Medium.").

The value read could be used by a font utility program to find out which
sizes of a font were available pre-scaled in the font directory.
