aboutsummaryrefslogtreecommitdiff
path: root/postscript/prologues/forms.ps
diff options
context:
space:
mode:
Diffstat (limited to 'postscript/prologues/forms.ps')
-rw-r--r--postscript/prologues/forms.ps213
1 files changed, 213 insertions, 0 deletions
diff --git a/postscript/prologues/forms.ps b/postscript/prologues/forms.ps
new file mode 100644
index 00000000..a96fcdae
--- /dev/null
+++ b/postscript/prologues/forms.ps
@@ -0,0 +1,213 @@
+%
+% Procedures that let you print any number of pages on each sheet of paper. It's
+% far from perfect and won't handle everything (eg. it's not recursive), but should
+% be good enough for now. Assumes the default page coordinate system has been set
+% up before setupforms is called. lastpage makes certain the last page is printed,
+% and should be called immediately after the %%Trailer comment.
+%
+% Three lines of code needed for page image clipping have been commented out for
+% now. It works, but can really slow things down on some versions of PostScript.
+% Uncomment them if you want to clip pages.
+%
+
+/setupforms {
+ /formsperpage exch def
+
+ /currentform 0 def
+ /slop 5 def
+ /min {2 copy gt {exch} if pop} def
+
+%
+% Save the current environment so the real showpage can be restored when we're all
+% done. Occasionally helps when a banner page is included with the job.
+%
+
+ /saveobj save def
+
+%
+% Number of rows and columns we'll need - may exchange them later.
+%
+
+ /columns formsperpage sqrt ceiling cvi def
+ /rows formsperpage columns div ceiling cvi def
+
+%
+% Slop leaves a little room around the edge so page images can be outlined and have
+% the borders show up. Distance is in default coordinates, so we need to figure out
+% how it maps into user coordinates.
+%
+
+ 6 array defaultmatrix
+ 6 array currentmatrix
+ 6 array invertmatrix
+ 6 array concatmatrix
+ /tempmatrix exch def
+
+ 0 slop tempmatrix dtransform dup mul exch dup mul add sqrt
+ /slop exch def
+
+%
+% Determine how big the image area is, using the clipping path bounding box minus
+% a little and leave the coordinates of the lower left corner of the clipping path
+% on the stack. Also temporarily set the size of each page (ie. formheight and
+% formwidth) from the clipping path - just in case old software uses this stuff.
+% Only works for coordinate systems that have been rotated by a multiple of 90
+% degrees.
+%
+
+ newpath clippath pathbbox
+ 2 index sub dup /formheight exch def slop 2 mul sub /pageheight exch def
+ 2 index sub dup /formwidth exch def slop 2 mul sub /pagewidth exch def
+
+%
+% New translators all store the size of each page in default coordinates in the
+% pagebbox array and it can be different than the size determined by the clipping
+% path. If we can find pagebbox use it to set the real dimensions of each page.
+% Leaves the coordinates of the lower left corner on the stack, (either from
+% pagebbox or clippath) so four numbers are there when we're done.
+%
+
+ userdict /gotpagebbox known userdict /pagebbox known and {
+ newpath
+ pagebbox 0 get pagebbox 1 get tempmatrix transform moveto
+ pagebbox 0 get pagebbox 3 get tempmatrix transform lineto
+ pagebbox 2 get pagebbox 3 get tempmatrix transform lineto
+ pagebbox 2 get pagebbox 1 get tempmatrix transform lineto
+ closepath pathbbox
+ 2 index sub /formheight exch def
+ 2 index sub /formwidth exch def
+ } {2 copy} ifelse
+
+%
+% Top two numbers are the displacement from the job's origin to the lower left
+% corner of each page image when we finish setting up the new coordinate system.
+%
+
+ /ycorner exch def
+ /xcorner exch def
+
+%
+% The two numbers left on the stack are the coordinates of the lower left corner
+% of the clipping path. Go there and then up a bit so page images can be outlined.
+%
+
+ translate
+ slop slop translate
+
+%
+% If the page is wider than high we may be able to do better if we exchange rows
+% and columns. Won't make a difference in the current orientation or if rows and
+% columns are the same.
+%
+
+ pagewidth pageheight gt {
+ rows columns /rows exch def /columns exch def
+ } if
+
+%
+% Find the orientation and scaling that makes things as large as possible. More
+% than what's really needed. First calculation essentially finds the minimum of
+% 1/rows and 1/columns.
+%
+
+ pagewidth formwidth columns mul div pageheight formheight rows mul div min
+ pageheight formwidth columns mul div pagewidth formheight rows mul div min
+
+ 2 copy lt {
+ rotation 1 eq {
+ landscape {
+ 0 pageheight translate
+ -90 rotate
+ }{
+ pagewidth 0 translate
+ 90 rotate
+ } ifelse
+ }{
+ landscape {
+ pagewidth 0 translate
+ 90 rotate
+ }{
+ 0 pageheight translate
+ -90 rotate
+ } ifelse
+ } ifelse
+ pagewidth pageheight /pagewidth exch def /pageheight exch def
+ exch
+ } if
+
+%
+% Second number from the top is the best choice. Scale so everything will fit on
+% the current page, go back to the original origin, and then get ready for the
+% first page - which goes in the upper left corner.
+%
+
+ pop dup dup scale
+ xcorner neg ycorner neg translate
+ 0 rows 1 sub formheight mul translate
+
+%
+% Try to center everything on the page - scaling we used is on top of the stack.
+%
+
+ dup pagewidth exch div formwidth columns mul sub 2 div
+ exch pageheight exch div formheight rows mul sub 2 div translate
+
+%
+% Redefine showpage.
+%
+
+ /!PreForms~showpage~ /showpage load def % save current showpage
+
+ /showpage {
+ saveobj restore
+% initclip
+ formsperpage 1 gt {
+ gsave .1 setlinewidth outlineform stroke grestore
+ } if
+ formwidth 0 translate
+ /currentform currentform 1 add def
+ currentform columns mod 0 eq {
+ columns formwidth mul neg formheight neg translate
+ } if
+ currentform formsperpage mod 0 eq {
+ gsave !PreForms~showpage~ grestore
+ currentform columns mod formwidth mul neg
+ formsperpage columns idiv formheight mul translate
+ /currentform 0 def
+ } if
+% outlineform clip newpath
+ /saveobj save def
+ } bind def
+
+ /outlineform {
+ newpath
+ xcorner ycorner moveto
+ formwidth 0 rlineto
+ 0 formheight rlineto
+ formwidth neg 0 rlineto
+ closepath
+ } bind def
+
+ /lastpage {
+ formsperpage 1 gt {
+ currentform 0 ne {
+ /saveobj save def
+ 0 1 formsperpage currentform sub formsperpage mod {
+ pop showpage
+ } for
+ saveobj restore
+ } if
+ saveobj restore
+ saveobj restore
+ } if
+ } def
+
+%
+% Clip the first page image and save the environment we just set up, including
+% the redefined showpage.
+%
+
+% outlineform clip
+ newpath
+ /saveobj save def
+} def