Font Manager improvements for RISC OS 2.50

Already implemented:

Not yet implemented:

Changes to the interface

Deprecated SWIs:

      Font_FindCaret            ; needs matrix
      Font_FindCaretJ           ; needs matrix
      Font_StringWidth          ; needs matrix
      Font_StringBBox           ; needs matrix
      Font_SetFont              ; silly when you can use Font_Paint (R0)
      Font_ReadInfo             ; font bbox can be found using Font_CharBBox

Extended SWIs:

      Font_Caret                ; needs matrix
      Font_Paint                ; new parameters for matrix etc
      Font_CharBBox             ; code = -1 => return font bbox

New SWIs:

      Font_ReadFontMetrics      ; return whole of font metrics in buffers
      Font_ScanString           ; deals with Font_StringWidth etc.
      Font_SwitchOutputToBuffer ; for exporting character outlines
      Font_SetColourTable       ; for ColourTrans to poke the Font Manager
      Font_CurrentRGB           ; for reading the current RGB settings
      Font_FutureRGB            ; for reading the future RGB settings

New control codes in Font_Paint

      27,28             ; set new paint matrix
      19                ; 19,r,g,b,R,G,B,max = ColourTrans_SetFontColours

(Existing ones):

      0, 10, 13         ; terminator
      9, 11             ; horizontal / vertical movement
      17, 18            ; colour change
      21                ; comment
      25                ; underline
      26                ; font change

New definition of Font_Paint

Font_Paint
In: R0 = not used (if R2 bit 8 clear)

        R0 = initial font handle (1..255) or 0 => current (if R2 bit 8 set)
        R1 -> string
        R2 = flags:
            bit 0 set => use justification coordinates (bit 5 must be 0)
            bit 1 set => use rubout box coordinates
            bits 2,3 ignored
            bit 4 set => coords are OS units or 1/256 OS unit, else 1/72000"
                         (OS units if R2 bits 5,6=0, else 1/256 OS unit)
            bit 5 set => use R5 as indicated below, else PLOT coords
            bit 6 set => use R6 as indicated below
            bit 7 set => use R7 as indicated below
            bit 8 set => R0 = initial font handle or 0 (else ignored)
            bit 9 set => perform kerning on the string
            bit 10 set => writing direction is right to left (else left to right)
            bits 11..31 reserved (must be 0)
        R3,R4 = start coordinates (units depend on R2 bits 4,5)
        R5 -> coordinate block (if R2 bit 5 set):
            R5!0,4 = additional x,y offset on space (note R2 bits 0,4)
            R5!8,12 = additional x,y offset between each letter (note R2 bit 4)
            R5!16,20,24,28 = rubout box coordinates (note R2 bits 1,4)
        R6 -> transformation matrix (if R2 bit 6 set)
            R6!0..R6!12 = fixed point multipliers
            R6!16,R6!20= translation (units depend on R2 bits 4,5)
            unit matrix = [1<<16,0,0,1<<16,0,0]
        R7 = length of string (if R2 bit 7 set)

In the RISC OS 2.50 implementation, if R2 bits 5 or 6 are set, the Font Manager will return an error if R2 bit 4 is set. This is because the new coordinate system will not be implemented until RISC OS 3.00.

Note that the character at [R1,R7] may be accessed, to determine the character offset due to kerning (which in turn affects the underline width). This will not be a problem if the string has a terminator, and the R7=length facility is only used to extract substrings.

If R2 bit 5 is clear, the justification and rubout box coordinates are taken from the previous graphics cursor positions, which are supplied in OS units and rounded by the MOS to the nearest pixel. In this case, the justification y-coordinate is ignored (since it is too inaccurate), and the start y-coordinate is used instead. The rubout box coordinates are also treated as inclusive, as for graphics window setting, whereas when they are in the block pointed to by R5, the fill rule is as for Draw_Fill of full interior and interior boundary pixels, ie. fill if the pixel centre is enclosed.

If R2 bit 5 is set, then R2 bit 0 must be unset (the 'justification' is provided by the x,y offsets in the first 4 words in the coordinate block, rather than by a target point). Left-justification can be achieved by simply setting these 4 words to 0.

