Proportional vs. Monospace

Die Typografie unterscheidet zwischen proportionalen Schriftarten (variable Breite) und Schiftarten mit fester Breite (monospace). Das Lernpaket beschäftigt sich nur mit Schriftarten fester Breite. Wie aber geht man an die Sache heran wenn man eine proportionale Darstellung von Texten auf einem Display abbilden möchte?
Darstellungsarten bei Schriften
Mehrere Lösungswege
Prinzipiell gibt es zwei Herangehensweisen. Die erste setzt voraus, dass bereits in der Font-Datei selbst die Informationen über die Zeichenbreite enthalten sind. So wird hier neben der Bildinformation zusätzlich die Breite hinterlegt. Die Zeichenfunktion wertet diese Information aus und kann so Zeichen variabler Breite ausgeben. Hier ein Beispiel:
0x03, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x00,  // Code for char i
                    
Jedes Zeichen hat für die Darstellung eine maximale Breite von 5 Pixel. Das erste Byte (3) zeigt an, dass nur die ersten drei Bytes gezeichnet werden sollen. (0x00, 0x7D, 0x00)
Lösung mit minimalem Aufwand
Die zweite Möglichkeit ist, einen bestehenden Font mit fester Breite bei der Darstellung auf seine sichtbaren Bereiche zu reduzieren. Die Zeichenfunktion erkennt leere Bereiche und überspringt sie einfach. Dazu sind folgende Änderungen im Code nötig.
void Display::drawString(byte x, byte y, const char *c, boolean proportional) {
  if(y > HEIGHT) {
    return;
  }
  byte page = y/8;
  do {
    char character = c[0];
    if (! character)
      return;
      
    for (byte i=0; i<CHARACTER_WIDTH; i++ ) {
      word charBuffer = pgm_read_byte(font7x5+(character*6)+i) << y%8;
      if (proportional && charBuffer == 0) {
        continue;
      }
      videoBuffer[x+(page*WIDTH)] |= charBuffer;
      videoBuffer[x+(WIDTH*(page+1))] |= charBuffer >> 8;
      x++;
    }   
    if (proportional) {
      x=x+1;
      if (character == ' ') {
      x++;
      } 
    }
  } 
  while (c++);
}
Leere Stellen "charBuffer == 0" werden mit einem "continue" übersprungen. Zusätzlich wird nach jedem Zeichen ein Abstand mit der Breite von einem Pixel eingefügt (x=x+1). Bei einem Leerzeichen wird auf zwei Pixel erhöht (x++).
Darstellungsart auswählen
Die Darstellungsart wird einfach über einen weiteren Übergabeparameter (boolean proportional) beim Aufruf der Funktion gewählt. "1" zeigt eine proportionale Darstellung an. "0" ergibt eine Darstellung in fester Breite. Der Code für die oben gezeigte Anwendung sieht folgendermaßen aus:
#include "Display.h"
#include "SPI.h"

Display lcd = Display();

void setup() {
  lcd.init(20);
  lcd.clearVideoBuffer();
  lcd.drawString(0, 0, "Proportional", 1);
  lcd.drawString(50, 8, "vs. MONOSPACE", 0);
  lcd.drawString(0, 40, "Lorem ipsum dolor sit", 1);
  lcd.drawString(0, 55, "Lorem ipsum dolor sit", 0);
  lcd.show();
}

void loop() {
}
Links und Download: