Bisher haben wir nur mit den Standardschriften gearbeitet. Es ist aber auch möglich, beliebige andere Schriften zu verwenden, sofern sie in einem von PDF unterstützten Format sind. Um sicherzustellen, dass unser Dokument immer noch überall gleich aussieht, müssen wir diese Schriften aber einbetten.
Die Einbettung per se ist nicht allzu kompliziert. Es gibt aber zwei Schwierigkeiten: Zum einen müssen wir die Zeichenbreiten der einzelnen Zeichen der Schrift kennen, um die Breite von Texten berechnen zu können. Andererseits erwartet PDF zu jeder verwendeten Schrift (ausser eben den Standardschriften) eine Reihe von Metadaten. Diese Metadaten sollen dazu dienen, eine Ersatzschrift zu wählen, sollte die eingebettete Schrift aus irgend einem Grund nicht verwendbar sein.
Schriften liegen in Fontdateien, welche verschiedene Formate haben können. Auf folgende Formate gehen wir ein:
PDF kennt noch ein zwei weitere Formate:
CID Schriften sind eine Variante von Type1 Schriften, die mehr als 256 Zeichen enthalten kann. Leider ist die Einbindung ziemlich kompliziert, und darum im Teil für Fortgeschrittene unter Voller Zeichenzugriff erklärt.
PDF Type3 Schriften (nicht zu verwechseln mit den nicht unterstützten Postscript Type3 Schriften) sind ein Spezialfall für Sonderzwecke. Man sollte sie grundsätzlich nicht verwenden, wenn man nicht genau weiss, was man tut. Ich gehe darum nicht darauf ein.
Bisher sind wir mit einem Objekt für jede Schrift ausgekommen, nämlich dem Schriftobjekt. Für eingebettete Schriften brauchen wir aber deren drei: Das Schriftobjekt, das Schriftdeskriptorobjekt, und ein Streamobjekt mit dem Inhalt der Schriftdatei.
Dieses ist grundsätzlich gleich aufgebaut wie das Schrifobjekt für Standardschriften. Es wird auch auf die genau gleiche Weise im Resourcendictionary eingebunden. Bei eingebetteten Schriften hat es aber ein paar Einträge mehr:
/Type | immer /Font |
---|---|
/Subtype | technischer Typus der Schrift |
/BaseFont | Name der Schrift |
/Encoding | Zeichenkodierung im Dokument |
/FirstChar | Code des ersten Zeichens |
/LastChar | Code des letzten Zeichens |
/Widths | Liste der Zeichenbreiten |
/FontDescriptor | Referenz auf das Schriftdeskriptorobjekt |
/Subtype
ist hier entweder /Type1
oder /TrueType
.
/BaseFont
ist wieder der Name der Schrift, in Form eines Namensobjekts.
/Encoding
sollte bei normalen Schriften auf /WinAnsiEncoding
gesetzt, bei symbolischen Schriften weggelassen werden.
/FirstChar
und /LastChar
geben den tiefstmöglichen bzw. höchstmöglichen Zeichencode an. Normalerweise setzt man einfach 0 bzw. 255 ein.
/Widths
ist ein Array mit den Zeichenbreiten1) für alle möglichen Zeichencodes (vom tiefstmöglichen zum höchstmöglichen Code). Die Zeichenbreiten werden als Ganzzahlen in Promille der Schriftgrösse angegeben.
/FontDescriptor
ist eine Referenz auf das Schriftdeskriptorobjekt.
Dieses Objekt enthält Metadaten, welche hauptsächlich dazu dienen sollen, im Notfall eine Ersatzschrift zu wählen. Es ist folgendermassen aufgebaut:
/Type | immer /FontDescriptor |
---|---|
/FontName | wie /BaseFont |
/Ascent | die Oberlänge |
/Descent | die Unterlänge |
/CapHeight | die Versalhöhe |
/FontBBox | der Zeichenumfang |
/ItalicAngle | die Schrägung |
/StemV | die Stammdicke |
/Flags | Zusatzdaten |
/FontFile | Postscript Schriftdatei |
/FontFile2 | TrueType Schriftdatei |
/FontFile3 | CFF Schriftdatei |
/FontFile
, /FontFile2
oder /FontFile3
verweisen auf das Streamobjekt mit der Datei. Es muss nur einer der Einträge angegeben werden, nämlich derjenige, der auf das Dateiformat passt. Für „OpenType Type1“ brauchen wir dabei das CFF Format.
Die übrigen Angaben müssen wir aus den Schriftdaten extrahieren. /Ascent
, /Descent
, /CapHeight
und /StemV
sind dabei einzelne ganzzahlige Promillewerte (ähnlich wie die einzelnen Zeichenbreiten). /FontBBox
ist ein Array mit vier solchen Werten. /ItalicAngle
ist eine Winkelangabe in Grad, und darf ein Dezimalbruch sein.
Achtung Typographen: In Postscript und PDF ist die Oberlänge nicht die Distanz der Oberkante zur x-Höhe, sondern zur Grundlinie.
/Flags
ist ein Spezialfall. Es ist eine Ganzzahl, in der verschiedene Eigenschaften der Schrift kodiert sind. Die einzelnen Eigenschaften haben je einen Wert, und indem man die Werte der zutreffenden Eigenschaften addiert, erhält man die gewünschte Zahl2). Die einzelnen Werte sind:
Option | Wert | Hexwert |
---|---|---|
Festbreitenschrift | 1 | 0x01 |
Serifenschrift | 2 | 0x02 |
symbolische Schrift | 4 | 0x04 |
Schreibschrift | 8 | 0x08 |
nichtsymbolische Schrift | 32 | 0x20 |
Schrägschrift | 64 | 0x40 |
Grossschrift | 65536 | 0x10000 |
Kapitälchenschrift | 131072 | 0x20000 |
ForceBold | 262144 | 0x40000 |
Der Eintrag ForceBold hat dabei nichts damit zu tun, ob es sich um eine Fettschrift handelt. Vielmehr handelt es sich um ein sogenanntes Hintingflag.
Es lässt sich relativ leicht ermitteln, ob eine Schrift eine Festbreitenschrift ist, ob sie symbolisch oder nichtsymbolisch ist, und ob es sich um eine Schrägschrift handelt. Die restlichen Informationen sind leider nicht oder nur mit erheblichem Aufwand aus den Schriftdateien extrahierbar. Üblicherweise werden sie einfach als „nicht zutreffend“ betrachtet.
Dies ist ein normaler Stream, welcher die eigentlichen Schriftdaten enthält. Zusätzlich zu den normalen Einträgen im Dictionary (/Length
und allenfalls /Filter
), brauchen wir noch ein paar weitere Einträge. Was für welche hängt vom Schriftformat ab.
Es gibt drei zusätzliche Einträge /Length1
, /Length2
und /Length3
. Die Schriftdatei ist nämlich in drei Abschnitte aufgeteilt, und die Länge dieser drei Abschnitte (vor einer allfälligen Kodierung mit ASCII85 oder ASCIIHex) muss angegeben werden.
Es gibt einen zusätzlichen Eintrag /Length1
mit der Länge der Datei vor einer allfälligen Kodierung mit ASCII85 oder ASCIIHex.
Es gibt einen zusätzlichen Eintrag /Subtype
, der auf /Type1C
gesetzt werden muss.
Diskussion