plan9port

[fork] Plan 9 from user space
git clone git://src.adamsgaard.dk/plan9port # fast
git clone https://src.adamsgaard.dk/plan9port.git # slow
Log | Files | Refs | README | LICENSE Back to index

forms.ps (6060B)


      1 %
      2 % Procedures that let you print any number of pages on each sheet of paper. It's
      3 % far from perfect and won't handle everything (eg. it's not recursive), but should
      4 % be good enough for now. Assumes the default page coordinate system has been set
      5 % up before setupforms is called. lastpage makes certain the last page is printed,
      6 % and should be called immediately after the %%Trailer comment.
      7 %
      8 % Three lines of code needed for page image clipping have been commented out for
      9 % now. It works, but can really slow things down on some versions of PostScript.
     10 % Uncomment them if you want to clip pages.
     11 %
     12 
     13 /setupforms {
     14     /formsperpage exch def
     15 
     16     /currentform 0 def
     17     /slop 5 def
     18     /min {2 copy gt {exch} if pop} def
     19 
     20 %
     21 % Save the current environment so the real showpage can be restored when we're all
     22 % done. Occasionally helps when a banner page is included with the job.
     23 %
     24 
     25     /saveobj save def
     26 
     27 %
     28 % Number of rows and columns we'll need - may exchange them later.
     29 %
     30 
     31     /columns formsperpage sqrt ceiling cvi def
     32     /rows formsperpage columns div ceiling cvi def
     33 
     34 %
     35 % Slop leaves a little room around the edge so page images can be outlined and have
     36 % the borders show up. Distance is in default coordinates, so we need to figure out
     37 % how it maps into user coordinates.
     38 %
     39 
     40     6 array defaultmatrix
     41     6 array currentmatrix
     42     6 array invertmatrix
     43     6 array concatmatrix
     44     /tempmatrix exch def
     45 
     46     0 slop tempmatrix dtransform dup mul exch dup mul add sqrt
     47     /slop exch def
     48 
     49 %
     50 % Determine how big the image area is, using the clipping path bounding box minus
     51 % a little and leave the coordinates of the lower left corner of the clipping path
     52 % on the stack. Also temporarily set the size of each page (ie. formheight and
     53 % formwidth) from the clipping path - just in case old software uses this stuff.
     54 % Only works for coordinate systems that have been rotated by a multiple of 90
     55 % degrees.
     56 %
     57 
     58     newpath clippath pathbbox
     59     2 index sub dup /formheight exch def slop 2 mul sub /pageheight exch def
     60     2 index sub dup /formwidth exch def slop 2 mul sub /pagewidth exch def
     61 
     62 %
     63 % New translators all store the size of each page in default coordinates in the
     64 % pagebbox array and it can be different than the size determined by the clipping
     65 % path. If we can find pagebbox use it to set the real dimensions of each page.
     66 % Leaves the coordinates of the lower left corner on the stack, (either from
     67 % pagebbox or clippath) so four numbers are there when we're done.
     68 %
     69 
     70     userdict /gotpagebbox known userdict /pagebbox known and {
     71 	newpath
     72 	pagebbox 0 get pagebbox 1 get tempmatrix transform moveto
     73 	pagebbox 0 get pagebbox 3 get tempmatrix transform lineto
     74 	pagebbox 2 get pagebbox 3 get tempmatrix transform lineto
     75 	pagebbox 2 get pagebbox 1 get tempmatrix transform lineto
     76 	closepath pathbbox
     77 	2 index sub /formheight exch def
     78 	2 index sub /formwidth exch def
     79     } {2 copy} ifelse
     80 
     81 %
     82 % Top two numbers are the displacement from the job's origin to the lower left
     83 % corner of each page image when we finish setting up the new coordinate system.
     84 %
     85 
     86     /ycorner exch def
     87     /xcorner exch def
     88 
     89 %
     90 % The two numbers left on the stack are the coordinates of the lower left corner
     91 % of the clipping path. Go there and then up a bit so page images can be outlined.
     92 %
     93 
     94     translate
     95     slop slop translate
     96 
     97 %
     98 % If the page is wider than high we may be able to do better if we exchange rows
     99 % and columns. Won't make a difference in the current orientation or if rows and
    100 % columns are the same.
    101 %
    102 
    103     pagewidth pageheight gt {
    104 	rows columns /rows exch def /columns exch def
    105     } if
    106 
    107 %
    108 % Find the orientation and scaling that makes things as large as possible. More
    109 % than what's really needed. First calculation essentially finds the minimum of
    110 % 1/rows and 1/columns.
    111 %
    112 
    113     pagewidth formwidth columns mul div pageheight formheight rows mul div min
    114     pageheight formwidth columns mul div pagewidth formheight rows mul div min
    115 
    116     2 copy lt {
    117 	rotation 1 eq {
    118 	    landscape {
    119 		0 pageheight translate
    120 		-90 rotate
    121 	    }{
    122 		pagewidth 0 translate
    123 		90 rotate
    124 	    } ifelse
    125 	}{
    126 	    landscape {
    127 		pagewidth 0 translate
    128 		90 rotate
    129 	    }{
    130 		0 pageheight translate
    131 		-90 rotate
    132 	    } ifelse
    133 	} ifelse
    134 	pagewidth pageheight /pagewidth exch def /pageheight exch def
    135 	exch
    136     } if
    137 
    138 %
    139 % Second number from the top is the best choice. Scale so everything will fit on
    140 % the current page, go back to the original origin, and then get ready for the
    141 % first page - which goes in the upper left corner.
    142 %
    143 
    144     pop dup dup scale
    145     xcorner neg ycorner neg translate
    146     0 rows 1 sub formheight mul translate
    147 
    148 %
    149 % Try to center everything on the page - scaling we used is on top of the stack.
    150 %
    151 
    152     dup pagewidth exch div formwidth columns mul sub 2 div
    153     exch pageheight exch div formheight rows mul sub 2 div translate
    154 
    155 %
    156 % Redefine showpage.
    157 %
    158 
    159     /!PreForms~showpage~ /showpage load def		% save current showpage
    160 
    161     /showpage {
    162 	saveobj restore
    163 %	initclip
    164 	formsperpage 1 gt {
    165 	    gsave .1 setlinewidth outlineform stroke grestore
    166 	} if
    167 	formwidth 0 translate
    168 	/currentform currentform 1 add def
    169 	currentform columns mod 0 eq {
    170 	    columns formwidth mul neg formheight neg translate
    171 	} if
    172 	currentform formsperpage mod 0 eq {
    173 	    gsave !PreForms~showpage~ grestore
    174 	    currentform columns mod formwidth mul neg
    175 	    formsperpage columns idiv formheight mul translate
    176 	    /currentform 0 def
    177 	} if
    178 %	outlineform clip newpath
    179 	/saveobj save def
    180     } bind def
    181 
    182     /outlineform {
    183 	newpath
    184 	xcorner ycorner moveto
    185 	formwidth 0 rlineto
    186 	0 formheight rlineto
    187 	formwidth neg 0 rlineto
    188 	closepath
    189     } bind def
    190 
    191     /lastpage {
    192 	formsperpage 1 gt {
    193 	    currentform 0 ne {
    194 		/saveobj save def
    195 		0 1 formsperpage currentform sub formsperpage mod {
    196 		    pop showpage
    197 		} for
    198 		saveobj restore
    199 	    } if
    200 	    saveobj restore
    201 	    saveobj restore
    202 	} if
    203     } def
    204 
    205 %
    206 % Clip the first page image and save the environment we just set up, including
    207 % the redefined showpage.
    208 %
    209 
    210 %   outlineform clip
    211     newpath
    212     /saveobj save def
    213 } def