PostScript language notes P.J. Drongowski 18 September 2004 (Updated: 24 September 2004) PostScript * What is PostScript? + A language invented by Adobe Systems, now an industry standard + A page description language and a stack-oriented programming language + Inspired by the FORTH language + A page description in a file is a PostScript program that describes what is to be drawn on a page + Can draw lines, circles, etc., and of course, text * How is PostScript used? + Most applications can and do generate PostScript + As a device independent page description and graphics language (EPS) + As a display language (OS X converts PostScript to PDF for display) + As a page description language for printers * Why are we studying PostScript? + It's an industry standard + Many applications directly generate PostScript + It's very useful to be able to display data graphically + You can use this class (module) as a tool in future assignments + It's fun -- hey, we get to draw pictures! * PostScript imaging model + Everything is drawn on a page + Coordinate system - Lower left corner of page is (0,0) - Positive X axis extends to right, positive Y extends up the page - Basic unit of measurement is 1/72 of an inch, roughly equal in size to a traditional printer's point + Paths and marks * Example: Show how to draw lines, etc. on a page * PostScript uses four stacks + Operand stack: Holds operands for operations and results from operations (such as arithmetic.) + Dictionary stack: Provides a context for name searches (variable names, procedure names.) + Execution stack: Holds executable objects (procedures or files) that are in partial stages of execution. + Graphics stack: Maintains current and nested graphics states (positional information, color, line width.) * Explain basic PostScript primitives and what they do + initgraphics Resets the graphics state + showpage Shows the marks on the current page (render the page) + gsave Save (push) the current graphics state + grestore Restore (pop) the current graphics state + sx sy scale Scale coordinates + angle rotate Rotate coordinates + tx ty translate Translate (re-position) coordinates + newpath Start a new path + x y moveto Move to new coordinate point + x y lineto Define line from current coordinate point to new point + x y r a1 a2 arc Define an arc around center point + closepath Close the open path from current point to first point + stroke Draw the any marks along the current path * PostScript comments + Begin with '%' character and run to end of line + First line in file must be "%!" so printers recognize PostScript file + UNIX files sometimes begin with 16-bit magic number to identify file type + "%%" is used for structural comments (see PostScript ref manual) * Tools for previewing a PostScript file + Save printer paper -- preview first! + PostScript programs must be interpreted - Ghostscript is an open source interpreter - Ghostscript interpreter (gsnd) can be run interactively without a display -- one way to play with stacks - Interactive interpretation is good for learning PostScript + Ghostscript previewer uses the Ghostscript interpreter, but actually renders a page to the display - Linux: gs and gsnd - Sun and Windows: gsview - Macintosh: MacGSview (OS 9), Panther Previewer (10.3) * On-line resources + PJD's PostScript tutorial + Adobe PostScript tutorial - "The Blue Book" - One of the best tutorials that I've ever read + Adobe PostScript language reference - "The Red Book" - Use it to get ideas for new primitives, info about graphics state + Links to PostScript tutorials on the WWW (including C-MU) Example program: Draws an X in the lower left corner of page %! newpath 72 72 moveto 144 144 lineto stroke newpath 72 144 moveto 72 -72 rlineto stroke showpage Example program: Define font and draw text %! /Helvetica findfont 12 scalefont setfont 72 72 moveto (A quick brown fox jumped over the lazy dog) show showpage Examples: Using gsnd to interact with the GhostScript interpreter 26 > gsnd GNU Ghostscript 6.52 (2001-10-20) Copyright (C) 2001 artofcode LLC, Benicia, CA. All rights reserved. This software comes with NO WARRANTY: see the file COPYING for details. GS>20 30 50 add sub = -60 GS>quit 27 > 29 > gsnd GNU Ghostscript 6.52 (2001-10-20) Copyright (C) 2001 artofcode LLC, Benicia, CA. All rights reserved. This software comes with NO WARRANTY: see the file COPYING for details. GS>10 20 30 40 stack 40 30 20 10 GS<4>pop GS<3>stack 30 20 10 GS<3>quit Project #2 -- A class for simple computer graphics * Overview + Abstraction/encapsulation of PostScript file concept - What does the interface make visible? * Coordinate space * Graphics primitives (similar to typical display primitives) * Make the interface look more like a typical graphics device - What does the interface hide? * Details of PostScript language * C++ file output - Why should we hide the details of the PostScript language? * It's tedious to generate all those primitives every time you want to draw a line -- increases our productivity and makes our programs more concise and compact * Eliminating the details makes PostScript programming less error prone + Explain interface + Explain main program to test the PSFile class * Two implementation approaches are possible + Emit PostScript equivalent PostScript primitives directly into the PostScript file + Emit procedure definitions in a prelude and then, later, emit calls to the procedures - How are procedures defined? Dictionaries! - Dictionaries hold both variables and procedure definitions - PostScript associates a value with a key by creating a dictionary entry (a key - value pair) - Variable example: /counter 1 def % Initialize the variable "counter" /counter counter 1 add def % Increment the count - How do we prevent execution of procedure body? Deferred execution - Procedure example: /average { add 2 div } def % Define procedure "average" 40 60 average % Call the procedure "average" - Dictionaries are stacked, so you can create nested scopes - Yes, PostScript has control constructs + Possible uses for procedure definition approach - Text or image decompression - Compact representation for object-oriented graphics - Adapt rendering for output device (accommodate differences between screen device resolution and printer resolution) ******************************************************************* %! % % Testing workflow diagram % % Display a string centered at the current point /showcentered { % Stack: string dup % Duplicate the string stringwidth % Get the string width and height pop % Discard the height 2 div % Compute half the string width neg 0 rmoveto % Move that distance to the left show % Show the string } def % Use arrow code from the PostScript Tutorial and Cookbook /arrowdict 14 dict def arrowdict begin /mtrx matrix def end % Stack: x1 y1 x2 y2 tail_thickness head_thickness arrowhead_length /arrow { arrowdict begin /headlength exch def /halfheadthickness exch 2 div def /halfthickness exch 2 div def /tipy exch def /tipx exch def /taily exch def /tailx exch def /dx tipx tailx sub def /dy tipy taily sub def /arrowlength dx dx mul dy dy mul add sqrt def /angle dy dx atan def /base arrowlength headlength sub def /savematrix mtrx currentmatrix def tailx taily translate angle rotate 0 halfthickness neg moveto base halfthickness neg lineto base halfheadthickness neg lineto arrowlength 0 lineto base halfheadthickness lineto base halfthickness lineto 0 halfthickness lineto closepath savematrix setmatrix end } def /Helvetica findfont 18 scalefont setfont 180 600 moveto (Test data \(test vector\)) showcentered newpath 180 590 180 560 2 8 8 arrow fill 180 540 moveto (System under test \(SUT\)) showcentered newpath 180 530 180 500 2 8 8 arrow fill 180 480 moveto (Actual test results) showcentered newpath 180 470 180 440 2 8 8 arrow fill 400 480 moveto (Known good \(KG\) results) showcentered newpath 2 setlinewidth 400 470 moveto 400 425 lineto stroke newpath 400 425 225 425 2 8 8 arrow fill 180 420 moveto (Compare) showcentered newpath 180 410 180 380 2 8 8 arrow fill newpath 180 380 70 320 2 8 8 arrow fill newpath 180 380 290 320 2 8 8 arrow fill 60 350 moveto (Same?) showcentered 60 300 moveto (PASS) showcentered 300 350 moveto (Different?) showcentered 300 300 moveto (FAIL) showcentered showpage