The PostScript
What is it that is necessary to print in two-up mode?
First, we need to translate and rotate each page into the right
location of the page, then we need to make sure that the page fits in
the new area reserved for it (we will need to scale it down to about
half its original size).
If we place the two pages side by side, we will get proper two-up
form.
The code I will present here will place the odd pages on the left (as your looking at the page in landscape orientation) and the even pages on the right. You could do it the other way around, if that makes more sense to you.
Here is the code we must wrap around the odd pages:
gsave 504 30 translate % Position page in middle of region 90 rotate % Aim it in the right direction .5 .5 scale % make it small enough % original page code here... grestoreAnd here is the code for the even pages:
gsave 504 426 translate % Position page in middle of region 90 rotate % Aim it in the right direction .5 .5 scale % make it small enough % original page code here... grestoreNow, you will notice that I used some curious numbers in the translate command. The reason I chose these particular numbers was that I wanted to center each page in its half of the page. I knew I was going to scale by 0.5, so I computed how much whitespace was left and added in the appropriate fudge-factor to center the pages.
You may also notice that I wrap a gsave and a grestore around the page and the additional code? The reason for this is that each page must leave the state of the printer unchanged when it has been printed. If you permanently change the state, that state change will be in affect for all subsequent pages. By following this rule, you make the pages independent of order. Some print servers must shuffle page order in order to print the document correctly; since my pages are independent (at least as far as my code is concerned), they will print correctly.
The Hard Part
Now comes the hard part of recognizing where the pages begin.
The technique is essentially the same as what we used for
galley proofs, so I will spare you the
logic here.
Essentially, we will look for %%Page: comments.
We will, however, need to keep track of whether the current page is an
odd page or an even page and insert the correct translation code.
Also, as before, we must be careful about inserting grestores before
subsequent pages and before the %%Trailer or
%%EOF comments.
Here is the PERL script to do the job:
#!/usr/local/bin/perl $flag = 0; # We have not yet found a page $even = 0; # First page is an odd page $page = 1; # Start at page #1 $pages = 1; # Allow %%Pages comment while (<>) { if (/^%%Pages:/ && $pages) { print "%%Pages: (atend)\n"; $pages = 0; } elsif (/^%%Page:/) { # We have found a page if ($flag) { print "restore\n"; # restore if it isn't the first } $flag = 1; if ($even) { # Translate for even pages print "save\n"; # gsave print "504 426 translate\n"; $even = 0; $page++; } else { # Translate for odd pages printf("%%%%Page: %d %d\n", $page, $page); print "save /showpage {} def\n"; print "504 30 translate\n"; $even = 1; } # Code to rotate and shrink print "90 rotate .5 .5 scale\n"; } elsif (/^%%Trail/) { # Cleanup if a %%Trailer is found if ($flag) { print "restore\n"; } print $_; printf("%%%%Pages: %d\n", $page); $flag = 0; } elsif (/^%%EOF/) { # Cleanup if an %%EOF is found if ($flag) { print "restore\n"; } print $_; $flag = 0; } else { print; } }Note the basic similarity with the script for the galley proofs. There are some additions, however. Because we are taking two pages and printing them on one page, we need to modify the page numbers. The %%Pages: comment specifies how many pages are in the document. If you specify "%%Pages: (atend)", you are specifying that you do not know the exact number of pages, but you will give the information later.
An additional complication is the use of
save and
restore
rather than
gsave
grestore.
These operators save the entire state of the printer and
restore it just as gsave and grestore work with the graphics
state. In fact, an implicit gsave is done by save; and an implicit
grestore is done by restore.
The reason these are used is so that I can redefine
showpage
to a do-nothing procedure (/showpage {} def
) for the
odd pages.
This trick prevents the page from being ejected when the odd page does its
end of page routines.
Unfortunately, this trick only works if the document calls showpage by
name. If the document bound showpage up or calls some of the lower
level operators, this program would need to be more sophisticated.