# PC Screen Font

PC Screen Font (kurz: PSF) ist ein einfaches binäres Dateiformat für Bitmap-Zeichensätzen. Es wird vor allem vom Linux-Kernel für die Textkonsole benutzt, ist aber nicht auf diesen Einsatzzweck beschränkt.
Es gibt zwei zueinander inkompatible Formatversionen. Der logische Aufbau ist gleich, aber die Kodierung unterscheidet sich stark.

## Version 1

PSF Version 1 hatte seine Ursprünge in dem Dateiformat, das H. Peter Anvin 1989 in seinem Font-Editor für MS-DOS benutzt hatte. Seine Fähigkeiten sind begrenzt, entsprechend den Fähigkeiten der VGA-Grafikkarte im Textmodus:
In dieser Version können nur Zeichensätze mit 8 Pixel breiten Zeichen definiert werden. Es werden Zeichensätze mit 256 oder mit 512 Zeichen unterstützt.
Dateien in diesem Format beginnen mit einem 4 Byte großen Header:
    PSF1 Header OffsetGrößeBedeutung 02Magic Number 36$_{hex}$, 04$_{hex}$ 21Font Mode: Bitfeld, das die Eigenschaften des Zeichensatzes definiert, wenn das entsprechende Bit gesetzt ist: Bit 0: Font enthält 512 Zeichen Bit 1: Font hat Unicode-Codierungstabelle Bit 2: Die Codierungstabelle enthält Zeichensequenzen 31Höhe eines Zeichens (=Größe eines Zeichens in der PSF-Datei)

## Version 2

Dieses Format kann beliebig große Zeichen speichern, auch die Anzahl der Zeichen im Font ist nun frei wählbar.
    PSF2 Header OffsetDatentypBedeutung 0uint8_t[4]Magic Number 72$_{hex}$, B5$_{hex}$, 4A$_{hex}$, 86$_{hex}$ 4uint32_tVersion. (bisher stets 0) 8uint32_tGröße des Headers (in Byte) 12uint32_tFlags (derzeit ist nur Bit 0 definiert, welches angibt, ob der Font eine Unicode-Tabelle enthält) 16uint32_tAnzahl an Zeichen im Font 20uint32_tGröße eines Zeichens (in Byte) 24uint32_tZeichenhöhe (in Pixel) 24uint32_tZeichenbreite (in Pixel)
Die 32-Bit-Werte sind im Little-Endian-Format gespeichert.

## Zeichendaten

Nach dem Header folgen die eigentlichen Zeichendaten. In PSFv1 entspricht jedes Byte genau einer Zeile mit 8 Pixeln. In PSFv2 werden die Zeilen gegebenenfalls von rechts mit Nullbits aufgefüllt, um auf eine ganze Anzahl von Bytes pro Zeile zu kommen.

### Beispiel PSFv1

Die bei vielen Linux-Distributionen mitgelieferte Font-Datei Uni1-Fixed16.psf beginnt (in Hexadezimaldarstellung) wie folgt:
Die ersten zwei Bytes 36 04 sind der PSF1-Header. Das Font Mode-Byte hat den Wert 03$_{hex}$, das bedeutet: Der Font enthält eine Unicode-Zeichentabelle und Zeichensequenzen. Das darauf folgende Byte hat den Wert 10$_{hex}$ = 16$_{dez}$ und gibt die Höhe der Zeichen in Pixel und in Byte an.
Es folgen daraufhin jeweils 16 Byte pro Zeichen, die die Pixeldaten enthalten:

### PSFv2

Der Font Lat7-TerminusBold22x11.psf enthält Zeichen der Größe 11 × 22 Pixel und liegt somit im Format PSFv2 vor:
Die ersten 4 Bytes 72 b5 4a 86 entsprechen dem PSFv2-Header. Die Kopfdaten sind:
* Version: 0
* Header-Größe: 32 Bytes (20$_{hex}$)
* Flags: 1 (=Font enthält Unicode-Tabelle)
* Anzahl der Zeichen: 256 (0100$_{hex}$)
* Größe eines Zeichens: 44 Byte (2c$_{hex}$)
* Höhe eines Zeichens: 22 Pixel (16$_{hex}$)
* Breite eines Zeichens: 11 Pixel (0b$_{hex}$)
Anschließend folgen ab Offset 20$_{hex}$ die Pixeldaten, mit jeweils 2 Byte pro Zeile:
Die Pixeldaten sind 44*256 = 11264 Bytes groß, belegen also in der Datei den Bereich von 0020$_{hex}$ bis 2c1f$_{hex}$, ab Offset 2c20$_{hex}$ beginnen die Unicode-Daten:
Diese bestehen aus Sequenzen von UTF-8-kodierten Zeichen, getrennt durch ein Byte mit dem Wert FF$_{hex}$, welches in UTF-8 nicht vorkommt. Der Erste Eintrag ist C2 A4, welches die UTF-8-Kodierung für U+00A4 ist, welches das allgemeine Währungszeichen ¤ ist.

## Unicode-Zeichentabelle

Die Unicode-Zeichentabelle gibt für jedes Zeichen im Font an, für welches Unicode-Zeichen oder Zeichenfolge es stehen soll. Das gestattet es, dass identisch aussehende Unicode-Zeichen (z. B. das lateinische A, das kyrillische А und das griechische Alpha) nur einmal im Font kodiert werden müssen.
Außerdem können Zeichen im Font enthalten sein, die in Unicode keinen eigenen Code haben, sondern nur über eine Sequenz von Unicode-Zeichen dargestellt werden können.
Die Unicode-Werte werden im PSFv1-Format als 16-Bit-Werte kodiert, sodass nur Zeichen aus der Basic Multilingual Plane unterstützt werden. PSFv2 kodiert die Werte in UTF-8 und kann so auch Zeichen jenseits von U+FFFF enthalten.