Das Schriftfeaturesystem

Mit OpenType wurde ein neues (auch für TrueType brauchbares) System eingeführt, um die Positionierung von Zeichen präziser zu bestimmen, und diverse Alternativzeichen und Ligaturen zur Verfügung zu stellen. Leider ist dieses System höchst komplex, und es gibt kaum Systeme, die es auch nur grösstenteils unterstützen.

Um das System verwenden zu können, müssen wir es aber auch nicht vollständig unterstützen. Die meisten Schriften nutzen ohnehin nur einen kleinen Teil davon. Problematisch wird es erst bei Schriften, die spezifisch für komplexe Schriftsysteme wie Arabisch oder Tibetanisch erstellt wurden.

Für unsere Zwecke erkläre ich hier nur einen kleinen Teil der Spezifikation, dessen Nutzung aber weit verbreitet ist. Dieser Teil für sich ist schon kompliziert genug.

die Möglichkeiten

Grundsätzlich können über das Schriftfeaturesystem vier Dinge beeinflusst werden: Die genaue Positionierung der Zeichen, alternative Zeichen, Sonderregeln für Blocksatz und Sonderregeln für die Grundlinie. Davon werden wir uns folgendes Anschauen:

  • Regeln für Unterschneidung
  • Alternative Zeichen (konkret Kapitälchen und Mediävalziffern)
  • Ligaturen

Ligaturen sind Zeichen, welche aus mehreren Einzelzeichen zusammengesetzt wurden. Damit lassen sich typographisch heikle Zeichenkombinationen besser lösen. Alternativzeichen und Ligaturen können nur bei Direktzugriff verwendet werden, da wir nur dort die volle Kontrolle über die verwendeten GIDs haben.

Schriftsystem, Sprache und Features

Die einzelnen Features der Schrift können je nach Schriftsystem und Sprache unterschiedlich definiert werden. Für uns heisst das leider, dass wir uns durch eine hierarchische Struktur hangeln müssen. Der GPOS Block und der GSUB Block, mit denen wir uns beschäftigen werden, haben hierfür drei Tabellen: Die Schrift/Sprachtabelle, die Featuretabelle und die Lookuptabelle.

die Schrift/Sprachtabelle

Diese Tabelle definiert, welche der Features für welche Kombinationen aus Schriftsystem und Sprache verwendet werden können. Die Tabelle beginnt mit einer Liste der unterstützten Schriftsysteme. Jeder Eintrag hat eine Liste dazu passender Sprachen. Jeder Eintrag der Sprachenlisten enthält eine Liste mit den gültigen Featurenummern. Sowohl die Schriftsystemliste wie auch die Sprachenlisten können jeweils einen Standardeintrag haben, der gültig ist, wenn kein Schriftsystem bzw. keine Sprache passt.

Die Position der Schrift/Sprachtabelle wird durch einen Eintrag am Anfang des Blocks vorgegeben, der in den Unterkapiteln erklärt ist. Die Tabelle beginnt mit folgendem Eintrag:

PositionLänge Typ Inhalt
02 Byteuint16Anzahl Schriftsysteme

Danach folgt eine Liste der unterstützten Schriftsysteme. Jeder Eintrag ist folgendermassen aufgebaut:

PositionLänge Typ Inhalt
04 Bytechar Schriftsystem-ID
42 Byteuint16Position Sprachtabelle

Die möglichen Schriftsystem-IDs sind bei Microsoft einsehbar:

http://www.microsoft.com/typography/developers/opentype/scripttags.aspx

Beispiele für Schriftsystem-IDs:

DFLTStandard
latnLateinische Schrift
grekGriechische Schrift
cyrlKyrillische Schrift
kanaJapanische Silbenschrift
haniCJK Wortschrift

Die Position der Sprachenliste ist gerechnet vom Anfang der Schrift/Sprachtabelle.

Die Sprachenliste beginnt folgendermassen:

PositionLänge Typ Inhalt
02 Byteuint16Position Standardfeaturenummern
22 Byteuint16Anzahl Sprachen

Danach folgt eine Liste der unterstützten Sprachen. Jeder Eintrag ist folgendermassen aufgebaut:

PositionLänge Typ Inhalt
04 Bytechar Sprachen-ID
42 Byteuint16Position Featurenummern

Die möglichen Sprachen-IDs sind bei Microsoft einsehbar:

http://www.microsoft.com/typography/developers/opentype/languagetags.aspx

Beispiele für Sprach-IDs:

dflStandard
DEUDeutsch
ENGEnglisch
ELLGriechisch
RUSRussisch
JAPJapanisch

Wie man sieht, bestehen die Sprachen-IDs meist aus drei Zeichen, wohingegen in der Liste jeweils vier Zeichen abgelegt sind. Das vierte Zeichen ist in diesen Fällen immer ein Leerzeichen.

Falls die „Position Standardfeaturenummern“ nicht 0 ist, so hat dies dieselbe Bedeutung wie ein „dflt“ Eintrag. die Position der Featurenummern ist gerechnet vom Anfang der Sprachentabelle.

Die Liste der Schrift/Sprache-Spezifischen Features beginnt folgendermassen:

PositionLänge Typ Inhalt
02 Byteuint16unbenutzt
22 Byteuint16benötigtes Feature
42 Byteuint16Anzahl Features

Danach folgt für jedes Feature die Featurenummer:

PositionLänge Typ Inhalt
02 Byteuint16Featurenummer

