Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Reid G.C.Thinking in PostScript.1990.pdf
Скачиваний:
17
Добавлен:
23.08.2013
Размер:
846.44 Кб
Скачать

memory if the string is a long one. In either case, the memory allocated is exact, and should be predictable. A string that is thirty bytes long requires exactly ten bytes more storage than a string that is twenty bytes long.

This discussion does not cover the precise details of memory allocation, but it does provide a pretty good framework for understanding how memory is consumed in a PostScript program. If you are concerned about gaining precise control over memory allocation, it is best to get specific documentation for the interpreter that you are using.

GETTING MEMORY BACK

Once you have allocated memory in your program, either by creating data structures or by executing some code that uses memory, there are only two ways to reclaim that space:

Use the save and restore operators to reclaim all memory used since the last save was executed.

Use the undef, undefinefont, and vmreclaim operators available in the Display PostScript extensions to the PostScript language (not available in all products).

When using save and restore, you have to plan carefully where you want to restore the contents of memory, because the save/restore mechanism also affects other aspects of the interpreter, including the current graphic state, the current device, and so on. In a typical page description, save and restore may be done at each page boundary or around each page element (like a block of text or a photographic image).

OPENING AND CLOSING FILES

Opening and closing files is a fundamental operation in any program, which is why this section is included in this chapter on the basics. The quick overview is that there are a lot of file-related PostScript operators for reading and writing files; there is one for opening files (the file operator) and one for closing files (the closefile operator). The file operator returns a file object that you must retain for all subsequent file operations (including closefile). Please see Chapter 14 for a complete discussion of file operations.

Chapter 3: FOUNDATIONS

31

COMPARISONS AND EQUALITY OF OBJECTS

PostScript has several distinct data types and is fairly strict about typechecking. However, you can easily convert one type to another, assuming that the type conversion makes some sense, and you can then compare them. (See Data Conversions in Chapter 13 for a discussion of type conversions.) In many instances, the PostScript comparison operators will even do this for you as a convenience. Strings and names, for example, are both simply composed of bytes, so they can easily be compared, as shown in Example 3.13.

Example 3.13: Comparison of Different Types of Objects

% comparing reals with integers:

103.0 103 eq

% true

103.0 103 ge

% true

103.0 103 gt

% false

% comparing mark objects:

mark [ eq

% true

% comparing null objects to integers and booleans:

null 0 eq

% false

null false eq

% false

% comparing strings and name objects:

(Palatino-Roman)

 

/Palatino-Roman eq

% true

(abc)

 

(defabc)

 

3 3 getinterval eq

% true

(abc) (abc) eq

% true (an exception)

% comparing array objects:

[ 1 2 3 ] dup eq

% true

[ 1 2 3 ]

 

[ 1 2 3 ] eq

% false (arrays created independently)

matrix matrix eq

% false

{ 1 exch sub }

 

{ 1 exch sub } eq

% false

% comparing dictionary objects:

5 dict dup begin

 

currentdict eq

% true

32

Chapter 3: FOUNDATIONS

/show where { %if

 

systemdict eq

% true (if “show” has not been redefined)

} if

 

5 dict 5 dict eq

% false (dictionaries created independently)

% comparing file objects:

 

(%stdin) (r) file

 

currentfile eq

% true (most of the time)

% comparing operator objects:

{ 1 2 add } bind 2 get

 

/add load eq

% true (if “add” has not been redefined)

As you may have noticed upon careful reading of Example 3.13, some composite objects (dictionaries, procedures, and arrays) get a little bit tricky when you compare them. In particular, when you use, say, the eq operator, you are comparing the objects themselves, not the structure to which they point. Composite objects represent a structure that is stored in memory somewhere. If you create two different structures, even if they happen to contain the same elements, the structures themselves are independent, and therefore the objects that represent them are not considered to be equal. However, if you have two copies of the same composite object, the eq operator will confirm that they are in fact equal.

Example 3.14: Procedure to Compare Array Contents

/arrayeq

% array1 array2 arrayeq bool

{ %def

 

 

2 copy eq { pop pop true }{ %ifelse

 

 

% if lengths are not equal, return false

 

2 copy length exch length eq { %ifelse

 

% We now have to compare all elements

 

true

% arr arr true

 

0 1 3 index length 1 sub { %for

 

3 index 1 index get

% arr arr bool index val1

 

3 index 2 index get

% arr arr bool index val1 val2

 

eq exch pop and

% arr arr bool

 

} for

 

 

exch pop exch pop

 

 

}{ pop pop false } ifelse

 

}ifelse

}bind def

/arrayne { arrayeq not } bind def

Chapter 3: FOUNDATIONS

33

If you really need to find out if two independently formed composite objects are equivalent, you can compare their contents. If their contents are exactly equal and the lengths of the two composite objects are equal, then you can consider the two composite objects to be equivalent, if not equal. In Example 3.14 is a procedure definition called arrayeq that will compare two arrays, returning true if their contents and lengths are equal.

CONCLUDING THOUGHTS

If you build a solid foundation of PostScript programming skills, you should be able to write programs that work the very first time. There isn’t much to forget, really. You don’t have to declare variables, the syntax is very free, and you cannot get compile-time errors. It helps to get the indentation right, so that all of the parentheses and curly braces balance correctly, and if you develop the skill of always laying out a template for a structure before you go back and fill it in, you should never run into that problem.

The next chapter provides a few examples of typical PostScript programs to help you adopt a style and structure that is appropriate for the task you are faced with. A program to render a graph on a laser printer may be quite different from a program that constructs a downloadable font, for example, and the programming techniques you use should reflect the task.

EXERCISES

1.Syntax errors arise very infrequently in PostScript, but when they do, it can be difficult to track them down.

a.Find the syntax error in the following program segment:

0 1 20 { ( Hello world (part 1) == flush } for

b.Find the syntax error in the following program segment:

currentpoint exch 32 gt {

72 lt { showpage 36 500 moveto } if { %else

(hello world \(part 2) show

} ifelse

34

Chapter 3: FOUNDATIONS

2.Create a simple procedure named line that takes four operands, the x, y location for the beginning of the line and the x, y location for the end of the line. The procedure should perform the necessary moveto, lineto, and stroke operations. Use your procedure once or twice to create some sample lines.

3.Create a template for a procedure that contains an ifelse statement.

4.Design a procedure called ++ that will increment a variable. The procedure should be able to increment any variable that contains an integer or a real value. Design it so that the following sample will add 1 to the value of the variable named counter each time it is called:

/counter 0 def

 

/counter ++

 

/counter ++

 

counter ==

% should be 2

Chapter 3: FOUNDATIONS

35

36

Chapter 3: FOUNDATIONS