A font file is a data structure which contains the bitmap image data for a complete ASCII character set ranging from ASCII 32 ($20), the space, upto ASCII 126 ($7E), the tilde.
GEOS Font files are created using the GEOS-specific Variable Length Indexed Record file structure.
An actual font of a single point size is written sequentially to the file as a self contained VLIR record. In most cases, the records are written so that a 10 point font file would be written to record #10 of the file, while a 14 point version of the same font would be written to record #14. (The appearence of Font Editor V2.4, V2.5, and Font Monster have allowed a font to be saved in any of the file's records.)
@The File Header
The first discussion will be of the differences in the file's header block which are unique to font files.
At offset 97 ($61) you will find a table of upto 15 words. These words are the record size table for each of the fonts contained in the file. The order of the entries is the same as the appearence of records in the file.
An application can use this table to detrmine if the font it wishes to load will fit. This may be easier in some cases than trying to read the file and merely testing for an overflow error.
At offset 128 ($80) you will find a word-sized constant which is the font's own unique identification number. With the scores of user-written fonts available, some fonts may wind up having the same ID. (Even BSworks' own Font Pack I had a bug where two of the fonts had the same ID.)
The ID word only uses the lower ten bits to contain the value. This allows us a maximum value of 1023.
The ID number is used to permanently identify which font is being used, indenpendent of the font filename. When an application seaches for a font on disk, it uses the ID, not the name. The drawback being that of two fonts using the same ID, only the font appearing first on disk will be used.
At offset 130 ($82) you will find an additional table of upto 15 words. This is the point size table for the file.
Upto 15 words are used to indicate the available point sizes in order of appearence. The words are structred as follows:
Bits 0-5 are used to indicate the size, in points, of the font. Since only six bits are used, the largest available point size is 63.
Bits 6-15 are a copy of the unique font ID number. The number is the same, but merely shifted left by six bits.
@The Font Bit Stream
Next we will discuss the data contained within the file records.
Unlike the normal Commodore 64/128 character sets, the GEOS fonts are stored as packed bit streams. This means that each font has been stored as bitmapped scanlines, one scanline per 'point' (a nine point file would have nine scanlines, or bit streams) with the topmost scamline appearing first, followed by as many more as needed.
If a character happens to be less than eight bits wide, then the first few bits of the next character will be stored in the bits unused by the current character, as per the following example:
Before the start of the font bit streams is a small data table that tell the system all it needs to know about the font itself.
The table format is as follows:
.BYTE $XX - The baseline. This is defined as the number of the scanline
Pabove
the underline, where the top scanline is numbered zero. The maximum value you should give the baseline is equal to one less than the current point size, or the number of the last scanline of characters. Should this maximum be used, the font will never appear with an underline.
.WORD - The number of bytes in
Peach
bitstream.
.BYTE - The point size of the font, equal to the number of bit streams.
.WORD - Offset pointer to the start of the character locator table (normally 8).
.WORD - Offset pointer to the start of the first bit stream (normally 202).
.WORD table - Locator table. Offset pointer to the position of the first
Pbit
of each character in the bit stream, plus one dummy entry to the pixel beyond the last character.
Beyond the locator table is the start of the bit streams. If a bit stream should end in the middle of a byte, the rest of the bits in that byte are ignored. Each bit stream starts in a new byte to simplify printing calculations.
To calculate the width of a character, all you need to do is find the start of the
Pnext
character, then subtract the start of the character you are interested in. The result is its width in bits. It is for this reason that a dummy entry is appended to the locator table, so that the last charcter width can be calculated.
@The Empty Character
Each character set should also have one more character appended to the end, beyond ASCII 127, the tilde. This is the 'empty character'. Its sole purpose is to be used for erasing already drawn characters.
This character is defined as being a space character with a width equal to the width of the widest character in the font.
In order to delete a drawn character, a CHR$(8) should be sent to PutChar. The PutChar routine traps this character and chages it to print a CHR$(127). Instead of using the actual width of the empty character, PutChar uses the value of the width for the last character drawn, stored in LastWidth ($8807). The result is that a properly sided space is drawn.
It is up to the application in question to backup the print position to start over the character to be erased before trying to delete it.
@BSW 9
The built in BSW 9 font has one more special character appended to it, CHR$(128). This is a special character used to display the familiar
logo.
The strange thing is that for fonts without this logo character, PutChar traps it and prints, instead two characters: 'C' and '='.
To use a font in your own program, all you need to do is load pseudoregister r0 ($0002) with the start address of the font, then use the system call 'LoadCharSet'.
-Joe Buckley (71570,2600)
-GEOS Section Leader, CompuServe CBMPRG forum
@Note:
Material derived from an article by William Coleman published in geoWorld V1I8, November 1987.