Schriften

Textausgaben sind essenzielle Funktionen einer Displaylösung. Neben der Benutzerführung und der Ausgabe unterschiedlichster Informationen, spielt eine differenzierte Formatierung, um Inhalte entsprechend ihrer Bedeutung hervorzuheben, eine große Rolle. Die µGL Bibliothek bietet leistungsfähige Klassen und Funktionen für die Textausgabe an.

Aufgabe

Es ist eine Anwendung zum Testen unterschiedlicher Schriftarten und Schriftstile zu entwickeln. Dabei sollen verschiedene Ausgabefunktionen genutzt werden.

Vorbereitung

Falls Sie nicht in der Vorgehensmodell-Ebene sind, navigieren Sie diese bitte an (nach oben). Falls das Projekt nicht mehr geöffnet ist, öffnen sie das SiSy UML-Projekt wieder. Legen Sie ein neues Klassendiagramm an und wählen Sie die Sprache ARM C++. Beachten Sie die Einstellungen für die Zielplattform STM32F4-Discovery. Beim Öffnen des Diagramms (rechte Maustaste, nach unten) laden Sie die Diagrammvorlage für eine ARM C++ Applikation mit Grafikdisplay ohne µGL.

(Mit installiertem Flash kann man an dieser Stelle ein Video in dieser Web-Seite ansehen.)

Selektieren Sie die Opration onStart der Klasse Application.

Ersetzen Sie möglicherweise vorhandenen Beispielquelltext durch folgenden Code:

onStart()
display.clearScreen();

Erstellen und übertragen Sie die Anwendung auf den Mikrocontroller.

Grundlagen zu Schriften

In der Bibliothek finden wir die Schriftarten (Fonts) in verschiedenen Paketen. Zum einen die Standardschriftarten im Paket UglFonts.

Zusätzliche Schriften sind im Paket UglFontExt enthalten. Durch die Aufteilung in verschiedene Paket kann der Umfang einer Anwendung übersichtlicher gehalten werden und es wird unnötiger Speicherverbrauch verhindert.

Eine Schrift besteht aus den eigentlichen Bitmustern für jedes Zeichen und einer Font-Struktur. Diesen Aufbau kennen wir bereits von icons und Bitmaps.

const unsigned char dataTableFontSmallPlain[] =
{
   0x55, 0x55, 0x55, 0x55, 0x55, 	//  (ascii=0)
   ...					// ...
   0x00, 0x00, 0x00, 0x00, 0x00, 	// 0x20 = Leerzeichen (ascii=32)
   0x00, 0x00, 0x4F, 0x00, 0x00, 	// ! (ascii=33)
   ...					// ...
   0x3E, 0x51, 0x49, 0x45, 0x3E, 	// 0 (ascii=48)
   0x00, 0x42, 0x7F, 0x40, 0x00, 	// 1 (ascii=49)
   0x42, 0x61, 0x51, 0x49, 0x46, 	// 2 (ascii=50)
   0x22, 0x49, 0x49, 0x49, 0x36, 	// 3 (ascii=51)
   ...					// ...
   0x7E, 0x11, 0x11, 0x11, 0x7E, 	// A (ascii=65)
   0x7F, 0x49, 0x49, 0x49, 0x36, 	// B (ascii=66)
   0x3E, 0x41, 0x41, 0x41, 0x22, 	// C (ascii=67)
   ...					// ...
   0x61, 0x51, 0x49, 0x45, 0x43, 	// Z (ascii=90)
   ...					// ...
   0x00, 0x28, 0x54, 0x54, 0x78, 	// a (ascii=97)
   ...					// ...
   0x44, 0x64, 0x54, 0x4C, 0x44, 	// z (ascii=122)
   ...					// ...
   0xFE, 0x01, 0x45, 0x3A, 0x00, 	// ß (ascii=133)
   0x06, 0x09, 0x09, 0x06, 0x00, 	// ° (ascii=134)
   0x00, 0xFC, 0x40, 0x40, 0x3C, 	// µ (ascii=181)
};

Die FontStruktur enthält die notwendigen Informationen für die Font-Engine, damit diese die Schrift auf dem Display rendern kann. Der Anwendungsentwickler seinererseits kann ebenfalls auf diese Daten zugreifen. So ist zum Beispiel die Zeichenhöhe eine oft benötigte Information.

Font fontSmallPlain =
{
	charSizeX,  
	charSizeY,
	mapTranslation,
	mapTranslationSize,
	data,
	dataFirstAscii,
	bytesPerCol,
	dataRegularCharCount
} ;

Ein Zeichen wird spaltenweise aus einzelnen Bits aufgebaut. Vergleichen Sie das ASCII-Zeichen Nr 33 (0x21, Ausrufezeichen) mit den dazugehörigen Daten.

  0x00, 0x00, 0x4F, 0x00, 0x00, 	// ! (ascii=33)

