Pixel Fonts

Schriftarten (auch “Fonts” genannt) sind heute eine komplexe Sache. Alles ist vektorisiert und die Zeichen orientieren sich an mehreren Linien um Schleifen Punkte und Striche auf der richtigen Höhe im Verhältnis zu den anderen Zeichen zu setzen.

Früher hatten wir feste Schriftarten, die es in ein paar Größen gab und in denen Zeichen für Zeichen und Pixel für Pixel fix gespeichert waren.
Denn so etwas kann man nämlich sehr leicht selbst implementieren.


Als Minimalist bin ich immer wieder schockiert, wenn man die Aufgabe:

Wir müssen auf ein Foto noch eine Information wie Ort und Datum draufdrucken.

so interpretiert, dass man eine zig-MB große Library mit unnötig komplexen Schriftarten und deren Lizenzen an sein Programm binden muss.

Ich verstehe natürlich, dass man in Falle der Internationalisierung nicht für jedes Zeichen von Runen bis Hieroglyphen alles selbst implementieren kann, doch gerade bei diesen 0815 Tasks wie z.B.: Datum auf ein Bild draufschreiben, hat man das auch selbst in einigen Minuten implementiert und damit jede Menge Abhängigkeiten gespart.

Und daher findet sich eine solche Pixel-Font auch im GATE Projekt.

Pixel Bits als C struct

C unterstützt ein Feature, auf das gerne vergessen wird: Bitfelder.
Man kann in einer Struktur bei einem Integer angeben, wie viele Bits dieser belegen soll. Der Compiler legt dann die Bits in einen Datenblock zusammen und holt bei Zugriffen genau die richtigen Bits heraus.

Das kann man natürlich mit AND und OR Verknüpfungen auch selbst tun, doch mit Bitfeldern arbeiten wir so, als hätten wir einen Integer und der Compiler erledigt den Rest.

Das tolle dabei ist: Wir können dann mit einer struct quasi “Bits malen”, ohne kryptische Hex-Zahlen einsetzen zu müssen. Und wenn man ein Bit mit einem sichtbaren Pixel gleichsetzt, kann man so ein Zeichen visuell in Sourcecode abbilden.

Aus Byte-Sicht “schöne” Ausmaße hat eine 8x8 Pixel Schrift. Man definiert eine C struct für die Bit-Member einer Zeile und erstellt daraus ein C-Array von Zeilen um einen Buchstaben darstellen zu können:

 1typedef struct gate_font_char_row8_bits
 2{
 3  unsigned char c1 : 1;
 4  unsigned char c2 : 1;
 5  unsigned char c3 : 1;
 6  unsigned char c4 : 1;
 7  unsigned char c5 : 1;
 8  unsigned char c6 : 1;
 9  unsigned char c7 : 1;
10  unsigned char c8 : 1;
11} gate_font_char_row8_bits_t;
12
13static gate_font_char_row8_bits_t const font8x8_A[8] = {
14  { 0,1,1,1,1,0,0,0 },
15  { 1,0,0,0,0,1,0,0 },
16  { 1,0,0,0,0,1,0,0 },
17  { 1,1,1,1,1,1,0,0 },
18  { 1,0,0,0,0,1,0,0 },
19  { 1,0,0,0,0,1,0,0 },
20  { 1,0,0,0,0,1,0,0 },
21  { 0,0,0,0,0,0,0,0 }
22};

Man braucht zwar etwas Augen-Übung, aber dann kann man erkennen, dass die 1 Bits den Buchstaben A im Beispiel formen.

Jede gate_font_char_row8_bits_t Zeile belegt ein Byte (also 8 Bits), womit man die Struct auch nach unsigned char casten kann.

Und wenn man nun noch zwei Schleifen baut, die für y und x von 0 bis 8 laufen, reicht ein set_pixel() Aufruf um jene Pixel zu zeichnen, wo das aktuelle Bit auf 1 steht.
… fertig ist der Font-Renderer.

Mit dem Bitfield-Trick lassen sich somit Schriftarten ganz leicht direkt in den C Code einbetten.
Und das machen einige andere Libs (z.B.: aus der Arduino Welt) ebenfalls so.

Fazit

Ich finde es schade und teilweise dumm, dass Entwickler heute lieber 3 Tage im Netz nach einer Bibliothek suchen, die ein Datum auf ein Rasterbild schreiben kann, nur weil der Code per Copy & Paste integriert werden soll und dann eine 200 MB Runtime im Schlepptau hängt.

Es stimmt schon, dass nicht jeder das Rad neu erfinden soll, aber die Tatsache, dass so gut wie niemand mehr weiß und wissen möchte, wie man solche einfachen Aufgaben selbst löst, ist das andere Extrem, das ebenso schlecht einwirkt.

Ich füge meine Zeichen von A bis Z in groß und klein daher ins GATE Framework ein und wenn man diese Pixel-Font in einer App nicht benutzt, merkt das der Compiler und nimmt den Inhalt der statischen Bibliothek auch nicht weiter auf.

Jetzt kann ich z.B. die Fotos meiner Webcam, die als Sicherheitskamera umfunktioniert wurde, sofort mit Infos “signieren”, bevor sie ins Netz geschickt werden, ohne dass ich eine Font oder Zusatz-Lib mit ausliefern muss.