C for Yourself - part 43

Steve Mumford explains how you can exert greater control when plotting fonts

We're now at a stage where we can paint a string of text to the screen in a chosen font without too much trouble. As I mentioned last time round, this can be handy but it's definitely not the end of the story. This month I'll introduce some of the other SWI calls available for more sophisticated manipulation of text prior to display.

First, it's important to be able to convert between OS units and millipoints, as some of the more flexible font manipulation commands, such as Font_ScanString, only take input in the form of the latter. Two SWI calls are provided to ease this process, and these are Font_ConverttoOS and Font_Converttopoints.

They're simple to use - just set registers 1 and 2 to the x and y coordinates you wish to translate, and a call to the appro- priate SWI will convert and return the values in the same registers. The default 'exchange rate' is 400 millipoints per OS unit, but this can be altered if you're really desperate.

Font_StringWidth can also be particularly useful - its function is to calculate the length of a string as it would appear on the screen when plotted in the current font. If you know the dimensions of the area you want to paint the text into, this call can predict where you'd need to split a long string to fit it into the available space. It takes values in registers 1 to 5 - the first is a pointer to the string you wish to analyse, the second and third hold the maximum x and y sizes of the area the text is to fit into, the fourth holds the numeric code of the character at which a line-split may take place (normally '32', which represents a space) and the fifth stores the number of characters you wish to process - normally the length of the string.

Armed with this information, Font_StringWidth will take a note of the font currently in use and scan through the given string, character by character, until one of several criteria is met, taking note of the positions of the assigned 'split' characters on the way. Obviously, if the string comes to an end before its on-screen size exceeds those values in R2 and R3, the call will terminate and will calculate sizes based on the whole string.

However, if the predicted size of the painted text exceeds those given in R2 and R3, the function will return eariy. In this case, the SWI will return the lehgth and the dimensions of the string as it would be plotted, up to but not including the last successfully scanned 'split' character. In most situations, a space will be used as the separation character, so Font_StringWidth will just discard the last interrupted word.

On returning, the call will give you five values, again in registers 1 to 5. R1 is a pointer to the last character that was reached in the scan, R2 and R3 give the x and y offsets that would result if the string was actually printed to screen, R4 holds the number of occurrences of the 'split' character specified, and R5 gives the position of the character within the string at which the scan stopped - the character before the last 'split' character if the text had to be broken over more than one line.

One way of using this call is to partition a long bit of text into smaller chunks that will all fit within a certain width - by taking the returned values and re-submitting the modified string, it's possible to work through and format a complete column of text.

Font_ScanString is a more powerful relative of the above SWI, and is only available in RISC 05 3 or later. It closely minors the format of Font_Paint, so it can give details about most of the effects of a Font_Paint call without having to display the text on-screen.

As well as more sophisticated termination criteria, it can deal with text being painted in different directions and help you discover where to insert a caret following a mouse-click within a region of text. In the later versions of the operating system, this call replaces Font_StringWidth as well as a couple of other system calls, and provides all their functionality within one SWI.

Source: Acorn User - 187 - November 1997
Publication: Acorn User
Contributor: Steve Mumford