|
|
1.1 root 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.