If bit 6 is set, R6 -> transformation matrix to use at the start. Subsequent matrices in the string alter the matrix to the specified value, rather than being concatenated with any previous matrix. Matrix changes within the string are made using one of the following control sequences:

                27, <align>, m1, m2, m3, m4
             or 28, <align>, m1, m2, m3, m4, m5, m6

where <align> means "advance until pointer is word-aligned". The equation for this is:

        pointer := (pointer + 3) AND NOT 3

m1..m4 are little-endian 32-bit signed numbers with a fixed point at bit 16, ie. 1 is represented as 1 << 16, or 65536.

m5 and m6 are the offsets, which are in 1/72000" (even if R2 bit 4 is set). These values are assumed to be 0 if the 27,m1..m4 code is used.

To restore the unit matrix, use 27,<align>,65536,0,0,65536.

Note that underlining and rubout do not work correctly if the x-axis is transformed so that it is no longer on the output x-axis, or has its direction reversed. The effect when doing this should NOT be relied on.

If bit 10 is set, then text is written right to left, rather than left to right. In this case the width of each character is subtracted from the position of the current point before painting the character, rather than the width being added after painting it. Rubout and underline are also filled in from right to left.

When kerning, the kern pairs stored in the metrics file indicate the left and right hand characters of a pair, and the additional offset to be applied between the characters if this pair is found. Note that if the main writing direction is right to left, then the right hand character is encountered first, and the left hand one is encountered next.

Subpixel scaling:

This is quite simple if neither x or y scaling is performed, and also if both x and y scaling is performed - the subpixel scaling directions relate to the output device axes.

When just horizontal or just vertical subpixel scaling is performed, it is sometimes necessary to swap over the sense of which is h and which is v, in order to determine the 'size' of the font.

This goes for the other FontMax<n> thresholds too, such as FontMax2, which determines whether characters should be anti-aliased. FontMax3 determines whether characters should be cached or not, and this must relate to the amount of memory taken up by the bitmaps.

Scaffolding:

Clearly it is not possible to apply scaffolding to characters which are transformed such that its new axes do not lie on the old ones. However, if the axes are mapped onto each other (eg. a scale, rotation or reflection about an axis or 45-degree line) then scaffolding can still be applied. This can involve swapping over the x and y scaffolding. If a font is sheared, then scaffolding may be applied in one direction but not the other.

Bounding boxes:

The bounding box of a transformed character cannot be determined purely by transforming the original bounding box of the character outline, since bounding boxes are axis-aligned rectangles, and character outlines are not, so the bounding box of the transformed character is typically smaller than that of the transformed bounding box.

Taking the bounding box of the transformed original bounding box is sufficient to work out a large enough box for outline->bitmap conversion, since not much memory is wasted (only one character is done at a time, and the character is 'shrink-wrapped' after conversion).

Bitmap fonts:

If a font has an encoding applied to it, then Font_Paint looks inside <fontname>.<encoding> to find the bitmap files. This is because bitmap files are specific to one encoding.

Note that Font_MakeBitmap also generates its bitmap files inside the appropriate encoding subdirectory.

If the font has no encoding applied, the bitmap files are inside the font directory, as before.

Note that this means that encoding names must not clash with any of the filenames that normally reside within font directories, ie:

        IntMetrics[<n>]         ; <n> is optional and the prefix is
        Outlines[<n>]           ; truncated so it all fits in 10 characters
        x90y45
        b<n>x<n>                ; <n> is a number from 1..9999
        f<n>x<n>

Font_ScanString

This is similar to Font_Paint above, but there are extra bits in R2 to do with returning results.

