[Next] [Previous] [Top]

unix/mail 6/94

Schluss: Ueberblick über die PostScript-Objekte


Nachdem Sie in dieser Serie viele PostScript-Beispiele gesehen haben, soll als Zusammenfassung noch der Begriff "PostScript-Objekt" vorgestellt werden. Diese Zusammenfassung will eine Uebersicht über die verschiedenen Objekt-Typen geben und weist ferner auf die Operatoren hin, welche Typ-Konvertierungen durchführen.

Vom Token zum Objekt

Bevor der PostScript-Interpreter Objekte, d.h. Datenwerte im Memory, erzeugen kann, fasst der sogenannte Scanner mehrere Zeichen zu Tokens zusammen. Dieses Zusammenfassen zu Tokens geschieht aufgrund der PostScript-Syntaxregeln. Ein Token oder mehrere Tokens bilden nun ein PostScript-Objekt, das schliesslich ausgeführt wird.

Verwechseln Sie den Begriff "PostScript-Objekt" weder mit den grafischen Objekten wie Linienzüge, geometrische Figuren, Schriftzüge und Rasterbilder, noch mit den Objekten einer grafischen Benutzeroberfläche.

Objekte können aber nicht nur Operatoren, sondern auch Operanden sein. Beim Operanden-Stack handelt es sich um einen Speicherbereich, der zur Verfügung steht, um Objekte zwischenzeitlich abzulegen. Die PostScript-Operatoren nehmen ihre Operanden vom Stack und geben allfällige Resultate ebenfalls auf den Stack zurück.

Objekt-Typen

Es gibt zahlreiche unterschiedliche Objekt-Typen. Zuerst einmal unterscheidet man einfache und zusammengesetzte Objekten (simple und composite). Der wesentliche Unterschied besteht darin, wie kopiert wird: ein simple object wird echt kopiert, ein composite object teilt sich seinen Werte mit dem Original. Am besten bekannt sind die zusammengesetzten Objekte Array, Zeichenkette und Dictionary. PostScript Level 2 kennt zusätzlich das gstate-Objekt.

Es gibt jedoch Unterscheidungen, die etwas verwirrender sind, so die Unterscheidung zwischen Daten- und Programm-Objekten (data und program). Daten-Objekte können Zahlen, boolsche Werte, Zeichenketten oder Arrays sein, Programm-Objekte etwa Namen, Operatoren oder Prozeduren (diese PostScript-Spalte gab zahlreiche Beispiele für Prozeduren). Gegenüberstellung:

Programm-Objekte: Name, Operator, Prozedur { ... }

Daten-Objekte: Zahl, Bool, Zeichenkette ( ... ), Array [ ... ]

Eine Prozedur ist durch geschweifte Klammern gekennzeichnet, eine Zeichenkette durch runde Klammern und ein Array durch eckige Klammern.

Es zeigt sich aber, dass es Ueberlappungen gibt. Ein Daten-Objekt kann als Teil eines Programms ausgeführt werden, während ein Programm-Objekt, z.B. ein Name, als Daten-Objekt behandelt wird. Denken Sie auch an die Prozedur-Objekte, die als ausführbare Arrays bezeichnet werden. Der Unterschied liegt in den verwendeten Syntax-Zeichen "{ }" bzw. "[ ]". Falls das Prozedur-Objekt zwischen geschweiften Klammern steht, bedeutet dies, dass der Interpreter die Prozedur lediglich abscannt. Prozedur-Objekte zwischen eckigen Klammern geben dem Interpreter an, dass die Prozedur sofort auszuführen ist. Im ersteren Fall werden die Prozedur-Objekte auf den Operanden-Stack gelegt (im Hinblick auf eine spätere Ausführung). Im zweiten Fall erfolgt die Ausführung sofort.

Beispiel:

/ave { add 2 div } def
definiert die Prozedur ave.

[ 5 3 add 2 div ] == 
schreibt den Wert [4.0] ins Konsolenfile.

Objekte können zusätzlich nach Attribut (literal, executable) sowie bei Dictionaries nach Wert klassiert werden. Siehe "Objekt-Attribute".

Einfache Objekte

Einfache Objekte (simple objects) besitzen keine sichtbare Substruktur. Ihre Eigenschaften (Typ, Attribute, Wert) hängen zusammen und können nicht verändert werden. Wenn ein einfaches Objekt kopiert wird, wird seine ganze Struktur kopiert.