Jede Schrift kann auf dem Display in unterschiedlichen Schriftstilen dargestellt werden.

class Font {
  enum { 
     Normal, 
     Wide, 
     Fixed, 
     High,
     Cursive,
     Underline,
     Stroke,
     Inverse 
     };
  ...   
};

Entwurf Schriften-Anwendung

Die Eigenschaften von Schriften sollen in vier Schritten betrachtet werden.

  1. verschiedene Schrift auswählen (Schriftarten)
  2. eine Schrift variieren (Schriftstile)
  3. farbige Schriften
  4. ausgewähtle Schriftoperationen anwenden

Realisierung Schriften-Anwendung

1. Iteration, Schriftarten

In der ersten Iteration sollen einfach verschiedene Schriftarten ausgewählt werden. Beachten Sie, dass die Schriften in unterschiedlichen Paketen liegen. Es ist unter Umständen notwendig, das betreffende Paket (UglFonExt) in das Diagramm zu ziehen.

display.setFont( fontSmallPlain );
display.drawText( 10,10,"Das ist die kleinste Schrift.");
 
display.setFont( fontMediumPlain );
display.drawText( 10,20,"Diese mittelgroße Schrift ist Standard.");
 
display.setFont( fontLargePlain );
display.drawText( 10,45,"das ist GROSS!");
 
// ein Font aus dem Paket UglFontExt
display.setFont( font7Segment );
display.drawText( 10,75,"12345678");

Erstellen und übertragen sie den Code auf den Mikrocontroller. Vergleichen Sie die Darstellung auf dem Display mit dem Quelltext.

2. Iteration, Schriftstile

Nur einen Font zu verwenden spart durchaus wertvollen Speicher. Deshalb ist es möglich, eine Schriftart zu variieren, um zum Beispiel Überschriften oder auch andere Hervorhebungen und Unterscheidungen im Text vorzunehmen.

display.setFont( fontMediumPlain );
 
display.fontStyle=Font::Normal;
display.drawText( 10,15,"Das ist der normale Schriftschnitt");
 
display.fontStyle=Font::Cursive;
display.drawText( 10,30,"Das ist kursive Schrift");
 
display.fontStyle=Font::Wide;
display.drawText( 10,45,"Das ist die breite Variante");
 
display.fontStyle = Font::High;
display.drawText( 10,60,"Das ist der hohe Schriftschnitt");
 
display.fontStyle = Font::Wide | Font::High;
display.drawText( 10,85,"Das ist hoch und breit");
 
display.fontStyle=Font::Underline;
display.drawText( 10,110,"Das ist unterstichene Schrift");
 
display.fontStyle=Font::Inverse;
display.drawText( 10,125,"Das ist invertierte Schrift");
 
display.fontStyle=Font::Stroke;
display.drawText( 10,140,"Das ist durchgestrichene Schrift");

Erstellen und übertragen sie den Code auf den Mikrocontroller. Vergleichen Sie die Darstellung auf dem Display mit dem Quelltext. Beachten Sie, dass diese verschiedenen Schriftstile mit ein und derselben Schriftart (Font) softwareseitig generiert wurden.

3. Iteration, Schriftfarben

Zur Hervorhebung oder Unterscheidung von Texten kann auch die Textfarbe dienen. Die Font-Engine rendert die Schrift mit der aktuell eingestellten Fordergrundfarbe des Displays. Dabei kann der Texthintergrund überdeckend oder auch transparent sein. Beim Überdecken (opaque) wird die aktuelle Hintergrundfarbe benutzt. Vergleichen sie dazu die Displayfunktionen setColor und setBackgroundColor.

display.setColor( RGB(0,200,0) );
Rect r(45,5,160,160);
display.fillRect(r);
 
display.setFont( fontLargePlain );
display.setColor( RGB(0,0,0) );
display.drawText( 10,15,"das ist schwarz");
display.setColor( RGB(255,0,0) );
display.drawText( 10,45,"das ist rot");
display.setColor( RGB(0,0,255) );
display.drawText( 10,75,"das ist blau");
 
display.setColor( RGB(0,0,0) );
display.setBackgroundTransparent();
display.drawText( 10,105,"das ist transparent");

Erstellen und Übertragen sie den Code auf den Mikrocontroller. Vergleichen Sie die Darstellung auf dem Display mit dem Quelltext.

4. weitere Iterationen

Einzelne Zeichen werden mit der Displayfunktion drawChar dargestellt. Diese können wir nutzen, um uns den gesamten Zeichensatz einer Schriftart ausgeben zu lassen. Variieren Sie die Schriftart.

