CS 131 PostScript Tutorial
The Basics of Drawing in PostScript

PostScript is a domain-specific language for describing the intended output of printers, i.e., by explaining how to draw the contents on each printed page.

The following video shows a very simple pic diagram being drawn. (The red circle marks PostScript's current page position, which is initially undefined.)

You will see that PostScript uses a two-step process: first a path is defined (paths don't need to be continuous), and separately we ask PostScript to draw that path onto the page.

PostScript has many other commands for creating paths in addition to lineto. Here we demonstrate

  • rlineto, where you specify the relative location of the far end rather than the absolute position, and
  • closepath, which draws a line back to the position of the most recent moveto. (This is always the preferred final step if you are drawing a closed figure.)

If the path you've defined describes a closed figure (particularly if you finished with closepath), then instead of drawing the path on the page with stroke you can fill the interior:

The arc command is used to draw complete and partial circles; it requires the center of the circle, the radius, and the starting and ending angles of the arc. The resulting path can be displayed with stroke or fill.

Warning: though not apparent from this demo, the arc command actually starts by drawing a straight line from the current position on the page to the start of the arc! If you don't want this line, either use arc immediately after newpath (so there isn't yet a "current position"), or use moveto to preset the current position to the point where you calculate the arc will start.

Going Deeper: PostScript's Execution Model

Just like the RPN example in Assignment 2, the PostScript language evaluates expressions using a stack. (It's not using the stack, i.e., the program stack used for function calls and returns; it's just using a stack.) Stack-based languages like PostScript are sometimes referred to by the slightly more general term "concatenative" programming language.

So, you will not be surprised to learn that the PostScript code

                    6 5 3 sub mul
                  
has the effect of pushing 12 on the stack: first the numbers 6, 5, and 3 are successively pushed onto the stack (the “push” is implicit when a constant is mentioned), then the top two (5 and 3) are subtracted (obtaining 2), and then 6 and 2 are multiplied.

The stack can hold any PostScript values, including numbers and strings; strings in PostScript are delimited with parentheses instead of quotes, e.g., (Hello!).

All PostScript commands take their arguments, if any, on the stack. For example, the lineto command pops exactly two values off the stack and uses them as (x,y) coordinates, while the arc command pops five values off the stack.

It follows that the sequence 2 3 moveto 5 4 lineto does the same thing as the sequence 5 4 2 3 moveto lineto (especially since PostScript also doesn't care about line breaks or indentation).

Going Deeper: Coordinate Transformations

One useful feature of PostScript is the ability to modify the entire coordinate system used when defining paths. The following video demonstrates how moving the axes on the page changes how the same filled-triangle code shows up on the page.

The green circle in these next two videos marks the origin, the location of point (0,0). By default, this is the lower-left corner of the page.

The position of this origin is important for two reasons:

  • All coordinates are interpreted relative to the origin on the page;
  • If you rotate the axes, the rotation is around the current location of the origin (which, recall, defaults to rotating around the lower-left corner of the paper).

You can move the position of the origin on the paper by using translate, as shown in the next video.

We can use gsave and grestore to save and restore the PostScript graphics context. This can be useful for temporarily modifying the coordinate system.

The order of coordinate transformations matters; compare the previous video with this next video.

In general, getting the order wrong can lead to paths being drawn in the wrong place — possibly even outside the boundaries of the page (and disappearing).

Note: in addition to translate and rotate, there's a corresponding two-argument operation scale. The command a b scale makes everything you draw a times bigger in the x direction and b times bigger in the y direction. (If a or b are less than 1, then in that direction your drawings will come out smaller than smaller than specified.) You probably won't need this for the assignment, though it can be fun to play around with.

In fact, the videos above are all slightly misleading. By default PostScript measures all dimensions in points, where 1 points is 1/72 of an inch. So really to move to a point 2 inches to the right of the bottom corner and 3 inches up, we would say 144 216 moveto.

For our purposes, measurements in inches are more convenient. We can do this as long as our PostScript code begins 72 72 scale. The provided code for the Lab and the Assignment both ensure this scaling happens before any of your PostScript code.