Font_ScanString
In: R0 = not used (if R2 bit 8 clear)

        R0 = initial font handle (1..255) or 0 => current (if R2 bit 8 set)
        R1 -> string (terminated by 0, 10 or 13)
        R2 = flags:
            bits 0..3 reserved (must be 0)
            bit 4 set => coords are 1/256 OS unit, else 1/72000"
            bit 5 set => use R5 as indicated below
            bit 6 set => use R6 as indicated below
            bit 7 set => use R7 as indicated below
            bit 8 set => R0 = initial font handle or 0 (else ignored)
            bit 9 set => perform kerning on the string
            bit 10 set => main writing direction is right to left, else left to right
            bits 11..15 reserved (must be 0)
            bit 16 reserved (must be 0)
            bit 17 set => return nearest caret position, else width of string
            bit 18 set => return bbox of string
            bit 19 set => return matrix applying at end of string in [R6..]
            bit 20 set => return number of split characters in R7
            bits 21..31 reserved (must be 0)
        R3,R4 = max x,y-coord offset before termination
                (or offset of mouse click for caret search)
        R5 -> coordinate block (R2 bits 0,1 => whether used)
            R5!0,4 = additional x,y offset on space
            R5!8,12 = additional x,y offset on each character
            R5!16 = split char (-1 => no split char)
        R6 -> transformation matrix (if R2 bit 6 set)
              or buffer for returned matrix (if R2 bit 19 set)
        R7 = length of string (if R2 bit 7 set)
Out:R1 -> point where scan terminated
        R3,R4 = x,y offset to termination point (or caret position)
        [R5] updated as follows (if R2 bits 5 and 18 set):
             R5!20,24,28,32 = string bbox (note R2 bit 4)
        [R6] updated (if R2 bit 19 set):
             R6!0,4,8,12,16,20 contain matrix at point where scan terminated
        R7 = number of split characters encountered (if R2 bit 20 set)

In the RISC OS 2.50 implementation, the Font Manager will return an error if R2 bit 4 is set. This is because the new coordinate system is not yet implemented.

Note that the character at [R1,R7] may be accessed, to determine whether it is a 'split character'. It may also make a difference to the string width, if kerning is enabled.

If R5!16 = -1, ie. there is no split character, then the number of 'split characters' returned in R7 if R2 bit 20 is set is the number of non-control characters encountered, ie. those whose codes are 32 or more and which are not part of a control sequence.

When scanning for termination (as opposed to finding the nearest caret position), the scan continues until the current offset is less than or greater than the limit supplied, depending on the sign of that limit. In other words, if R3 is negative on entry, the scan continues until the x offset is less than R3, while if R3 is positive, the scan continues until the x offset is greater than R3. Note that this is incompatible with the old Font_StringWidth call, which always continued until the x,y offsets were greater than R2 or R3 (Font_StringWidth still works in the old way, to ensure compatibility).

Where bit 10 is set, ie. the main writing direction is right to left, one would normally supply a negative value of R3.

If a bounding box is returned, this does not include the area occupied by underlining or rubout.

This SWI replaces the following deprecated (still supported, but not recommended) SWIs:

        Font_FindCaret
        Font_FindCaretJ
        Font_StringWidth
        Font_StringBBox

Font_CurrentRGB

This SWI allows the setting of the RGB foreground and background colours after calling Font_Paint to be read.

        Font_CurrentRGB
        Out:    R0 = font handle
                R1 = background font colour
                R2 = foreground font colour
                R3 = max colour offset (0 => mono, else anti-aliased)
        Error:  "Undefined RGB font colours" if colours not set using RGB

Font_FutureRGB

This SWI allows the setting of the RGB foreground and background colours after calling Font_ScanString, Font_StringWidth, Font_StringBBox, Font_FindCaret or Font_FindCaretJ to be read.

        Font_FutureRGB
        Out:    R0 = font handle
                R1 = background font colour
                R2 = foreground font colour
                R3 = max colour offset (0 => mono, else anti-aliased)
        Error:  "Undefined RGB font colours" if colours not set using RGB

Font_ReadColourTable


        Font_ReadColourTable
        In:    R0 = &44524F57 ("WORD") => R1 -> 16-word table to contain results
                                     else R1 -> 16 byte array to contain results
        Out:   [R1..] = output data for each of the 16 anti-aliasing colours
               If R0="WORD" on entry, then the values are in the top <bpp> bits of each word
                                      else they in the bottom <bpp> bits of each byte
               where <bpp> denotes the number of bits per pixel in the current output mode

Font_SetColourTable

This SWI allows the ColourTrans module to poke colours directly into the Font Manager's colour table to determine preceisely which colours are used for font rendering.

