Lab 4: pic and PostScript
Overview
Over the next two weeks, we will implement a program that translates between two programming languages, each designed to draw pictures:
-
The
pic
language is easy for people to read and write and lets us describe diagrams as a collection of shapes and arrows (think: flowcharts). -
The PostScript (PS) language is primarily designed to be a portable way to describe documents that can be printed and displayed.
A translator (i.e., compiler) between these two languages gives us the best of both worlds: a programmer can write a high-level description of certain kinds of diagrams, them compile them into PostScript files, which can be displayed and printed on all kinds of devices.
Before we can write a compiler from pic
to PS, we first must understand these
languages. Thus, the purpose of this lab is to learn about pic
and PS, by
writing programs in each of these languages.
In the assignment, you will write an evaluator that takes as input an AST for pic
and
produces as output a PostScript file.
Materials
Use the assignment workflow and the link provided on Piazza to get access to this week’s files.
Do the lab on knuth
For this lab, you need to work on knuth. You can use VS Code with RemoteSSH, or ssh
to knuth with the -Y
flag (ssh -Y username@knuth.cs.hmc.edu
) from a laptop with
X-Windows installed.
Set up your environment to work with images
We will make use of a set of programs collectively known as ImageMagick. To do so, we need to set up a configuration file.
(Note: There is a small chance that you already have a configuration file. The
commands below should not break anything with your existing configuration. But if you
already have a file named ~/.config/ImageMagick/policy.xml
, check with the course staff
before running these commands.)
On knuth, run the following commands, which will allow you to convert from PostScript files to other files (such as images):
mkdir -p ~/.config/ImageMagick
cd ~/.config/ImageMagick
touch policy.xml
echo '<policy domain="coder" rights="read | write" pattern="PS" />' >> policy.xml
cd -
Practice Writing pic
Code (20 minutes)
The pic
language is a simple language for drawing box and line diagrams.
Let’s learn about pic
and use it to create a few diagrams.
-
Go through the short tutorial on pic.
-
Edit the
pic
program indiagram.pic
so that it will draw the exact diagram shown in Figure 1.
- Run the following command to create a PostScript file:
groff -p -T ps read-diagram > out.ps
- View the resulting picture. You have two options for viewing:
- If you have XWindows installed, you can view with the command
gv out.ps
Note: to see your output, you will probably need to change the default zoom level (5th button at the top) from
1.0000
toFit to Window
. - If you are using VS Code, you can convert your PostScript file to an image by running the command
convert out.ps -strip -opaque none out.png
Now you can view the
out.png
in VS code.
- If you have XWindows installed, you can view with the command
- When you think your picture exactly matches Figure 1, you can
test it by running the command
/cs/cs131/bin/lab4-test out.ps
You’ll get a message that tells you how closely your picture matches. If the match is not very close, the tester will generate a file
out-diff.ps
that visualizes the differences. Here is an example:
Practice Writing PostScript Code (25 minutes)
The PostScript language is a Turing-complete language for drawing text and
graphics. A PostScript-enabled printer thus contains an embedded interpreter
for the PostScript language. When you send it a .ps
file, the printer
interprets the file (i.e., runs the program that draws the page), and the result
is made physical.
The file figure.ps
is an extremely minimal PostScript file.
-
Go through the short tutorial on postscript.
-
Edit the PostScript program in
figure.ps
so that it draws a picture that includes a “person.” (Stick figures are totally acceptable.) You can debug your picture by viewingfigure.ps
withgv
(if you are ssh-ing) or by convertingfigure.ps
to an image (if you are using VS Code).
Practice with Coordinate Transformations (10 minutes)
One way to define a PostScript function is like so:
/foo % pushes the symbolic name foo on the stack
{
...PostScript commands...
} % pushes a sequence of commands on stack
def % associate the name with the commands
Then, in your code, you can just say foo
to execute that sequence of commands.
Turn your drawing of a person into a function. Call your function a few times
interspersed, with uses of translate
and/or rotate
and/or scale
, to get
many “people” of different sizes, locations, and angles on one page. Once your
masterpiece is finished, push your repo and commit on Gradescope.