[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:
- Operatoren, die den Operanden-Stack manipulieren, z.B.
pop, exch, dup.
Wie bereits erwähnt nehmen die Operatoren ihre Operanden vom Operanden-Stack und geben allfällige Resultate auf den Operanden-Stack zurück.
- Arithmetische und mathematische Operatoren, z.B. add, div
- Array-Operatoren, z.B. array, get, put
- Dictionary-Operatoren, z.B. get, put, forall.
Das Dictionary
ist ein Konstrukt, das in anderen Programmiersprachen nicht bekannt ist.
- String-Operatoren, z.B. length, get, put
- Relationale, Bool- und Bit-Operatoren, z.B.
eq, ne
- Control-Operatoren, z.B.
if, ifelse
- Type-, Attribut- und Konversionsoperatoren, z.B. type, cvs
- File-Operatoren, z.B. file, ==
- VM-Operatoren (Virtual Memory), z.B.
save, restore
- Operatoren des grafischen Zustands, z.B. setlinewidth, setcolor,
gsave, grestore.
Das gleiche grafische Objekt kann je nach dem grafischen Status mit unterschiedlichen Attributen wiedergegeben werden.
- Koordinatensystem- und Matrix-Operatoren, z.B. translate, scale, rotate. Mit diesen drei Operatoren kann eine Abbildung verschoben, verkleinert/vergrössert und gedreht werden.
- Operatoren der Pfad-Konstruktion, z.B. moveto, arc, curveto. Gemäss Imaging-Modell von PostScript muss zuerst ein Pfad aufgebaut werden, bevor etwas gezeichnet werden kann.
- Painting-Operatoren, z.B. fill, stroke,
image
- Device- und Output-Operatoren, z.B. showpage
- Text- und Font-Operatoren, z.B.
selectfont, show, xyshow
- Fontcache-Operatoren
- Diverse Operatoren
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 !
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