It also specifies the exact (24-bit) colours which the current colours are supposed to represent, and so allow ColourTrans_SetFontColours to tell the Font Manager the colours which the caller regards as being represented by the current colours.

        Font_SetColourTable
        In:     R0 = new font handle (0 => leave unchanged)
                R1 -> 16-word table of pixel values, shifted to top of word (background..foreground)
                R1 = 0 => don't set table (just use RGB values)
                R2 = true 24-bit RGB of background colour
                R3 = true 24-bit RGB of foreground colour
                R4 = max colour offset (as passed to ColourTrans_SetFontColours)
                     (0 => use 1-bpp bitmaps, else use 4-bpp bitmaps)
        Error:  "Invalid font colour" if pixel values too big

ColourTrans_SetFontColours actually works out what the colours should be, then calls Font_SetFontColours (thus invalidating the Font Manager's internal idea of what the current RGB colours are), and then calls Font_SetColourTable with R1=0, R2,R3,R4 = parameters as passed to ColourTrans_SetFontColours. If output is directed to a buffer, this allows Font_Paint to get the colours of the resulting DrawFile objects right.

In fact in 256-colour modes things are even more complex: ColourTrans_Set/ReadFontColours chooses a pseudo-palette entry to use, then calls Font_SetPalette to set up the font data: the Font Manager then calls ColourTrans_SetTable to set up its own colour table. ColourTrans then calls Font_ReadColourTable to find out what this data is, and stashes it in its own cache, along with the corresponding background, foreground and max colour offset. On subsequent calls, if the same RGB colours are requested, ColourTrans calls Font_SetFontColours to set up the correct current colour, and uses Font_SetColourTable to restore the colour data more quickly.

Note that this SWI should not called by application programs, since the Printer Drivers cannot deal correctly with it. Use ColourTrans_SetFontColours or Font_Paint 19 sequences instead.

Font_SetPalette

This now takes one extra parameter:

        In      R6 = &65757254 ("True") => use all 24 bits of R3,R4

If R6 is equal to this magic word, the RGB values in R3 and R4 are treated as true 24-bit palette values, where white = &FFFFFF00 (not &F0F0F000).

Otherwise, for compatibility, palette values are processed as follows:

        R3 := (R3 AND &F0F0F000) OR ((R3 AND &F0F0F000) >> 4)
        R4 := (R4 AND &F0F0F000) OR ((R4 AND &F0F0F000) >> 4)

Thus the bottom nibbles of each gun are set to be copies of the top nibbles.

The Font Manager now calls ColourTrans_SetPalette to set palette entries in non 256 colour modes, and calls ColourTrans_ReturnColourNumber to match RGB values with logical colours in modes with 256 colours or more.

If ColourTrans is not loaded, it calls PaletteV to set the palette, and if PaletteV is not intercepted, it finally calls OS_Word 12 to set the palette.

Font_ReadFontMetrics

This SWI allows the new metrics information held in a font's IntMetrics file to be accessed directly.

      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

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)

R5 -> Kern data:

                Kern pair hash table index is given by:
                        (first letter) EOR (second letter ROR 4)
                where the rotate happens in 8 bits.
        256 * 4 offset of first kern pair from table start
        4       offset of end of all kern pairs from table start
        4       flag word:
                        bit 0 set => no bboxes
                        bit 1 set => no x-offsets
                        bit 2 set => no y-offsets
                        bits 3..30 reserved (ignore these)
                        bit 31 set => 'short' kern pairs
                kern data follows
        The table indicates the point in the list of kern pairs following
        the table to start looking for a given kern pair.  The entries are
        consecutive, so each list finishes as the next one starts.
        The kern pairs consist of the code of the first letter of the kern
        pair (the second letter can be deduced from this and the hash
        index), followed by the x-offset (if flags bit 1 is clear) and the
        y-offset (if flags bit 2 is clear).
        If bit 31 of the flag word is set, then the letter code is combined
        with the first offset word as follows:
                bits 0..7 = character code
                bits 8..31 = x or y-offset
        If bit 31 is clear, then the letter code is contained in the first
        word, followed by the x-offset word (if flags bit 1 is clear) and
        the y-offset word (if flags bit 2 is clear).
        Note that if flag bits 1 and 2 are both set, then it is illegal for
        there to be any kern pairs.
        The offsets are in millipoints.

Once the kern offsets are obtained, they can be inserted into a Font_Paint string as character 9 and 11 move sequences.

**** Not yet implemented ****

Font_Caret

