- •Preface
- •DESIGN FEATURES
- •STRUCTURED PROGRAMMING TECHNIQUES
- •PROGRAMMING TASKS
- •WINDOW SYSTEMS, COMMUNICATIONS, AND DISPLAYS
- •DATA STRUCTURES AND ALGORITHMS
- •CONCLUDING THOUGHTS
- •PostScript is Not Like C
- •COMPARISON OF LANGUAGE MECHANISMS
- •EXPRESSING AN ALGORITHM AS A PROGRAM
- •THE UNIX SHELL AND OPERATING SYSTEM
- •INPUT, OUTPUT, AND THROUGHPUT
- •CONCLUDING THOUGHTS
- •Foundations
- •POSTSCRIPT LANGUAGE SYNTAX
- •SIMPLE PROGRAM STRUCTURE
- •Make Definitions First
- •Indentation Style
- •SETTING UP TEMPLATES
- •DECLARING AND USING VARIABLES
- •Arithmetic with Numeric Variables
- •Using the // Notation for Constants
- •ALLOCATING MEMORY
- •GETTING MEMORY BACK
- •OPENING AND CLOSING FILES
- •COMPARISONS AND EQUALITY OF OBJECTS
- •CONCLUDING THOUGHTS
- •Some Typical Programs
- •A TYPICAL PAGE DESCRIPTION PROGRAM
- •FONT PROGRAMS
- •PROGRAMS THAT READ DATA
- •QUERY PROGRAMS
- •ENCAPSULATED POSTSCRIPT PROGRAMS
- •PERSISTENTLY RESIDENT PROGRAMS
- •CONCLUDING THOUGHTS
- •Understanding the Stack
- •A QUICK OVERVIEW OF DATA TYPES
- •NAME LOOKUP
- •HOW OPERATORS USE THE STACK
- •GROUPING AND VISUAL CHUNKING
- •THINKING BACKWARD AND SIDEWAYS
- •COMPOSITE OBJECTS
- •THE OTHER STACKS
- •The Dictionary Stack
- •The Execution Stack
- •The Graphics State Stack
- •CONCLUDING THOUGHTS
- •Trusting the Stack
- •SAFETY OF DATA ON THE STACK
- •WHERE ARE THE DATA GOING?
- •REARRANGING THE STACK
- •Using the dup and index Operators
- •Using the roll Operator
- •CONDITIONALS AND LOOPS
- •RECURSION AND LOCAL VARIABLES
- •CONCLUDING THOUGHTS
- •Building Conditional Statements
- •SIMPLE CONDITIONALS
- •SETTING UP THE CONDITION
- •CONDITIONALS ARE NOT MAGIC
- •NESTED CONDITIONALS AND ELSE CLAUSES
- •COMPOUND CONDITIONALS
- •CONCLUDING THOUGHTS
- •Using Looping Constructs
- •LOOP BASICS
- •USING THE LOOP INDEX
- •LOOPS ARE PROCEDURE BODIES
- •LOOPS OF INSTRUCTIONS
- •EXITING LOOPS PREMATURELY
- •CONCLUDING THOUGHTS
- •Procedures
- •WHAT EXACTLY IS A PROCEDURE?
- •PARAMETER PASSING
- •CONSTRUCTING GOOD PROCEDURES
- •What to Name Your Procedure
- •A Useful Naming Convention
- •SELF-MODIFYING PROCEDURES
- •CONCLUDING THOUGHTS
- •Using Dictionaries
- •DICTIONARIES FOR NAME SCOPING
- •LOCAL DICTIONARIES
- •GLOBAL DICTIONARIES OF PROCEDURES
- •MAINTAINING THE DICTIONARY STACK
- •INTO AND OUT OF DICTIONARIES
- •LOOKING INTO DICTIONARIES
- •Using the forall Operator
- •Using the where and known Operators
- •REDEFINING OPERATORS
- •Changing the Behavior of Operators
- •Debugging with Redefined Names
- •Proper Nesting of Redefinitions
- •CONCLUDING THOUGHTS
- •Creating and Manipulating Data
- •CONSTRUCTING AN ARRAY
- •CONSTRUCTING A STRING
- •MANIPULATING DATA WITH PUT AND GET
- •CONCATENATING ARRAYS AND STRINGS
- •INPUT AND OUTPUT OF STRING DATA
- •ARRAYS VERSUS DICTIONARIES
- •ADVANCED TECHNIQUES
- •CONCLUDING THOUGHTS
- •Storing and Using Data
- •Data and the Operand Stack
- •Data and Algorithms for Underlining
- •CLASSICAL DATA STRUCTURES
- •Linked Lists
- •Using Arrays to Form Lists
- •Using Dictionaries to Form Lists
- •Queues, Trees, and Other Data Structures
- •CONCLUDING THOUGHTS
- •Program Data and Instructions
- •TURNING DATA INTO INSTRUCTIONS
- •TURNING INSTRUCTIONS INTO DATA
- •DATA CONVERSIONS
- •CONCLUDING THOUGHTS
- •File Objects
- •Streams and Files
- •PostScript File Operators
- •OPENING AND CLOSING FILES
- •READING AND WRITING FILES
- •Reading from a File
- •Writing to a File
- •Copying and Renaming Files
- •WRITING FORMATTED DATA TO FILES
- •Writing Out Various Data Types
- •Spaces, Tabs, Returns, and Special Characters
- •FILE STATUS INFORMATION
- •RANDOM VERSUS SEQUENTIAL ACCESS
- •CONCLUDING THOUGHTS
- •Appendix
- •Answers to Exercises
/Times-Bold 24 selectfont 1.0 -5 underlineON
(Hamlet, Act II) 200 650 TEXT underlineOFF
/Times-Roman 12 selectfont
(This should be the first line from Hamlet.) 72 600 TEXT (And this, of course, the second.) 72 570 TEXT
The resulting program has a nice balance of data use, passing some of it from the host word processor, storing some of it, and reducing the complexity of the program itself in the way it relies on the data. Notice that the only change to the way we wanted to set the program up was to add two operands to the underlineON procedure call. The rest of it stayed the same.
CLASSICAL DATA STRUCTURES
There are some classic data structures in the field of computer science that you might want to construct in your PostScript program. For instance, you might want to make use of doubly-linked lists, queues, stacks, trees, and so forth. (Stacks are generally free in PostScript because of the inherent stack-based model, but sometimes you need to create your own.)
Linked Lists
Linked lists can be very useful data structures. A linked list is basically a sequential list of chunks of data that you can traverse either forward or backward (if it is doubly-linked). The main advantage to linked lists in traditional programming languages is that you can allocate memory as you need it, and it doesn’t have to be contiguous. In each data block, you store a pointer to the next block, wherever it may be. In PostScript, the need for these lists diminishes greatly, since you don’t need to worry about the way memory is allocated in order to access data. PostScript language arrays are arrays of other PostScript objects, each of which is self-contained (and very likely occupies some memory that is not adjacent to the next element in the array). But, readjusting the terminology very slightly, lists are still extremely useful, even if you don’t have to spend much time worrying about the links between the elements.
Chapter 12: STORING AND USING DATA |
151 |
Let’s assume that you have a single block of data representing text from a drawing program. You want to store the x, y location of the text on the page, the font in which the text is to appear, the text itself, and the color. In the C language, you might come up with something like the code in Example 12.7.
Example 12.7: List Elements as C Structures
struct textchunk { |
|
float X,Y; |
/* X,Y location on screen */ |
char font [ 128 ]; |
/* font name */ |
float ptsize; |
/* point size of font */ |
float R,G,B; |
/* color */ |
char *text |
/* the text itself */ |
struct textchunk *next; |
/* link for list */ |
} *head, *tail; |
|
What might be the best way to implement a composite data structure like a struct in PostScript? You have only a few choices.
•You could use an array that contains all of the pieces of data.
•You might use dictionaries, creating one for each chunk of data.
•You might simply accumulate piles of data on the operand stack, keeping track of what was where.
Since the operand stack is likely to be unwieldy for a structured approach such as this, let’s consider arrays and dictionaries, to see which one seems better.
Using Arrays to Form Lists
Let’s look at an array that contains everything that the C struct does, but which does not have the links to the next item in the list (see Example 12.8).
152 |
Chapter 12: STORING AND USING DATA |
Example 12.8: List Elements as PostScript Array Objects
[
72.0 100.0 /Times-Italic 24.0 1.0 0.0 0.0
(Julius Caesar)
]
Notice that the names have disappeared, since arrays contain just the data. But how would you create a link to the next chunk of data? Since a PostScript array object is already a pointer to a composite data structure, we could use it directly, including an array object within the array that represents the next item in the list. It looks as though the arrays are nested when you look at them syntactically, but in effect one array simply contains a pointer to another. An array might even contain a circular reference by including a copy of itself as one of its elements, but we will try to avoid that in our examples. Notice that the original array (the one containing the name Julius Caesar) has been reproduced, but is written a little more compactly to save some space on the page (Example 12.9).
Example 12.9: Forming a List of Array Objects
[
72.0 650.0 /Times-BoldItalic 24.0 1 0 0 (Julius Caesar)
[
72.0 600 /Times-Italic 18.0 1 0 0 (William Shakespeare)
[]
]
]
The actual structure of these arrays looks more like Figure 12.1 when it is represented internally in the PostScript interpreter.
Chapter 12: STORING AND USING DATA |
153 |
Figure 12.1: Structure of the PostScript Linked List
72.0 650.0 /Times-BoldItalic 24.0 1 0 0 (Julius Caesar) [ ]
72 600 /Times-Italic 18 1 0 0 (William Shakespeare) [ ]
This method is very compact and efficient, but it does present one difficulty: the elements of the structure cannot be referred to by name, but only by their position within the array (although you could write procedures to help you with this). Arrays could be troublesome to maintain effectively and to debug, but are much more space-efficient than dictionaries.
Using Dictionaries to Form Lists
Let’s try the same idea using a dictionary to store the elements of the structure (see Example 12.10).
Example 12.10: List Element as a PostScript Dictionary
/head 9 dict def /tail head def head begin
/X 72 def /Y 470 def
/font /Times-Roman def /ptsize 16 def
% red, green, and blue stored as R,G,B: /R 1 def
/G 0 def /B 0 def
/text (Act One) def
/next null def% points to nothing
end
154 |
Chapter 12: STORING AND USING DATA |