Ein grosses

PostScript-Fonts sind nichts anderes als PostScript-Programme, welche eine Reihe von Schriftzeichen beschreiben. Jeder Font ist als sogenanntes Dictionary organisiert, das die Namen der Zeichen mit den Umriss-Definitionen verbindet. Die Umriss-Definitionen bestehen im wesentlichen aus den Befehlen moveto (Bewegung), lineto (Linie), curveto (Kurve) und fill (zum Füllen). Das PostScript-Programm demonstriert die Beschreibung eines Zeichens "A":
200 200 moveto 300 200 lineto 385 410 lineto 615 410 lineto 700 200 lineto 800 200 lineto 500 900 lineto closepath % Umriss aussen 425 500 moveto 500 660 lineto 575 500 lineto closepath % Umriss innen fillDas Symbol wird durch eine äussere und eine innere Hüllkurve gebildet. Während der äussere Umriss im Gegenuhrzeigersinn konstruiert wird, verläuft der innere Umriss im Uhrzeigersinn. Es werden lediglich Linien-Segmente verwendet (hier keine Bezier-Kurven). Der Nullpunkt des Koordinatensystems liegt unten links. Die Einheiten sind gewöhnlich typografische Punkte, die PostScript-Sprache definiert die Zeichen jedoch grössenunabhängig.
Theoretisch ist es auch möglich, ein Zeichen als Bit-Muster zu definieren (mittels imagemask). Aber die Umriss-Methode ist der Bitmap-Methode aus zwei Gründen überlegen:
dict key get anyDer Operator get sucht nach dem Schlüssel key in dict und gibt den entsprechenden Wert, d.h. die gefundene Zeichenbeschreibung, auf den Operandenstack zurück. Beachten Sie, dass "get" sowohl ein Dictionary- als auch ein Array- oder String-Operator sein kann.
Die Typ-1-Fonts von Adobe Systems sind gewöhnlich verschlüsselt und enthalten spezielle Instruktionen oder Hints, die zur scharfen Wiedergabe von kleinen Zeichen verwendet werden. Diese Hints dienen der Verbesserung der Schriftqualität im niedrigen Auflösungsbereich. Die Fonts des Typs 1 runden die Koordinaten der Stützpunkte nicht einfach auf die nächste Pixel-Position. Technisch sind die Hints durch spezielle Routinen im Rasterprozess verwirklicht, die dem Benutzer verborgen sind.
Die wichtigste Anwendung von Hints ist das Angleichen der Stammdicken von
Schriftzeichen. Bei Typ-3-Schriften kann es sein, dass von zwei gleich stark
definierten Stämmen der eine zum Beispiel mit zwei Pixeln und der andere mit
drei Pixeln ausgegeben wird. Dieser bei geringen Auflösungen gut sichtbare
Effekt wird im grafischen Gewerbe Pixelsprung genannt. Er wird dadurch
hervorgerufen, dass die Koordinaten einfach auf die nächste Pixel-Position
gerundet werden. Beispiel:
In dieser Abbildung SOLLTEN alle Striche gleich dick sein, sind es aber
nicht (Pixelsprung).
Die Hints sorgen dafür, dass die Linien oder die Zeichenstämme der physikalischen Auflösung des Ausgabegerätes angepasst werden, und garantieren, dass gleich definierte Stämme mit der gleichen Pixelanzahl belichtet werden. Die Amerikaner sagen: "Hints tell the computer how to modify character outlines so they fit the grid of dots."
Ein weiterer Typ von Hints nennt sich Force-Bold. Wenn kleine Schriftzeichen mit einer kleinen Auflösung, z.B. auf dem Bildschirm, gerastert werden, kann es sein, dass die Stämme fetter Zeichen nur ein Pixel stark sind. Diese Zeichen erscheinen somit gleich wie magere Zeichen und können nicht mehr von jenen unterschieden werden. Die Hints Force-Bold sorgen dafür, dass ein fettes "a" immer dicker als ein normales "a" aussieht.
Als Faustregel gilt, dass der PostScript-Interpreter von Adobe Systems die Hint-Informationen berücksichtigt, während bei den Non-Adobe-Interpretern die Lesbarkeit der kleinen Zeichen häufig zu wünschen übrig lässt.
Siehe auch
Adobe Font Metrics: Die AFM-Dateien enthalten Breiten- und Kerning-Angaben für die Schriftzeichen bzw. Zeichenkombinationen: Character Metrics und Kerning Data. Diese in einer AFM-Datei abgelegten Daten werden von Textverarbeitungsprogrammen eingelesen, um die Zeilenumbrüche berechnen zu können.
Zeichenkombinationen mit/ohne Unterschneiden.
Beispiel für eine AFM-Datei (ZapfChancery-MediumItalic.afm).
Abbildung: Random-Font mit sechs Zeichen.
Die einzelnen Zeichen- oder Umrissbeschreibungen verwenden natürlich den curveto-Operator für die Bezier-Segmente sowie den lineto-Operator. Der curveto-Operator dient dazu, beliebige Rundungen zu konstruieren. Seine Operanden werden mithilfe der Sequenz
rand 100 modberechnet, d.h. die Zufallszahl (geliefert von rand) wird durch 100 geteilt, sodass der Restwert (Modulo) zwischen 0 und 99 liegt. Der vorliegende Random-Font wurde vollständig von Hand ausprogrammiert. Normalerweise erzeugen Sie einen eigenen Font mit einem Fontgenerator, z.B. mit dem bekannten Macintosh-Programm Fontographer von Altsys in Texas.
Im folgenden ist das (gekürzte) PostScript-Programm abgedruckt:
%!PS-Adobe-3.0 EPSF-3.0 %%Title: WilliamRand at 100 %%Creator: (Mein Mail-Freund John F Sherman) %%BoundingBox: 0 0 530 750Das Programm beginnt mit dem EPS-Kopf, der unter anderem die Boundig-Box angibt. John F. Sherman entwickelte das Programm an der Notre Dame University in Indiana.
/Helvetica findfont 12 scalefont setfont 15 15 moveto (Random font with 100 random factor) show % Legende
/newfont 10 dict def % Font-Dictionary ... newfont begin /FontInfo 9 dict dup begin /version (001.000) readonly def /FullName (WilliamRand) readonly def /FamilyName (William) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch false def /UnderlinePosition -133 def /UnderlineThickness 20 def /Notice (designed by John F Sherman) readonly def end readonly defDie neun Einträge im Unter-Dictionary FontInfo werden vom PostScript-Interpreter nicht beachtet, sie dienen der Dokumentation. Der wichtige Eintrag FontType besagt, ob es sich um einen Font des Typs 1 oder des Typs 3 handelt.
/FontType 3 def % ohne HintsDie Variable FontType ist auf 3 gesetzt. Der Font enthält keine Hints, ist somit vom Typ 3.
/FontMatrix [.001 0 0 .001 0 0] def /FontBBox [0 0 1000 1000] defDas Koordinatensystem für die Zeichenbeschreibung besteht aus 1000 mal 1000 Einheiten; der Nullpunkt befindet sich unten links.
/UniqueID 1734 def /Encoding 256 array def StandardEncoding Encoding copy popDer "Encoding Vector" ordnet jedem Buchstaben einen numerischen Code zu. Die Buchstaben a bis f werden gemäss ASCII-Code angesteuert (Normalfall).
/CharProcs 60 dict def % Unter-Dictionary
CharProcs begin % Zeichenbeschreibungen...
/.notdef { } def
/space {300 0 setcharwidth} bind def
Dieser Befehl legt die Breite des Leerzeichens fest. Der Operator setcharwidth gibt die Zeichenbreite an (Font-Metrik).
Zuerst werden die Umrisse des Buchstabens "a" definiert:
/a { 300 0 setcharwidth
277.9999 rand 100 mod add 79.9866 rand 100 mod add moveto
% Startpunkt fuer a
Der moveto-Operator legt fest, wo mit dem Konstruieren begonnen wird. Darauf folgen einige lineto's und viele curveto's:
289.9933 rand 100 mod add 79.9866 rand 100 mod add lineto % gerades Segment 293.9911 rand 100 mod add 72.998 rand 100 mod add 287.9944 rand 100 mod add -7.9956 rand 100 mod add 235.9924 rand 100 mod add -7.9956 rand 100 mod add curveto % erstes Bezier-Segment 201.9958 rand 100 mod add -7.9956 rand 100 mod add 176.9867 rand 100 mod add 28.9917 rand 100 mod add 183.9905 rand 100 mod add 61.9965 rand 100 mod add curveto % zweites Bezier-Segment 165.9851 rand 100 mod add 21.9879 rand 100 mod add 137.9852 rand 100 mod add -6.9885 rand 100 mod add 93.9941 rand 100 mod add -7.9956 rand 100 mod add curveto % drittes Bezier-SegmentEs folgen weitere Bezier-Segmente...
6.9885 rand 100 mod add -9.9945 rand 100 mod add 17.9901 rand 100 mod add 192.9932 rand 100 mod add 50.9949 rand 100 mod add 233.9935 rand 100 mod add curveto 90.9882 rand 100 mod add 283.9966 rand 100 mod add 164.9933 rand 100 mod add 283.9966 rand 100 mod add 180.9998 rand 100 mod add 311.9965 rand 100 mod add curveto 182.9987 rand 100 mod add 314.9872 rand 100 mod add 201.9958 rand 100 mod add 475.9979 rand 100 mod add 144.989 rand 100 mod add 467.9871 rand 100 mod add curveto 70.9991 rand 100 mod add 457.9925 rand 100 mod add 110.9924 rand 100 mod add 400.9857 rand 100 mod add 109.9853 rand 100 mod add 383.9874 rand 100 mod add curveto 107.9864 rand 100 mod add 356.9946 rand 100 mod add 50.9949 rand 100 mod add 347.9919 rand 100 mod add 49.9878 rand 100 mod add 383.9874 rand 100 mod add curveto 48.996 rand 100 mod add 439.9872 rand 100 mod add 89.9963 rand 100 mod add 485.9924 rand 100 mod add 154.9988 rand 100 mod add 481.9946 rand 100 mod add curveto 216.9952 rand 100 mod add 477.9968 rand 100 mod add 231.9946 rand 100 mod add 403.9917 rand 100 mod add 231.9946 rand 100 mod add 341.9952 rand 100 mod add curveto 231.9946 rand 100 mod add 49.9878 rand 100 mod add lineto % Zur Abwechslung eine LinieWieder mal eine Linie! Der Operator lineto hat zwei Operanden, er konstruiert ein gerades Segment von der aktuellen zur angegebenen Position (x,y). Beispiel für die oben angegebene Koordinatenposition: x = (231.9946 + 71.3292), y = (49.9878 + 44.0131). Und noch ein Bezier-Segment:
231.9946 rand 100 mod add 27.9999 rand 100 mod add 253.9978 rand 100 mod add 17.9901 rand 100 mod add 264.9994 rand 100 mod add 27.9999 rand 100 mod add curveto % Bezier-SegmentDer Buchstaben "a" besteht aus einer äusseren und inneren Hüllkurve, daher der folgende moveto-Operator!
181.9916 rand 100 mod add 288.9862 rand 100 mod add moveto % Start fuer innere Huellkurve 163.9862 rand 100 mod add 281.9977 rand 100 mod add 100.9979 rand 100 mod add 253.9978 rand 100 mod add 87.9974 rand 100 mod add 199.9969 rand 100 mod add curveto 74.9969 rand 100 mod add 144.989 rand 100 mod add 76.9958 rand 100 mod add 47.9889 rand 100 mod add 109.9853 rand 100 mod add 19.989 rand 100 mod add curveto 140.9912 rand 100 mod add -5.9967 rand 100 mod add 181.9916 rand 100 mod add 56.9916 rand 100 mod add 181.9916 rand 100 mod add 97.9919 rand 100 mod add curveto 181.9916 rand 100 mod add 288.9862 rand 100 mod add lineto fill } def % Buchstaben aDie Umrisse des Zeichens "a" sind mehrheitlich aus Bezier-Segmenten zusammengesetzt (curveto). Zu einem curveto-Operator gehören jeweils sechs Operanden, d.h. drei Koordinatenpaare. Der Operator rand liefert jeweils eine Zufallszahl zurück, die dann durch 100 geteilt wird. Der Operator mod liefert somit einen Restwert zwischen 0 und 99. Der Operator fill füllt die geschlossenen Umrisse mit schwarzer Farbe auf.
/b { 290 0 setcharwidth % Zeichenbreite b
217.9871 rand 100 mod add 250 rand 100 mod add moveto % Startpunkt fuer b
218.9941 rand 100 mod add 153.9917 rand 100 mod add 207.9925 rand 100 mod
add 38.9862 rand 100 mod add 154.9988 rand 100 mod add 11.9934 rand 100 mod
add
curveto % Bezier-Segment
... Umrissbeschreibung fuer b ...
fill } def % Buchstaben b
Hier sind die meisten Bezier-Segmente, d.h. curveto-Operatoren, weggelassen.
/c { 270 0 setcharwidth % Zeichenbreite c
75.9888 rand 100 mod add 248.9929 rand 100 mod add moveto % Startpunkt fuer c
76.9958 rand 100 mod add 154.9988 rand 100 mod add 70.9991 rand 100 mod add
1.9989 rand 100 mod add 143.9972 rand 100 mod add 17.9901 rand 100 mod add
curveto % Bezier-Segment
... Umrissbeschreibung fuer c ...
fill } def % Buchstaben c
Der Buchstaben "c" besteht lediglich aus einer Hüllkurve, verwendet daher nur einen moveto-Operator; sonst ausschliesslich Bezier-Segmente.
/d { 270 0 setcharwidth % Zeichenbreite d
272.995 19.989 moveto % Startpunkt fuer d
272.995 rand 100 mod add 0 rand 100 mod add lineto 182.9987 rand 100 mod add 0 rand 100 mod add lineto
182.9987 rand 100 mod add 47.9889 rand 100 mod add lineto
166.9922 rand 100 mod add 14.9994 rand 100 mod add 152.9999 rand 100 mod add
-17.9901 rand 100 mod add 115.9973 rand 100 mod add -17.9901 rand 100 mod
add
curveto % Bezier-Segment
... Umrissbeschreibung fuer d ...
fill } def % Buchstaben d
Sowohl c wie auch d und e sind gleich breit, nämlich 270 Einheiten.
/e { 270 0 setcharwidth % Zeichenbreite e
12.9852 rand 100 mod add 235.9924 rand 100 mod add moveto % Startpunkt fuer e
10.9863 rand 100 mod add 341.9952 rand 100 mod add 50.9949 rand 100 mod add
481.9946 rand 100 mod add 128.9978 rand 100 mod add 481.9946 rand 100 mod
add
curveto % Bezier-Segment
... Umrissbeschreibung fuer e ...
fill } def % Buchstaben e
/f { 170 0 setcharwidth % Zeichenbreite f
99.9908 rand 100 mod add 639.9994 rand 100 mod add moveto % Startpunkt fuer f
99.9908 rand 100 mod add 474.9908 rand 100 mod add lineto
139.9994 rand 100 mod add 474.9908 rand 100 mod add lineto
... Umrissbeschreibung fuer f ...
fill } def % Buchstaben f
Um Buchstaben mit geraden Segmenten -- z.B. "d" oder "f" -- zu konstruieren, sind auch eine Reihe von lineto-Operatoren erforderlich.
end % CharProcsSomit sind die Umrisse der sechs Zeichen mathematisch beschrieben!
/BuildChar % obligatorische Prozedur
{exch begin % d.h. font begin
Encoding exch get % Code => Name
CharProcs exch get % => Zeichenbeschreibung
end
exec % ausfuehren
} def
Falls sich ein Zeichen noch nicht im Font-Cache befindet, muss BuildChar aufgerufen werden. Objekte auf dem Operanden-Stack vor dem Aufruf: der aktuelle Font und ein numerischer Code für das gewünschte Zeichen. Aufgrund des numerischen Schlüssels holt sich der Array-Operator get den Zeichennamen im Vektor Encoding. Der Dictionary-Operator get holt sich aus CharProcs eine einzelne Zeichenbeschreibung. Der Wert, der vom ersten get zurückgegeben wird, dient somit als Schlüssel für das zweite get. Dies bedeutet, dass sich auf dem Operanden-Stack folgende Objekte ablösen: numerischer Code => Zeichenname, z.B. "a" => Zeichenbeschreibung.
Erst die Prozedur BuildChar führt die Zeichenbeschreibungen aus, sodass nun das Font-Dictionary vollständig ist.
end % newfontHier endet unser eigenes Font-Dictionary.
/WilliamRand newfont definefont popDer Operator definefont dient dazu, unser Font-Dictionary mit dem Font-Namen WilliamRand zu verbinden. Der Font ist somit "getauft" und steht auf dem Drucker oder der PostScript-Maschine (NeXT) zur Verfügung. Nachdem die Zeichen konstruiert und der Font erzeugt sind, folgt das sogenannte Skript, d.h. die Seitenbeschreibung...
/WilliamRand findfont 70 scalefont setfont % neuen Font anwaehlen 10 50 translate % Ursprung 0 600 moveto (abcdef) show % von 0 450 moveto (abcdef) show % oben 0 300 moveto (abcdef) show % nach 0 150 moveto (abcdef) show % unten showpageDas obige Skript schreibt die sechs Zeichen des neuen Fonts je viermal, siehe Abbildung: Random-Font mit sechs Zeichen. Die Buchstaben mit den zufälligen Umrissen werden in 70 Punkt gesetzt. Die vertikale Zeilenschaltung beträgt 150 Punkt.
Dieses Beispiel demonstrierte einerseits den random-Operator, zeigte aber in erster Linie, wie man einen eigenen Font konstruieren kann. John, many thanks for the example!
Last update: Monday, 27-Dec-2004 12:02:06 CET by
vo