Font_Caret

    In:     R0 = colour to EOR onto screen
            R1 = height (units depend on R2 bit 4)
            R2 = flags:
                bits 0..3 unused
                bit 4 set => coordinates are OS units, not 1/72000"
                bit 6 set => use R6 as indicated below
                bits 5,7..31 reserved (must be 0)
            R3,R4 = start coordinates (units depend on R2 bit 4)
            R6 -> transformation matrix (if R2 bit 6 set)
                R6!0..R6!12 = fixed point multipliers
                R6!16,R6!20 = translation (units depend on R2 bit 4)
                unit matrix = [1<<16,0,0,1<<16,0,0]

If R2 bit 6 is set, then, the caret can be transformed. This will be useful for applications to allow text round a circle to be edited.

**** Not yet implemented ****

Font_CharBBox

Font_CharBBox

    In:     R0 = font handle
            R1 = character code, or -1 => return font bbox
            R2 = flags:
                    bits 0..3 ignored
                    bit 4 set => return OS unit bbox, else 1/72000"
                    bits 5..31 reserved (must be 0)
Out: R1-R4 = bbox of char or font (x0,y0,x1,y1)
                    x0,y0 inclusive, x1,y1 exclusive

The only change is that setting the character code to -1 causes the values for the whole font to be returned. The current SWI Font_ReadInfo should be deprecated, as it only allows the font bounding box to be read in OS units.

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

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

************************ not yet implemented ****************************

The font "name" string can also 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 it is a font identifier.

The strings following qualifiers must not contain "\", as this denotes the start of the next qualifier.

The possible qualifiers are:

        \F<identifier>  font identifier (as for old Font_FindFont)
        \f<t> <name>    territory (country) number of font name, followed by
                        the font name in the alphabet of the territory
                        (terminated by end-of-string).
        \E<identifier>  encoding identifier
        \e<t> <name>    territory number of name, then encoding name
        \M<matrix>      transformation matrix to apply to this font
      <identifier> is a string of ascii characters, in the range 33 to 126
                   inclusive, which must represent a legal filename
                   (although it can contain "."s).
            <name> is the name of the font/encoding, expressed in the
                   language of the current territory, and using the alphabet
                   of the current territory.
               <t> is the territory number of the current territory, ie. the
                   language in which the font/encoding name is expressed.
          <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 s/he is in the same territory).

The "\E" (encoding) field indicates the appropriate encoding for the font itself. This field is only supplied by Font_DecodeMenu if the font is deemed to be a 'language' font, ie. one whose encoding depends on the territory. Other fonts are thought of as "Symbol" fonts, which have a fixed encoding.

Note that Font_DecodeMenu will return a font identifier of the following form:

                \F<fontid>\f<territory> <fontname>

To apply a particular encoding to a font, remember to eliminate the existing encoding fields (if present) first. Note that no field is allowed to contain a "\".

                \E<encid>\e<t> <encname>\F<fontid>\f<t> <fontname>

Note that since <fontid>\f<t> <fontname> is also accepted by Font_FindFont, when prepending "\E<encid>\e<t> <encname>" on the front, you should also put "\F" on the front of the original string if it did not start with "\".

