forms.ps 5.9 KB

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