Font-formats recognized by the Linux kbd package: PSF fonts

Next Previous Contents

## 1. PSF fonts

PSF fonts come in two types: old (psf1) and new (psf2). A PSF font consists of (1) The header, (2) The font, (3) Unicode information.

## 1.1 The header

For psf1 this is

> `

>     #define PSF1_MAGIC0     0x36
>     #define PSF1_MAGIC1     0x04

>     #define PSF1_MODE512    0x01
>     #define PSF1_MODEHASTAB 0x02
>     #define PSF1_MODEHASSEQ 0x04
>     #define PSF1_MAXMODE    0x05

>     #define PSF1_SEPARATOR  0xFFFF
>     #define PSF1_STARTSEQ   0xFFFE

>     struct psf1_header {
>             unsigned char magic[2];     /* Magic number */
>             unsigned char mode;         /* PSF font mode */
>             unsigned char charsize;     /* Character size */
>     };

> `

For psf2 this is

> `

>     #define PSF2_MAGIC0     0x72
>     #define PSF2_MAGIC1     0xb5
>     #define PSF2_MAGIC2     0x4a
>     #define PSF2_MAGIC3     0x86

>     /* bits used in flags */
>     #define PSF2_HAS_UNICODE_TABLE 0x01

>     /* max version recognized so far */
>     #define PSF2_MAXVERSION 0

>     /* UTF8 separators */
>     #define PSF2_SEPARATOR  0xFF
>     #define PSF2_STARTSEQ   0xFE

>     struct psf2_header {
>             unsigned char magic[4];
>             unsigned int version;
>             unsigned int headersize;    /* offset of bitmaps in file */
>             unsigned int flags;
>             unsigned int length;        /* number of glyphs */
>             unsigned int charsize;      /* number of bytes for each character */
>             unsigned int height, width; /* max dimensions of glyphs */
>             /* charsize = height * ((width + 7) / 8) */
>     };

> `

The meaning is fairly clear from the field names. The fonts here are bitmap fonts (not, for example, vector fonts), and each glyph has a `height` and a `width`. The bitmap for a glyph is stored as `height` consecutive pixel rows, where each pixel row consists of `width` bits followed by some filler bits in order to fill an integral number of (8-bit) bytes. Altogether the bitmap of a glyph takes `charsize` bytes.

For psf1 the width is constant 8, so that the height equals the charsize.

The number of glyphs in the font equals `length`. For psf1 the length is constant 256, unless the `PSF1_MODE512` bit is set in the `mode` field, in which case it is 512.

The font is followed by a table associating Unicode values with each glyph in case (for psf1) the `PSF1_MODEHASTAB` bit is set in the `mode` field, or (for psf2) the `PSF2_HAS_UNICODE_TABLE` bit is set in the `flags` field.

The starting offset of the bitmaps in the font file is given by `headersize`. (This allows the header to grow, probably depending on `version`, without changes in the code.)

The integers in the psf2 header struct are little endian 4-byte integers.

## 1.2 The font

The actual bitmaps.

## 1.3 Unicode information

The bitmaps may be followed by a Unicode description of the glyphs. This Unicode description of a position has grammar

> `

>     <unicodedescription> := <uc>*<seq>*<term>
>     <seq> := <ss><uc><uc>*
>     <ss> := psf1 ? 0xFFFE : 0xFE
>     <term> := psf1 ? 0xFFFF : 0xFF

> `

where `<uc>` is a 2-byte little endian Unicode value (psf1), or a Unicode value coded in UTF-8 (psf2), and `*` denotes zero or more occurrences of the preceding item.

The semantics is as follows. The leading `<uc>*` part gives Unicode symbols that are all represented by this font position. The following sequences are sequences of Unicode symbols - probably a symbol together with combining accents - also represented by this font position.

Example: At the font position for a capital A-ring glyph, we may have (psf1):

> `

>          00C5,212B,FFFE,0041,030A,FFFF

> `

where the Unicode values here are LATIN CAPITAL LETTER A WITH RING ABOVE and ANGSTROM SIGN and LATIN CAPITAL LETTER A and COMBINING RING ABOVE. Some font positions may be described by sequences only, namely when there is no precomposed Unicode value for the glyph.

## 1.4 Historical

PSF stands for PC Screen Font. The psf1 format without Unicode map was designed by H. Peter Anvin in 1989 or so for his DOS screen font editor `FONTEDIT.EXE`. In Oct 1994 he added the Unicode map and the programs `psfaddtable`, `psfgettable`, `psfstriptable` to manipulate it - see `kbd-0.90`. Andries Brouwer added support for sequences of Unicode values and the psf2 format in Sep 1999 in order to handle Tibetan - see `kbd-1.00`.

Next Previous Contents