int 	posX,posY,count,height;
char	firstAscii;
posX=10;
posY=10;
 
// Font auswählen
display.setFont( fontSmallPlain ); // fontSmediumPlain, fontLargePlain
 
count		= display.getFont().dataRegularCharCount;
height		= display.getFont().charSizeY;
firstAscii	= display.getFont().dataFirstAscii;
 
for (unsigned char i=0; i<count; i++)
{
	posX += display.drawChar( posX, posY, firstAscii + i );
	if (posX>220)
	{
		posX=10;
		posY+=height+5;
	}
 
}

Um eine Zeichenfolge (String) auszugeben, benutzt man zum Beispiel die Funktion drawText(x,y,text). Diese gibt den Startpunkt (links, oben, x, y) und den auszugebenden Text an. Das Sonderzeichen für einen Zeilenumbruch \n bewirkt, dass die nächsten Zeichen auf einer neuen Zeile ausgegeben werden.

int pos=10;
display.setFont( fontSmallPlain );
// pos + tatsächliche Breite des ausgegebenen Textes
pos += display.drawText( pos,20-display.getFont().charSizeY/2,"klein ");
display.setFont( fontMediumPlain );
pos += display.drawText( pos,20-display.getFont().charSizeY/2,"mittel ");
display.setFont( fontLargePlain );
pos += display.drawText( pos,20-display.getFont().charSizeY/2,"GROSS");
display.setFont( fontMediumPlain );
pos += display.drawText( pos,20-display.getFont().charSizeY/2," mittel");
display.setFont( fontSmallPlain );
pos += display.drawText( pos,20-display.getFont().charSizeY/2," klein");
 
display.setFont( fontMediumPlain );
display.drawText( 10,40,"Das ist ein Text mit \nZeilenumbruch!");

Die Displayfunktion drawText(x,y,text,onlyCalculate) liefert, wie gerade gezeigt, immer die tatsächlich gerenderte Breite des ausgegebenen Textes zurück. Sie kann aber auch benutzt werden, um die Ausdehnung eines Textes ohne Ausgabe zu ermitteln. Dazu wird ein vierter Parameter angegeben (onlyCalculate=true).

Rect r;
String text;
 
display.setFont( fontLargePlain );
 
text="Lorem ipsum";
r.top 		= 20;
r.left		= 20;
 
// die Höhe des Textes
r.height	= display.getFont().charSizeY;
 
// die Breite des Textes ermitteln
r.width		= display.drawText(r.left,r.top,text,true);
 
display.setColor(RGB(200,200,200));
display.fillRect(r);
 
display.setBackgroundTransparent();
display.setColor(RGB(0,0,0));
display.drawText(r.left,r.top,text);
 
r.margin(3);
display.setColor(RGB(200,0,0));
display.drawRect(r);

Die leistungsfähigste Textausgabe erfolgt mit der Displayfunktion drawText(r,text,format). Diese rendert den Text in einem vorgegebenen Rechteck. Dabei verfügt die Funktion über folgende Eigenschaften:

enum Align { 
  Left, 
  Right, 
  Center, 
  Top, 
  VCenter, 
  Bottom
};
display.clearScreen();
 
String text = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam. ";
Rect r(20,10,200,45);
display.setFont(fontMediumPlain);
 
display.drawRect(r);
r.margin(-2);
display.drawText(r,text);
 
r.margin(+2);
r.top += r.height+10;
 
display.drawRect(r);
r.margin(-2);
display.drawText(r,text,Align::Center|Align::VCenter);
 
 
r.margin(+2);
r.top += r.height+10;
 
display.drawRect(r);
r.margin(-2);
display.drawText(r,text,Align::Bottom|Align::Right);
 
 
text+= "Nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam. ";
r.margin(+2);
r.top += r.height+10;
 
display.drawRect(r);
r.margin(-2);
display.drawText(r,text,Align::Left|Align::Top);

Inlineformatierungen werden gekennzeichnet (gequotet) mit einem “&“. Dabei werden Großbuchstaben zum Einschalten und Kleinbuchstaben zum Ausschalten der Inlineformatierung benutzt. Ein “&“ wird durch ein doppeltes “&&“ abgebildet

display.clearScreen();
 
String text;
text = "Lorem &Wipsum&w dolor sit amet, &Iconsetetur&i "
       "&Vsadipscing&v elitr, &Ssed&s diam. ";
 
Rect r(20,10,200,45);
display.setFont(fontMediumPlain);
 
display.drawRect(r);
r.margin(-2);
display.drawText(r,text);

Videozusammenfassung

(Mit installiertem Flash kann man an dieser Stelle ein Video in dieser Web-Seite ansehen.)

Nächstes Thema