In BASIC, this looks like:

        REM original$ is the original string passed to Font_FindFont
        REM encoding$ is the string returned from Font_DecodeMenu
        REM           typically "\E<enc_id>\e <territory> <enc_name>"
        REM result is the new string to be passed to Font_FindFont
        DEF FNapply_encoding_to_font(original$,encoding$)
        IF LEFT$(original$,1)<>"\" THEN original$ = "\F"+original$
        original$ = FNremove(original$,"\E")
        original$ = FNremove(original$,"\e")
        = encoding$ + original$
        REM this function removes the specified field from the string
        REM eliminates all characters from b$ to "\"
        DEF FNremove(a$,b$)
        LOCAL I%,J%
        I% = INSTR(a$,b$)
        IF I%=0 THEN =a$              :REM nothing to eliminate
        J% = INSTR(a$+"\","\",I%+1)   :REM searches from I%+1
        = LEFT$(a$,I%-1)+MID$(a$,J%)

Note that it is not strictly necessary to remove the original encoding fields from the font identifier, since an earlier occurrence of a field overrides a later one, but if this is not done then the length of the total string will continue to grow every time an encoding is altered.

Font_ReadDefn

Font_ReadDefn

    In:     R0  = font handle
            R1 -> buffer to fill in
            R2  = &4C4C5546 ('FULL')

Out: [R1] = name of font (if R2 =&4C4C5546 then contains encoding and matrix aswell.

            R2  = x point size *16
            R3  = y point size *16
            R4  = horizontal resolution
            R5  = vertical resolution
            R6  = age of font
            R7  = usage of Font

This SWI has been extended to accept 'FULL' in R2, this is used to indicate that the buffer should be returned containing the matrix and encoding information specified on Font_FindFont.

This call is used by the printer drivers when trying to re-cache a font for printer use.

*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_MakeBitmap

Same as before, except that if the font has an encoding applied to it (ie. if there was a "/E" qualifier in the Font_FindFont string, or if this is a 'language' font, which varies in encoding according to the territory), then the bitmaps are held inside a subdirectory of the font directory.

The subdirectory is <prefix>.<fontname>.<encoding>.

Note that the Font Manager's Font_Paint stuff also looks inside this directory to find the bitmaps.

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
             bit 22 = 1 => return list of encodings, else return list of fonts
             bits 23..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/encoding names/identifiers

                     font/encoding identifier/name is invalid in this case
                     font/encoding 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/encoding 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/encoding 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.

By setting bit 22 of R2, it is possible to return a list of the encodings known to the font manager. These are text files contained in <font prefix>.Encodings.<encoding id>, and are used to specify the encodings of the 'language' fonts (as opposed to the 'symbol' fonts, whose encoding is fixed).

Font_DecodeMenu

In R0 = flag word: bit 0 = 0 => this is a font menu

                          bit 0 = 1 => this is an encoding menu
                          bits 1..31 reserved (must be 0)
          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..] = returned string (if R3<>0 on entry)
          R4 = size of buffer required to hold output string
             = 0 => no font selected

Bit 0 of R0 determines whether this is the font menu or the encoding menu that is being decoded.

In either case, the format of the returned string depends on whether the names of the fonts/encodings have been specified in a Messages<n> file inside the font directory - the name field is not present if the Font Manager has worked out the list of fonts/encodings by scanning the directory instead.

    Font id, no name:       \F<font id>
    Font id, with name:     \F<font id>\f<territory> <font name>
    Encoding, no name:      \E<encoding id>
Encoding, with name: \E<encoding id>\e <territory> <encoding name>

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_ReadEncodingFilename

In R0 = font handle

          R1 -> buffer to receive prefix
          R2 = length of buffer
Out R0 -> encoding filename (in buffer)
          R1 -> terminating 0 of filename
          R2 = bytes remaining in buffer
Error "Buffer overflow" if buffer too small

This SWI allows the filename of the encoding file used for a given font handle to be read. It is primarily useful for PDriverPS to gain access to the file of identifiers that defines an encoding, in order to send it to the printer output stream.

The filename depends on whether the font has a 'public' or 'private' encoding (public encodings apply to 'language' fonts, as described in Font_ListFonts, while 'private' encodings are not used by the Font Manager, and simply describe the PostScript names for the characters in the font).

        public encoding : <font prefix>.Encodings.<encoding>
        private encoding: <font prefix>.<font name>.Encoding

*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.

Font Manager improvements for RISC OS 3.00

Not to be implemented in RISC OS 2.50:

Font_Paint

Note that R2 bit 5 has a dual function: if set, it causes the justification and rubout box coordinates to be taken from the block pointed to by R5 (if required), and it also causes the units if bit 4 is set to be 1/256th of an OS unit, rather than OS units. Note that R5 is simply a flag if R2 bit 5 is set and bits 0,1 are clear, ie. 0 => coords are in OS units if R2 bit 4 set, 1 => coords are in 1/256th of an OS unit if R2 bit 4 is set.

This goes for all coordinates specified in Font_Paint, including the rubout box and any matrices with non-0 offsets.

Font_ScanString

If R2 bit 4 is set on entry, then coordinates are supplied in 1/256th of an OS unit, rather than 1/72000".

If R2 bit 16 is set on entry, then coordinates are returned in 1/256th of an OS unit, rather than 1/72000".