home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.postscript
- Path: sparky!uunet!gumby!wupost!micro-heart-of-gold.mit.edu!news.media.mit.edu!news
- From: mike@media-lab.mit.edu (Michael Hawley)
- Subject: quarto
- Message-ID: <1992Nov16.023153.29054@news.media.mit.edu>
- Sender: news@news.media.mit.edu (USENET News System)
- Reply-To: mike@media-lab.mit.edu
- Organization: MIT Media Laboratory
- Date: Mon, 16 Nov 1992 02:31:53 GMT
- Lines: 896
-
- There have been a few more requests for an "N-up" program
- (that works with embedded EPS illustrations)
- ways of listing pages, printing booklets in signatures, etc.
- Here's a simple one I use on the NeXT (known to work on other
- Unix machines).
- quarto -l your-dissertation.ps
- lists the pages, and
- quarto -2 your-nobel-prize-acceptance-speech.ps | lpr
- prints 2 pages per sheet.
- quarto -8 ... | quarto -3 | ...
- prints 8*3 = 24 little pages per sheet, if that's really what you want.
-
- - - - -
- /*
- * quarto.c
- *
- * Quickie program to filter PostScript (EPS) files and...
- * - extract selected pages
- * ... | quarto -p1,2,6-8 ... print those pages
- * - change page order (reverse, even, odd; etc)
- * ... | quarto -r ... print in reverse order
- * ... | quarto -p odd ... select the odd pages
- * - print "N-up" (quarto/octavo; N=2,3,4,6,8,9) layouts
- * ... | quarto -4 -c -b ... print 4 (small) pages per side
- *
- * For printing books or booklets in signatures, e.g.,
- * quarto -2 -S 4 ...
- * means that a signature is 4 sheets, 2 (small) pages per side.
- * The page ordering is such that you can run them through a copier
- * printing 2 pages onto 1 double-sided page (or take every other sheet,
- * flip it over, and glue it back to back on the previous sheet).
- *
- * Currently only tested and used with a NeXT printer + Letter-size
- paper,
- * with input in portrait orientation. It should be easy to fix for
- * other varieties; check PBox, the test pattern, the calculation of
- 'Scale',
- * and the macro 'pgx()' (used by the 'putNup()' routines). If you can
- * print out test patterns (the "-d" option) you're close if not
- working.
- *
- * Enjoy at your own peril, but please send me any improvements.
- *
- * Also, if you like this program and get good use out of it, consider
- * sending $4.37 to:
- * Bob Greene
- * Media Lab Crew Treasurer
- * MIT Media Lab
- * 20 Ames Street
- * Cambridge, MA 02139
- *
- * Say "Yo Bob! I'm dying to find out how your boys did at Henley.
- * Did they really row in the nude because you are too poor
- * to buy uniforms? Perhaps this miserly contribution will
- help."
- *
- *
- * M. J. Hawley
- * MIT media Laboratory
- * 20 Ames Street
- * Cambridge, MA 02139
- * mike@media-lab.mit.edu
- * Copyright (c) MIT Media Laboratory 1991.
- * Top secret! Burn before reading! This means you!!
- *
- *
- * Notes -- version 1.1
- *
- * - added signature printing and fixed the nested-page bug (November,
- 1992)
- */
- #include <stdio.h>
- #include <ctype.h>
- #include <sys/types.h>
-
- /*
- * Some general utilities ----------------------------------------
- */
- char *av0;
- #define Case break; case
- #define Default break; default
- static char *_arg, *_argp; /* use by 'for_each_argument */
- extern char *av0; /* will hold name of the command */
- #define argument (_arg=(*_argp? _argp : av[++i==ac? --i :
- i]),_argp+=strlen(_argp),_arg)
- #define for_each_argument av0 = av[0]; for (i=1;i<ac &&
- *av[i]=='-';i++)\
- for (_argp = &av[i][1]; *_argp;)\
- switch(*_argp++)
-
- extern char *malloc(), *index();
- extern int atoi();
- extern double atof();
-
- stripnl(s) char *s; { /* remove trailing \n and space from 's' */
- char *p = s + strlen(s)-1;
- while (p>s && (*p=='\n' || *p == ' ')) *p-- = '\0';
- }
-
- char *
- skipsp(s) char *s; {
- while (*s==' ' || *s=='\t' || *s == '\n') ++s;
- return s;
- }
-
- error(a,b,c,d,e,f) int a,b,c,d,e,f; { /* printf an error msg */
- fprintf(stderr,(char *)a,b,c,d,e,f); fprintf(stderr,"\n");
- }
-
- /* ---------------------------------------------------------------- */
-
- FILE *Input, *Output;
- char *CurFile;
-
- typedef struct { float x, y; } Point;
- typedef struct { Point o, c; } Rectangle;
- #define HS(r) (r.c.x-r.o.x)
- #define VS(r) (r.c.y-r.o.y)
-
- Rectangle BBox = { 0, 0, 612, 792 }; /* bbox of the document */
-
- Rectangle PBox = { 10, 14, 600, 780 }; /* Letter-sized page-bounding box
- */
- /* These values probably depend on the printer and
- * paper size; use the test pattern to adjust them for
- now.
- */
- Rectangle NullRect = {0,0,0,0};
-
- int TestPattern = 0; /* if true, overlay a test pattern on the page*/
- int ListPages = 0; /* if true, list pages in the document (no
- print) */
-
- #define _N_up 1
- int N_up = 1; /* default # pages to fit on a sheet */
-
- #define _Gutter 12.
- float Gutter= _Gutter;
- #define _CutMarks 0
- #define _Borders 1
- int CutMarks=_CutMarks, /* print cutmarks around shrunken pages */
- Borders=_Borders; /* print dashed borders around shrunken pages */
- int ReversePages = 0;
- int Signatures = 0; /* determine signature page order */
-
- float Scale = .45; /* Scale is normally set by the tiling routines;
- */
- int ScaleSet = 0; /* made a user option just in case. */
- int Rotate = 0; /* will be true when landscaping for -2,6,8 */
-
- #define MaxP 1024
- #define Trailer (MaxP-1)
- int Page[MaxP], PageLen[MaxP];
- Rectangle PageBbox[MaxP], pageBbox;
- int NP=0;
-
- findPageOffsets(){
- char s[4192], *s2=s+2;
- int i,prevpos=0,prevp=0,p,nested=0;
- FILE *f = Input;
-
- for(i=0;i<MaxP;i++){
- Page[i]=PageLen[i]=0;
- PageBbox[i] = NullRect;
- }
-
- rewind(f);
- while (fgets(s,sizeof s,f)){
- if (s[0]=='%' && s[1]=='%'){
- if (strncmp(s2,"BeginDocument",13)==0 ||
- strncmp(s2,"BeginBinary",11)==0){
- nested++;
- } else
- if (strncmp(s2,"EndDocument",11)==0 ||
- strncmp(s2,"EndBinary",9)==0){
- if (nested>0) nested--;
- } else
- if (nested==0){
- if (strncmp(s2,"Page:",5)==0){
- sscanf(s,"%%%%Page: %*s %d",&p);
- Page[p] = ftell(f)-strlen(s);
- PageLen[prevp] = Page[p] - prevpos;
- prevp = p;
- prevpos = Page[p];
- NP++;
- } else
- if (strncmp(s2,"Trailer",7)==0){
- Page[Trailer] = ftell(f)-strlen(s);
- PageLen[prevp] = Page[Trailer] - prevpos;
- prevpos = Page[Trailer];
- } else
- if (strncmp(s2,"BoundingBox:",12)==0){
- char *q = skipsp(index(s,':')+1);
- if (isdigit(*q))
- sscanf(q,"%f %f %f %f",
- &BBox.o.x,&BBox.o.y,&BBox.c.x,&BBox.c.y);
- } else
- if (strncmp(s2,"PageBoundingBox:",16)==0){
- Rectangle r;
- char *q = skipsp(index(s,':')+1);
- if (isdigit(*q)){
- sscanf(q,"%f %f %f %f", &r.o.x,&r.o.y,&r.c.x,&r.c.y);
- if (NP) PageBbox[NP] = r;
- }
- }
- }
- }
- }
- PageLen[Trailer] = ftell(f) - prevpos;
- pageBbox = PageBbox[1]; /* hack ... */
- /*
- * Some NeXT programs put out PageBoundingBoxes
- * with various origins for each page,
- * but draw relative to the *first* PageBoundingBox.
- * See "hack", below.
- */
- }
-
- showPageOffsets() {
- char s[4192];
- int i,j;
- FILE *f = Input;
-
- printf("file: %s, %d pages\n",CurFile,NP);
- printf("%8s %8s\n","offset","length");
- for (i=j=0;j<=NP;i++){
- if (Page[i] || i==0){
- fseek(f,Page[i],0);
- fgets(s,sizeof s,f);
- printf("%8d %8d -- %s%s",Page[i], PageLen[i],i?"":"(header)
- ",s);
- j++;
- }
- }
- fseek(f,Page[Trailer],0);
- fgets(s,sizeof s,f);
- printf("%8d %8d -- (trailer) %s",Page[Trailer],PageLen[Trailer],s);
- }
-
- static char *_s = (char *)0;
- static int _sn = 0;
-
- char *
- readPage(n){
- size_t r;
- if (_s) *_s = '\0';
- if (Page[n] || (n==0 && PageLen[n])){
- if (_sn < PageLen[n]){
- _sn = 2*PageLen[n];
- _s = (_s? (char *)realloc(_s,_sn) : (char *)malloc(_sn));
- if (!_s) error("%s: no memory!",av0), exit(1);
- }
- rewind(Input);
- fseek(Input,Page[n],0);
- *_s = '\0';
- fread(_s,PageLen[n], (size_t)1, Input);
- }
- return _s;
- }
-
- copyPage(n)
- /*
- * Write the 'n'th page in 'f' onto 'o'.
- */
- {
- char *s = readPage(n);
- if (*s) fwrite(s,PageLen[n],1,Output);
- }
-
- P(a,b,c,d,e,f,g,h,i){
- fprintf(Output,(char *)a,b,c,d,e,f,g,h,i);
- fprintf(Output,"\n");
- }
-
- putProlog(n){
- char *date, *ctime();
- time_t t;
-
- time(&t); date = ctime(&t); stripnl(date);
- P("%%!PS-Adobe-2.0");
- P("%%%%Creator: %s, file: %s",av0,CurFile);
- P("%%%%CreationDate: %s",date);
- P("%%%%Pages: (atend)",n);
- P("%%%%BoundingBox: 0 0 612 792"); /* should have options to set */
- P("%%%%EndComments");
- P("");
- P("%% ---------------------- (routines for \"%s\")",av0);
- P("/q_W %f def /q_H %f def /q_margin 4 def",BBox.c.x,BBox.c.y);
- P("/q_factor %f def",Scale);
- P("/q_bbox {");
- if (Borders){
- P(" /q_y 0 q_factor mul def");
- P(" /q_x 0 q_factor mul def");
- P(" /q_w q_W q_margin 2 mul add def");
- P(" /q_h q_H q_margin 2 mul add def");
- P(" q_x q_margin sub q_y q_margin sub moveto");
- P(" .2 setgray");
- P(" 0 setlinewidth");
- P(" q_w 0 rlineto");
- P(" 0 q_h rlineto");
- P(" 0 q_w sub 0 rlineto");
- P(" 0 0 q_h sub rlineto");
- P(" stroke");
- }
- P("} def");
- P("");
- P("/q_cuts {");
- if (CutMarks){
- P(" /q_y 0 q_factor mul q_margin sub def");
- P(" /q_x 0 q_factor mul q_margin sub def");
- P(" /q_w q_W q_margin 2 mul add def");
- P(" /q_h q_H q_margin 2 mul add def");
- P(" /q_d 10 q_factor mul def");
- P(" 0 setgray");
- P(" 0 setlinewidth");
- P(" q_x q_d sub q_y moveto -1 -1 rmoveto");
- P(" q_d 0 rlineto 0 0 q_d sub rlineto stroke");
- P(" q_x q_d add q_w add q_y moveto 1 -1 rmoveto");
- P(" 0 q_d sub 0 rlineto 0 0 q_d sub rlineto stroke");
- P(" q_x q_d add q_w add q_y q_h add moveto 1 1 rmoveto");
- P(" 0 q_d sub 0 rlineto 0 q_d rlineto stroke");
- P(" q_x q_d sub q_y q_h add moveto -1 1 rmoveto");
- P(" q_d 0 rlineto 0 0 q_d rlineto stroke");
- }
- P("} def");
- P("");
- P("/StartShrunkenPage {");
- P(" /q_y exch def /q_x exch def");
- P(" gsave");
- P(" q_x q_y translate");
- P(" q_factor q_factor scale");
- if (Rotate) P(" -90 rotate");
- P("} def");
- P("");
- P("/EndShrunkenPage {");
- P(" grestore");
- P("} def");
- P("");
- if (N_up!=1){
- P("/oldshowpage {showpage} bind def");
- P("/showpage { } bind def");
- }
- P("");
- P("/q_circ { %% x y size ... draw circle + crosshairs");
- P(" /q_size exch def /q_y exch def /q_x exch def");
- P(" 0 setlinewidth");
- P(" q_x q_y moveto");
- P(" q_size 0 rlineto");
- P(" -2 q_size mul 0 rlineto");
- P(" q_size 0 rlineto");
- P(" 0 q_size rlineto");
- P(" 0 -2 q_size mul rlineto");
- P(" stroke");
- P(" q_x q_y moveto");
- P(" q_x q_y q_size 2 div 0 360 arc stroke");
- P("} def");
- P("");
- P("/q_box { %% lx ly ux uy ... draw a box");
- P(" /q_uy exch def /q_ux exch def /q_ly exch def /q_lx exch
- def");
- P(" q_lx q_ly moveto");
- P(" q_ux q_ly lineto");
- P(" q_ux q_uy lineto");
- P(" q_lx q_uy lineto");
- P(" q_lx q_ly lineto");
- P(" stroke");
- P("} def");
- P("");
- P("/q_testPattern {");
- P(" 0 setgray 0 setlinewidth");
- P(" %f %f %f %f q_box", PBox.o.x,PBox.o.y,PBox.c.x,PBox.c.y);
- P(" %f %f moveto 8 0 rlineto stroke",
- PBox.o.x-4,VS(PBox)/2+PBox.o.y);
- P(" %f %f moveto -8 0 rlineto stroke",
- PBox.c.x+4,VS(PBox)/2+PBox.o.y);
- P(" %f %f moveto 0 8 rlineto stroke",
- HS(PBox)/2+PBox.o.x,PBox.o.y-4);
- P(" %f %f moveto 0 -8 rlineto stroke",
- HS(PBox)/2+PBox.o.x,PBox.c.y+4);
- P(" %f %f 5 q_circ",HS(PBox)/2+PBox.o.x,VS(PBox)/2+PBox.o.y);
- P("} def");
- P("");
- P("%% ----------------------(end of \"%s\" routines)\n",av0);
- copyPage(0); /* put out the previous document header page */
- }
-
- ShowPage(){
- if (TestPattern) P("q_testPattern");
- P("q_sheet restore\noldshowpage");
- }
-
- putTrailer(n){
- copyPage(Trailer);
- P("%%%%Pages: %d %d",n,n);
- }
-
- static Point
- center(r) Rectangle r; {
- Point c;
- c.x = HS(r)/2. + r.o.x;
- c.y = VS(r)/2. + r.o.y;
- return c;
- }
-
- static Point
- add(a,b) Point a,b; {
- a.x += b.x;
- a.y += b.y;
- return a;
- }
-
- static Point
- sub(a,b) Point a,b; {
- a.x -= b.x;
- a.y -= b.y;
- return a;
- }
-
- hideOriginalPages(s) char *s; {
- s[2] = 'p';
- while ((s = index(s,'\n')+1) != (char *)1)
- if (strncmp(s,"%%Page:",7)==0) s[2] = 'p';
- }
-
- pput(n,p) Point p; {
- char *s = readPage(n);
- Rectangle r;
- if (*s){
- hideOriginalPages(s);
- r = pageBbox; /* PageBbox[n]; ... Thus endeth the hack. */
- P("%f %f StartShrunkenPage",p.x,p.y);
- P("%f %f translate",-1.*Scale*r.o.x,-1.*Scale*r.o.y);
- fwrite(s,PageLen[n],1,Output);
- P("EndShrunkenPage");
- }
- }
-
- float
- fmin(a,b) float a,b; {
- return a<b? a : b;
- }
-
- #define maxQ 16
-
- #define up_decls \
- int i, j, N = (NP+(N_up-1))/N_up, page[maxQ];\
- float gap = Gutter;\
- Point c, p, g, b, q[maxQ];\
- g.x=g.y = gap/2.; b = BBox.c
-
- #define nup_init() c = center(PBox); \
- b.x *= Scale; b.y *= Scale; \
- putProlog(N)
-
- #define pgx(inc,d) pput(i*N_up+j+1,p); page[j] = *_s; q[j++]=p; p.d +=
- inc
- #define putbox() for (j=0; j<N_up;j++) \
- if (page[j])\
- P("%f %f StartShrunkenPage q_bbox q_cuts
- EndShrunkenPage",\
- q[j].x,q[j].y); \
- ShowPage()
-
-
- put2up(){
- up_decls;
-
- if (!ScaleSet)
- Scale =
- fmin((VS(PBox)/2.-(2.*gap))/b.x,((HS(PBox)-(2.*gap))/b.y));
- nup_init();
-
- for (i=0;i<N;i++){
- P("\n%%%%Page: %d %d\n/q_sheet save def",i+1,i+1);
- j = 0;
-
- p = c; p.y += g.x + b.x; p.x -= b.y/2.;
- pgx(-(gap+b.x),y);
- pgx(-(gap+b.x),y);
-
- putbox(); /* put out boxes, cut marks, & ShowPage */
- }
- return N;
- }
-
- put3up(){
- up_decls;
-
- if (!ScaleSet)
- Scale =
- fmin((VS(PBox)/3.-(2.*gap))/b.x,((HS(PBox)-(2.*gap))/b.y));
- nup_init();
-
- for (i=0;i<N;i++){
- P("\n%%%%Page: %d %d\n/q_sheet save def",i+1,i+1);
- j = 0;
-
- p = c; p.y += g.x + 1.5*b.x; p.x -= b.y/2.;
- pgx(-(gap+b.x),y);
- pgx(-(gap+b.x),y);
- pgx(-(gap+b.x),y);
-
- putbox(); /* put out boxes, cut marks, & ShowPage */
- }
- return N;
- }
-
- put6up(){
- up_decls;
-
- if (!ScaleSet)
- Scale =
- fmin((VS(PBox)/3.-(2.*gap))/b.x,((HS(PBox)/2.-(2.*gap))/b.y));
- nup_init();
-
- for (i=0;i<N;i++){
- P("\n%%%%Page: %d %d\n/q_sheet save def",i+1,i+1);
- j = 0;
-
- p = c; p.y += gap + 1.5*b.x; p.x += g.x;
- pgx(-(gap+b.x),y);
- pgx(-(gap+b.x),y);
- pgx(-(gap+b.x),y);
-
- p = c; p.y += gap + 1.5*b.x; p.x -= g.x + b.y;
- pgx(-(gap+b.x),y);
- pgx(-(gap+b.x),y);
- pgx(-(gap+b.x),y);
-
- putbox(); /* put out boxes, cut marks, & ShowPage */
- }
- return N;
- }
-
- put8up(){
- up_decls;
-
- if (!ScaleSet)
- Scale =
- fmin((VS(PBox)/4.-(2.*gap))/b.x,((HS(PBox)/2.-(2.*gap))/b.y));
- nup_init();
-
- for (i=0;i<N;i++){
- P("\n%%%%Page: %d %d\n/q_sheet save def",i+1,i+1);
- j = 0;
-
- p = c; p.y += 1.5*gap + 2.*b.x; p.x += g.x;
- pgx(-(gap+b.x),y);
- pgx(-(gap+b.x),y);
- pgx(-(gap+b.x),y);
- pgx(-(gap+b.x),y);
-
- p = c; p.y += 1.5*gap + 2.*b.x; p.x -= g.x + b.y;
- pgx(-(gap+b.x),y);
- pgx(-(gap+b.x),y);
- pgx(-(gap+b.x),y);
- pgx(-(gap+b.x),y);
-
- putbox(); /* put out boxes, cut marks, & ShowPage */
- }
- return N;
- }
-
- put4up(){
- up_decls;
-
- if (!ScaleSet)
- Scale =
- 5*fmin((HS(PBox)-(2.*gap))/b.x,(VS(PBox)-(2.*gap))/b.y);
- nup_init();
-
- for (i=0;i<N;i++){
- P("\n%%%%Page: %d %d\n/q_sheet save def",i+1,i+1);
- j = 0;
-
- p = c; p.x -= g.x + b.x; p.y += g.y;
- pgx(gap+b.x,x);
- pgx(gap+b.x,x);
- p = c; p.x -= g.x + b.x; p.y -= g.y + b.y;
- pgx(gap+b.x,x);
- pgx(gap+b.x,x);
-
- putbox(); /* put out boxes, cut marks, & ShowPage */
- }
- return N;
- }
-
- put9up(){
- up_decls;
-
- if (!ScaleSet)
- Scale =
- 333*fmin((HS(PBox)-(3.*gap))/b.x,(VS(PBox)-(2.*gap))/b.y);
- nup_init();
-
- for (i=0;i<N;i++){
- P("\n%%%%Page: %d %d\n/q_sheet save def",i+1,i+1);
- j = 0;
-
- p = c; p.x -= g.x + 1.5*b.x; p.y += g.y + .5*b.y;
- pgx(g.x+b.x,x);
- pgx(g.x+b.x,x);
- pgx(g.x+b.x,x);
-
- p = c; p.x -= g.x + 1.5*b.x; p.y -= .5*b.y;
- pgx(g.x+b.x,x);
- pgx(g.x+b.x,x);
- pgx(g.x+b.x,x);
-
- p = c; p.x -= g.x + 1.5*b.x; p.y -= g.y + 1.5*b.y;
- pgx(g.x+b.x,x);
- pgx(g.x+b.x,x);
- pgx(g.x+b.x,x);
-
- putbox(); /* put out boxes, cut marks, & ShowPage */
- }
- return N;
- }
-
- putpages(){
- int i;
- char *s, *p, *index();
-
- putProlog(NP);
- for (i=1;i<=NP;i++){
- s = readPage(i);
- if (*s){
- p = index(s,'\n');
- if (p){
- p+1;
- fprintf(Output,"%%%%Page: %d %d\n",i,i);
- fwrite(p,PageLen[i] - (p-s),1,Output);
- fprintf(Output,"q_bbox\n");
- }
- } else { /* emit blank page, e.g., for signatures */
- fprintf(Output,"%%%%Page: %d %d\n",i,i);
- fprintf(Output,"q_bbox\n");
- }
- }
- }
-
- char *SelectPages = (char *)0;
-
- ReorderPages(){
- int i,j;
- int pages[MaxP], po[MaxP], pl[MaxP], np=0;
- Rectangle pr[MaxP];
-
- bzero(pages,sizeof(pages));
-
- if (SelectPages){
- char *s = skipsp(SelectPages);
- int start=0,end;
- while (*s){
- if (strncmp(s,"even",4)==0){
- for (i=2;i<=NP;i+=2) pages[np++]=i;
- s+=4;
- } else
- if (strncmp(s,"odd",3)==0){
- for (i=1;i<=NP;i+=2) pages[np++]=i;
- s+=3;
- } else
- if (strncmp(s,"blank",5)==0){
- pages[np++]=NP+1;
- s+=5;
- } else
- if (strncmp(s,"all",3)==0){
- for (i=1;i<=NP;i++) pages[np++]=i;
- s+=3;
- } else
- if (*s == '-'){
- start = 1;
- ++s;
- end = atoi(s);
- while (isdigit(*s)) ++s;
- for (i=start;i<=end;i++) pages[np++] = i;
- } else
- if (isdigit(*s)){
- pages[np++] = atoi(s);
- while (isdigit(*s) || isspace(*s)) ++s;
- if (*s == '-'){
- ++s;
- while (*s && !isdigit(*s)) ++s;
- end = *s? atoi(s) : NP;
- while (*s && isdigit(*s)) ++s;
- for (i=pages[np-1]+1;i<=end;i++) pages[np++] = i;
- }
- } else
- ++s;
- while (*s== ',' || *s=='-' || isspace(*s)) ++s;
- }
- for (i=0;i<np;i++){
- po[i] = Page[pages[i]];
- pl[i] = PageLen[pages[i]];
- pr[i] = PageBbox[pages[i]];
- }
- for (i=0;i<np;i++){
- Page[i+1] = po[i];
- PageLen[i+1] = pl[i];
- PageBbox[i+1] = pr[i];
- }
- for (i=np+1;i<=NP;i++) Page[i] = PageLen[i] = 0;
- NP = np;
- } else
- for (i=0;i<NP;i++) pages[i] = i+1;
- if (ReversePages){
- #define swap(t, a,b) t = a; a = b; b = t
- for (i=1,j=NP; i<j; i++,j--){
- int t;
- Rectangle r;
- swap(t, pages[i],pages[j]);
- swap(t, Page[i],Page[j]);
- swap(t, PageLen[i],PageLen[j]);
- swap(r,PageBbox[i],PageBbox[j]);
- }
- }
- if (Signatures){
- /* reorder appropriately for 2-sided signatures of
- 'Signature' sheets per packet.
- With signatures of 2 sheets, a page ordering of
- 1 2 3 4 5 6 7 8 9 10 11 12 . . .
- becomes
- 8 1 2 7 6 3 4 5 16 9 10 15 . . .
- */
- int i, p, s, *P, tmp, PP, page[MaxP];
- int SidesPerSig = Signatures*2,
- PagesPerSig = SidesPerSig*2,
- NumSigs = (NP + PagesPerSig - 1) / PagesPerSig;
- bzero(page,sizeof(page));
- for (s=0,i=0; s<NumSigs; s++){
- for (p=0, P = page+s*PagesPerSig+1;p<SidesPerSig;p++, P+=2)
- *P = pages[i++];
- for (p=0, P-=3 ;p<SidesPerSig;p++, P-=2)
- *P = pages[i++];
- for (p=0, P=page+s*PagesPerSig+2; p<PagesPerSig;p++,P+=4)
- tmp=P[0],P[0]=P[1],P[1]=tmp;
- }
- PP = NP; NP = PagesPerSig*NumSigs;
- for (i=0;i<NP;i++) if (page[i]>PP || !page[i]) page[i]=NP;
-
- for (i=0;i<NP;i++){
- po[i+1] = Page[page[i]];
- pl[i+1] = PageLen[page[i]];
- pr[i+1] = PageBbox[page[i]];
- }
- for (i=0;i<NP;i++){
- Page[i+1] = po[i+1];
- PageLen[i+1] = pl[i+1];
- PageBbox[i+1] = pr[i+1];
- }
- fprintf(stderr,"%d %d-page signatures:\n ",NumSigs,Signatures);
- for (i=0;i<NP;i++){
- if (i && i%4 == 0) fprintf(stderr," ");
- if (i && i%PagesPerSig == 0) fprintf(stderr,"\n ");
- if (page[i]==NP)
- fprintf(stderr," . ");
- else
- fprintf(stderr,"%2d ",page[i]);
- }
- fprintf(stderr,"\n");
- }
- }
-
- doFile(s) char *s; {
- FILE *f = fopen(s,"r");
- int n;
- if (!f) return error("%s: couldn't open %s",av0,s);
- Input = f;
- findPageOffsets();
-
- if (ListPages)
- showPageOffsets();
- else {
- ReorderPages();
-
- switch (N_up){
- case 2: n=put2up();
- Case 3: n=put3up();
- Case 4: n=put4up();
- Case 6: n=put6up();
- Case 8: n=put8up();
- Case 9: n=put9up();
- Default:n=putpages();
- }
-
- putTrailer(n);
- }
- fclose(f);
- }
-
- savetmp(s,f) char *s; FILE *f;
- /*
- * Copy 'f' into a tmp file; put the name in s,
- * and return 1 if success.
- */
- {
- FILE *o;
- int n, F, O;
- char b[8192];
- strcpy(s,"/tmp/quartoXXXXXX");
- mktemp(s);
- strcat(s,".eps");
- if (o = fopen(s,"w")){
- F = fileno(f);
- O = fileno(o);
- while ((n=read(F,b,sizeof b))>0)
- write(O,b,n);
- fclose(o);
- return 1;
- } else
- return 0;
- }
-
- use(){
- error("use: %s [-[234689]] [-p <pages>] [-S #] [-bcdlr] [-g #] [PS
- file]",av0);
- error("Select pages from a PostScript file, and print in a tiled
- format.");
- error("(The input must contain EPS-like directives
- '%%%%Page:...')");
- error(" -p... print the given pages; e.g., '-p1,2,4-8,12-'");
- error(" '-p -4' prints through page four;");
- error(" '-p 12-' prints from page 12 through the end;");
- error(" numbers are original ordinal page numbers, starting
- at 1");
- error(" also, '-p even', '-p odd', '-p1-4,1-4,1-4,1-4'
- etc.");
- error(" 'blank' or 0 inserts a blank page; 'all' inserts all
- the pages");
- error(" -2 print 2 tiled, shrunken pages per page;");
- error(" # may be 2,3,4,6,8 or 9 (default 1);");
- error(" portrait or landscape layout will be chosen
- accordingly.");
- error(" -b %sprint borders around each tiled page.",
- _Borders?"don't ":"");
- error(" -c %sprint cut-marks for each tiled page.",
- _CutMarks?"don't ":"");
- error(" -d overlay a test pattern on the page.");
- error(" (a box around the paper sheet border, ");
- error(" and a circle and cross in the middle;");
- error(" intended to help calibrate for different
- printers)");
- error(" -S # reorder pages to print them in signatures of #
- sheets;");
- error(" e.g., '-2 -S 3' prints pages 2-up per page for
- signatures");
- error(" of 3 double-sided sheets that will be folded and
- bound together.");
- error(" -g # set the gap between tiles to # (%3f)",_Gutter);
- error(" -l list the pages+offsets (don't output any
- PostScript).");
- error(" -r reverse the page order");
- exit(1);
- }
-
- main(ac,av) char *av[]; {
- int i;
-
- for_each_argument {
- case 'l': ListPages = 1;
- Case 'p': SelectPages = argument;
- Case 'r': ReversePages = 1;
- Case 'd': TestPattern = !TestPattern;
- Case 'c': CutMarks = !CutMarks;
- Case 'b': Borders = !Borders;
- Case '1': N_up = 1;
- Case '2': N_up = 2; Rotate = 1;
- Case '3': N_up = 3; Rotate = 1;
- Case '4': N_up = 4;
- Case '6': N_up = 6; Rotate = 1;
- Case '8': N_up = 8; Rotate = 1;
- Case '9': N_up = 9;
- Case 'g': Gutter = atof(argument);
- Case 's': Scale = atof(argument); ScaleSet++; /* not mentioned as
- option */
- Case 'S': Signatures = atof(argument);
- if (N_up != 2)
- error("You may want to specify -2 sheets per page.");
- Default : use();
- }
-
- Output = stdout;
- if (i==ac){
- char s[1024];
- if (savetmp(s,stdin))
- CurFile="stdin", doFile(s), unlink(s);
- else
- error("%s: couldn't save stdin to a tmp file.",av0),
- exit(1);
- } else
- if ((i+1)==ac)
- CurFile=av[i], doFile(av[i++]);
- else
- error("%s: accepts only one file, or stdin...\n",av0), use();
- exit(0);
- }
-