aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/postscript/psfiles/forms.ps
blob: a96fcdaefc7b90f4d64ee17809ea02d944092a84 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
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