Die Angabe unter „benötigtes Feature“ steht normalerweise auf 65535. Ist es eine andere Zahl, so bezeichnet es eine Featurenummer, die unterstützt werden muss, damit die Schrift korrekt dargestellt werden kann.

die Featuretabelle

Diese Tabelle enthält eine Liste der von der Schrift unterstützten Features. Zu jedem Feature sind die zugehörigen Lookupnummern abgelegt.

Die Position der Featuretabelle wird durch einen Eintrag am Anfang des Blocks vorgegeben, der in den Unterkapiteln erklärt ist. Die Tabelle beginnt mit folgendem Eintrag:

PositionLänge Typ Inhalt
02 Byteuint16Anzahl Features

Danach folgt eine Liste der Features. Jeder Eintrag ist folgendermassen aufgebaut:

PositionLänge Typ Inhalt
04 Bytechar Feature-ID
42 Byteuint16Position Lookupnummern

Die Featurenummer ist nicht explizit aufgeführt. Statt dessen werden die Features in der Liste von 0 an durchnummeriert.

Die möglichen Feature-IDs sind bei Microsoft einsehbar:

http://www.microsoft.com/typography/otspec/featurelist.htm

Wir werden uns folgende Features weiter ansehen:

kernUnterschneidung
smcpKapitälchen
onumMediävalziffern
ligaLigaturen

Anhand der in der Schrift/Sprachtabelle ermittelten Featurenummern und der gewünschten Feature-ID sollte man nun für jedes Feature auf maximal einen Eintrag kommen. Nun können wir die dazugehörigen Lookupnummern ermitteln. Die Position ist gerechnet ab dem Beginn der Featureliste. Die Liste der Lookupnummern beginnt folgendermassen:

PositionLänge Typ Inhalt
02 Byteuint16unbenutzt
22 Byteuint16Anzahl Lookupeinträge

Danach folgt für jeden Lookupeintrag die Lookupnummer:

PositionLänge Typ Inhalt
02 Byteuint16Lookupnummer

Falls mehrere Lookupeinträge vorhanden sind, müssen sie in der aufgeführten Reihenfolge abgearbeitet werden.

die Lookuptabelle

Diese Tabelle enthält die Positionen der eigentlichen Unterblöcke mit den Daten zu den Features.

Die Position der Lookuptabelle wird durch einen Eintrag am Anfang des Blocks vorgegeben, der in den Unterkapiteln erklärt ist. Die Tabelle beginnt mit folgendem Eintrag:

PositionLänge Typ Inhalt
02 Byteuint16Anzahl Lookupeinträge

Danach folgt eine Liste der Positionen für jeden Lookupeintrag:

PositionLänge Typ Inhalt
02 Byteuint16Position Lookupeintrag

Ähnlich wie bei den Features sind auch die Lookupnummern nicht explizit aufgeführt, sondern die Einträge sind einfach ab 0 durchnummeriert.

Die Position ist jeweils gerechnet ab dem Beginn der Lookuptabelle. Der Eintrag ist folgendermassen aufgebaut:

PositionLänge Typ Inhalt
02 Byteuint16Typ
22 Byteuint16Flags
42 Byteuint16Anzahl Unterblocks

Die Bedeutung der Typnummer hängt davon ab, ob wir im GPOS oder GSUB Block sind, und ist darum in den Unterkapiteln erklärt. Die Flags können wir bei den hier vorgestellten Features ignorieren.

Nun folgt eine Liste der Positionen der Unterblocks:

PositionLänge Typ Inhalt
02 Byteuint16Position Unterblock

Die Position ist jeweils gerechnet ab dem Beginn des Lookupeintrags. Der Inhalt des Unterblocks ist abhängig vom Feature, und darum in den Unterkapiteln erklärt.

Falls mehrere Unterblöcke vorhanden sind, müssen sie in der angegebenen Reihenfolge abgearbeitet werden.

Zeichenlisten

Fast jeder Unterblock für Schriftfeatures verweist auf eine Zeichenliste. Dies ist ein spezieller Unterblock, der eine Liste von GIDs definiert. Es gibt zwei Formate. Die jeweils ersten 2 Bytes sind dabei ein uint16 mit der Formatnummer.

Format 1

Das ist eine einfache Liste. Sie beginnt folgendermassen:

PositionLänge Typ Inhalt
02 Byteuint16Format (immer 1)
22 Byteuint16Anzahl Einträge

Danach folgt die Liste der GIDs. Jeder Eintrag sieht so aus:

PositionLänge Typ Inhalt
02 Byteuint16GID

Format 2

Dieses Format definiert die Liste, indem es zusammenhängende Nummernbereiche aufzählt. Der Unterblock beginnt folgendermassen:

PositionLänge Typ Inhalt
02 Byteuint16Format (immer 2)
22 Byteuint16Anzahl Bereiche

Danach folgt die Liste der Bereiche. Jeder Eintrag sieht so aus:

PositionLänge Typ Inhalt
02 Byteuint16erste GID
22 Byteuint16letzte GID
42 Byteuint16erste Indexnummer

Der Bereich enthält der Reihe nach alle GIDs von der ersten bis und mit der letzten. Die „erste Indexnummer“ ist die Anzahl der von den bisherigen Bereichen abgedeckten GIDs. Wenn wir die GIDs aufzählen, und dabei mit 0 beginnen, ist „erste Indexnummer“ somit die Nummer der ersten GID in diesem Bereich.