CS 3723/3721
Programming Languages

Overlapping Boxes

 


Example of overlapping boxes:
    This example is from the Blue Book, pages 23, 30, 31: three different Postscript programs produce exactly the same three overlapping boxes. The first program is basic Postscript with no functions. The second uses one function, while the third has three functions, each with parameters. Here are all three listings presented side-by-side, along with a fourth version illustrating parameters. It produces the same output and is explained in the next section):

    First Version Second Version Third Version Fourth Version
    %!PS-Adobe-2.0
    newpath % black
      252 324 moveto
      0 72 rlineto
      72 0 rlineto 
      0 -72 rlineto
      closepath
      fill
    newpath % dark
      270 360 moveto
      0 72 rlineto
      72 0 rlineto
      0 -72 rlineto
      closepath
      .4 setgray
      fill
    newpath % light
      288 396 moveto
      0 72 rlineto
      72 0 rlineto
      0 -72 rlineto
      closepath
      .8 setgray
      fill
    showpage % print
    
    %!PS-Adobe-2.0
    % Define box proc
    /box {
      72 0 rlineto
      0 72 rlineto
      -72 0 rlineto
      closepath
    } def
      
    % Begin Program
    newpath % black
      252 324 moveto box
      0 setgray fill
    newpath % dark
      270 360 moveto box
      .4 setgray fill
    newpath % light
      288 396 moveto box
      .8 setgray fill
    showpage
    
    %!PS-Adobe-2.0
    % Define procedures
    /inch {72 mul} def
    
    /box {
    % stack: x y => ---
      newpath moveto
      1 inch 0 rlineto
      0 1 inch rlineto
      -1 inch 0 rlineto
      closepath
    } def
      
    /fillbox {
    % stack: gray => ---
      setgray fill
    } def
    
    % Main Program
    3.5 inch 4.5 inch box
    0 fillbox
    3.75 inch 5 inch box
    .4 fillbox
    4 inch 5.5 inch box
    .8 fillbox
    showpage
    
    %!PS-Adobe-2.0
    % Define procedures
    /inch {72 mul} def
    
    /box { 
     % stack: x y => ---
      /y exch def % save
      /x exch def % save
      newpath x y moveto
      1 inch 0 rlineto
      0 1 inch rlineto
      -1 inch 0 rlineto
      closepath
    } def
      
    /fillbox {
     % stack: gray => ---
      setgray fill
    } def
    
    % Main Program
    3.5 inch 4.5 inch box
    0 fillbox
    3.75 inch 5 inch box
    .4 fillbox
    4 inch 5.5 inch box
    .8 fillbox
    showpage
    
    Result: box1.pdf Result: box2.pdf Result: box3.pdf Result: box4.pdf


How to handle parameters:
    The "Cookbook" part of the Bluebook shows a simple way to handle parameters in Postscript. Ordinarily parameters are passed by pushing them on the stack, and there is no support in the language for normal formal/actual parameters. This is illustrated in the third "Box" program above: "box3.ps", where the procedure box gets x and y coordinates passed to it on the stack, for use one time by the moveto function. But suppose you wanted to use those parameters a second time? In Postscript it is always possible to use dup and rotate to arrange to put extra copies of the parameters on the stack, but it is much simpler (and makes programming easier) to save the input parameters into named variables where they can easily be used as often as needed. The fourth box program above illustrates this, with the necessary additions in bold red. In the first case, for example, the code /y exch def % save will push the name y on the stack, then exchange this name with the value for y, and finally use def to pop both these and give y the desired value.

    If you save parameters inside variables in this way, the standard mistake is not to take the parameters off the stack in the opposite order from the order of insertion.


Boxes Gone Crazy:
    There are two examples below. On the left is code to generate an arbitrary-sized box with an arbitrary graylevel at an arbitrary location. It is illustrated with 4 boxes. On the right is code to generate 5555 random boxes of a random (bright) color.

4 Boxes, Rnd Graylevels 4 Boxes, Simplified 5555 Boxes, Random Bright Colors
%!PS-Adobe-2.0
/box { % stack: g
  setgray
  newpath 0 0 moveto
  72 0 rlineto
  0 72 rlineto
  -72 0 rlineto
  closepath fill
} def % box

/boxes { % st: x y r g
  gsave
    /g exch def
    /r exch def
    /y exch def
    /x exch def
    x y translate
    r dup scale
    g box
  grestore
} def % boxes

% x   y   r  g
 72 472   2  0.5 boxes

100 600 0.5  0   boxes
150 550 1.5  0.8 boxes
180 500 0.8  0   boxes

showpage
%!PS-Adobe-2.0
/box { % stack: g
  setgray
  newpath 0 0 moveto
  72 0 rlineto
  0 72 rlineto
  -72 0 rlineto
  closepath fill
} def % box

/boxes { % st:g r y x
  gsave
    translate
    dup scale
    box
  grestore
} def % boxes

% g   r   x   y 
0.5   2  72 472 boxes
  0 0.5 100 600 boxes
0.8 1.5 150 550 boxes
  0 0.8 180 500 boxes

showpage
%!PS-Adobe-2.0
/box { % stack: -
  mycolor setcmykcolor % random color
  newpath 0 0 moveto
  72 0 rlineto
  0 72 rlineto
  -72 0 rlineto
  closepath fill
} def % box

/boxes { % stack: r x y
  gsave
    translate
    dup scale
    % add below for box8.ps
    rd 90 mul rotate % random rotation
    box
  grestore
} def % boxes

/rd { rand 2147483647 div } def % 0 to 1
/mycolor {rd rd rd 0} def % bright
/r1 { % 0.1 to 4, weighted toward 0.1
  rd rd rd rd mul mul mul 3.9 mul 0.1 add
} def % r1
/x1 { rd 620 mul 10 sub } def % -10 - 610
/y1 { rd 820 mul 10 sub } def % -10 - 810

314158 srand
5555 { r1 x1 y1 boxes } repeat

showpage
Result: box5.pdf (2.4K) Result: box6.pdf (2.4K) Result: box7.pdf (138K), box8.pdf

    Above it was just one line added to get random rotated squares: box8.pdf (431K). A two-line change gives 10000 random parallelograms: box9.pdf (431K).

( Revision date: 2015-01-03. Please use ISO 8601, the International Standard Date and Time Notation.)