Font$Path and Font$Prefix summary of font files rules for cacheing Font_MakeBitmap
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.
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.
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 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.
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 (#### - not yet implemented). In the latter case, the same rules apply concerning FontMax1, if there is also an Outlines file.
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.
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.
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).
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.
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 bits 3..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.
#### Currently this call only works properly if:
(a) the font has an outlines file (b) the font does not already have the required bitmap file (in this case it all goes horribly wrong!)