boolean
Boolsche Objekte sind Status-Objekte, ihr Wert ist entweder true oder false. Diese Objekte werden etwa in Vergleichen verwendet, z.B. if.
Beispiel: true
integer
Integer sind numerische Objekte. Es sind ganze Zahlen mit positivem oder negativem Vorzeichen, sowie Null.
Beispiel: 123
mark
Mark-Objekte geben eine bestimmte Position auf dem Operanden-Stack an. Sie helfen anderen Operatoren in deren Funktion, z.B. counttomark.
Beispiel: [
name
Namen-Objekte können Schlüssel sein, die auf eine Zeichenkette oder Werte in Dictionaries zeigen.
Beispiel: BitsPerComponent
null
Null-Objekte füllen Leerräume in zusammengesetzten Objekten aus.
Beispiel: null
operator
Operatoren stellen eingebaute Aktionen dar, wobei diese Objekte gewöhnlich in systemdict gefunden werden. Wird ein Name gefunden, dann kommt die Definition (sein Wert) zur Ausführung.
Beispiel: def
save
Save-Objekte geben den VM-Zustand zur Zeit des Saves wieder. Der restore-Operator dient dazu, diesen Zustand wieder herzustellen. Bei PostScript Level 2 können die Save-Objekte nur im lokalen VM verwendet werden.
real
Im Gegensatz zu Integer verwenden Real-Objekte Fliesskommazahlen.
Beispiel: 4.0

Zusammengesetzten Objekte

Zusammengesetzte Objekte haben Substrukturen, die verändert oder modifiziert werden können. Wenn ein zusammengesetztes Objekt kopiert wird, dann wird sein Wert nicht kopiert. Derselbe Wert gilt für das ursprüngliche und das kopierte Objekt.

array
Ein Array kann eine beliebige Anzahl unterschiedlicher Objekte enthalten, z.B. Zahlen, Dictionaries, Namen, Zeichenketten oder andere Objekte. Ein Array ist durch eckige Klammern [ ... ] gekennzeichnet und wird ab 0 indiziert.
Beispiel: /NewCodes 256 array def
dictionary
Ein Dictionary-Objekt setzt sich aus zwei Elementen zusammen: Schlüssel und Wert. Schlüssel-Objekte sind gewöhnlich Namen-Objekte. Ein Schlüssel ist mit einem Wert-Objekt verbunden, das z.B. eine bestimmte Operation durchführt. Während ein Dictionary-Objekt ein key/value-Paar darstellt, ist das Dictionary ein Behälter für Objekt-Paare.
Beispiel: /BitsPerComponent 8 def
gstate
Ein gstate-Objekt hält den grafischen Zustand fest (Level 2).
Beispiel: /Obj gstate def
string
Zeichenketten sind durch runde Klammern gekennzeichnet, also durch "(...)", ferner durch "<...>" und "<~...~>".
Beispiel: (hallo)

Ueberblick: Objekt-Attribute (literal, executable, access)

Wie bereits erwähnt können Objekte auch Attribute haben.

Ueberblick über Objekt-Attribute:

literal
Literal-Objekte werden als Daten behandelt (z.B. integer, real, string). Sie werden auf den Operanden-Stack gelegt, damit ein anderer Operator sie ausführen kann.
executable
Ausführbare Objekte werden direkt vom Interpreter ausgeführt.
access
Dieses Attribut bezieht sich auf die Zugriffsrechte für zusammengesetzte Objekte:
unlimited bedeutet die geringsten Restriktionen.
read-only bedeutet Lese- und Ausführungsberechtigung; aber ein Schreibzugriff ist nicht möglich.
execute-only bedeutet lediglich Ausführungsberechtigung.
none bedeutet, dass überhaupt kein Zugriff möglich ist.

Dictionary-Objekt: Schlüssel und Werte

Dictionaries haben in der PostScript-Sprache eine besondere Stellung, da ein Dictionary ein kompaktes, übersichtliches und fehlerfreies Programmieren erlaubt. Zu jedem Schlüssel gehört ein Wert. Falls in einem Dictionary ein Schlüssel gefunden wird, gibt der Interpreter den entsprechenden Wert zurück. Ein Schlüssel-Objekt ist gewöhnlich ein Name.

Wert ist das zweite Element eines Dictionary-Objekts. Ein Wert wird gewöhnlich auf den Operanden-Stack gelegt, um dann ausgeführt oder von einem anderen Operator konsumiert zu werden.

Bei einem Dictionary kommt es darauf an, an welcher Position im Dictionary-Stack (nicht: Operanden-Stack) es sich befindet. Beispiel:

/a 5 dict def % dict of five objects
/b 5 dict def
a begin /BitsPerComponent 1 def 
	end
b begin /BitsPerComponent 8 def 
	...
	end
In diesem Beispiel befindet sich BitsPerComponent des Dictionary b zuoberst im Dictionary-Stack. BitsPerComponent hat daher den Wert 8. Der Operator begin dient dazu, ein Dictionary zum current dictionary zu machen. Mit den Operatoren begin/end kann man hin- und herwechseln.

Verwechseln Sie den Dictionary-Stack nicht mit dem Grafikstatus-Stack, einem zusätzlichen Stack (Operatoren gsave und grestore).

Fontdarstellung: Font-Dictionary.

Ein Array-Beispiel: der Encoding-Vektor

Im Zusammenhang mit Fonts ordnet der Encoding-Vektor den grafischen Zeichen numerische Codes zu. Das folgende Beispiel erzeugt den Encoding-Vektor NewCodes, bei welchem das Zeichen "quoteleft" durch das Zeichen "grave" ersetzt wird.

/NewCodes 256 array def % array of 256 names
NewCodes 0					% ab Position 0
StandardEncoding 0 256 getinterval
			putinterval 		% Zeichen in NewCodes
NewCodes 8#140 /grave put 
				% quoteleft durch grave ersetzen

NewCodes ==

Zuerst erzeugt der Operator array den neuen Vektor. Nachdem der Operator getinterval dem Standard-Vektor StandardEncoding die 256 Namen entnommen hat, trägt der Operator putinterval die 256 Namen im neuen Vektor ein (ab Position 0). Zusätzlich wird an der oktalen Position 140 statt "quoteleft" das Symbol "grave" eingesetzt. Der Vektor StandardEncoding existiert auch in PostScript Level 1!

Falls Sie an einer Workstation arbeiten, dann schreibt der Operator "==" den Array, d.h. den neuen Encoding-Vektor, ins Konsolenfile.

Paper: ISO Latin-1.

Konvertierungen

Der Typ eines bestimmten Objekts kann mit dem Operator type herausgefunden werden. Beispiel:

(bla) type == flush
Dieser Befehl gibt den Namen stringtype auf den Operanden-Stack zurück. Falls Sie an einer Workstation arbeiten, dann schreibt der Operator "==" die Antwort ins Konsolenfile. Der Operator flush dient dazu, die Ausgabe nicht mehr zu puffern.

Wichtiger sind jedoch die Operatoren, welche Typ-Konvertierungen durchführen:

cvi
convert to integer
cvr
convert to real
Die beiden Operatoren cvi und cvr konvertieren numerische Werte.

cvs
convert to string
cvx
convert to executable
cvlit
convert to literal
Die beiden cvx und cvlit konvertieren Attribute.

cvn
convert to name
Der Operator cvn wandelt Zeichenketten um.

cvrs
convert to radix-string
Um eine Zahl ausdrucken zu können, muss diese zuerst in eine Zeichenkette umgewandelt werden. Beispiel:

8057 5 string cvs 						% => Zeichenkette
show
Der obige Befehl gibt eine Zeichenkette der Maximallänge 5 auf den Operanden-Stack zurück, sodass diese mit show ausgedruckt werden kann.

Ausblick

Im Rahmen dieser PostScript-Spalte war es natürlich nicht möglich, eine vollständige Einführung in die PostScript-Sprache zu geben oder gar alle PostScript-Operatoren zu behandeln. Zum Abschluss soll lediglich gezeigt werden, in welche Kategorien das Reference-Manual die rund 400 Operatoren einteilt:

Einige dieser Kategorien findet man in allen Programmiersprachen, andere wie z.B. "Operatoren der Pfad-Konstruktion" oder "Operatoren des grafischen Zustands" enthalten spezifische Grafik-Befehle.

Hinweis: einfache PostScript-Beispiele.

Rückblick

Zur Einführung in PostScript muss man sich mit folgenden Themen beschäftigen:

Weitere PostScript-Spalten haben gezeigt, dass die Themen Text und Fonts von zentraler Bedeutung sind:

unix/mail 5/93
Zeichensatz ISO Latin-1, Druckeremulation
unix/mail 6/93
Das Setzen von Text
unix/mail 1/94
Font-Technologie, Texteffekt
unix/mail 3/94
Drucker-abhängige PostScript-Befehle
unix/mail 5/94
Level 2: zusammengesetzte Fonts.
Somit hat sich der Kreis geschlossen, und ich kann nur nochmals auf die Literaturangabe auf Seite 288 in unix/mail 4/93 hinweisen. Gut showpage!

Noch ein Hinweis auf World Wide Web !

WWW Hinweis auf den PostScript-Corner im WWW-Server der Uni Zürich. URL:

http://www.zi.unizh.ch/publications/ps/
Wenn Sie mit einem WWW-Klienten (z.B. Mosaic) sich im PostScript-Corner umsehen möchten, brauchen Sie zusätzlich einen "external viewer" wie z.B. ghostview bzw. gs, um die zahlreichen PostScript-Beispiele betrachten zu können.

Der PostScript-Corner enthält zur Zeit folgende Teile im HTML-Format:

Vom Token zum Objekt
Objekt-Typen
Einfache Objekte
Zusammengesetzten Objekte
Ueberblick: Objekt-Attribute (literal, executable, access)
Dictionary-Objekt: Schlüssel und Werte
Ein Array-Beispiel: der Encoding-Vektor
Konvertierungen
Ausblick
Rückblick
Noch ein Hinweis auf World Wide Web !

PostScript-Objekte - 27 OCT 94
[Next] [Previous] [Top]

Generated with WebMaker