2 * Copyright (C) Angus J. C. Duggan 1991-1995
3 * See file LICENSE for details.
5 * page spec routines for page rearrangement
18 /* create a new page spec */
19 PageSpec
*newspec(void)
21 PageSpec
*temp
= (PageSpec
*)malloc(sizeof(PageSpec
));
23 message(FATAL
, "out of memory\n");
24 temp
->reversed
= temp
->pageno
= temp
->flags
= temp
->rotate
= 0;
26 temp
->xoff
= temp
->yoff
= 0;
31 /* dimension parsing routines */
32 int parseint(char **sp
, void (*errorfn
)(void))
39 if (*sp
== s
) (*errorfn
)() ;
44 double parsedouble(char **sp
, void (*errorfn
)(void))
49 while (isdigit(*s
) || *s
== '-' || *s
== '.')
51 if (*sp
== s
) (*errorfn
)() ;
56 double parsedimen(char **sp
, void (*errorfn
)(void))
58 double num
= parsedouble(sp
, errorfn
);
61 if (strncmp(s
, "pt", 2) == 0) {
63 } else if (strncmp(s
, "in", 2) == 0) {
66 } else if (strncmp(s
, "cm", 2) == 0) {
67 num
*= 28.346456692913385211;
69 } else if (strncmp(s
, "mm", 2) == 0) {
70 num
*= 2.8346456692913385211;
72 } else if (*s
== 'w') {
74 message(FATAL
, "width not initialised\n");
77 } else if (*s
== 'h') {
79 message(FATAL
, "height not initialised\n");
87 double singledimen(char *str
, void (*errorfn
)(void), void (*usagefn
)(void))
89 double num
= parsedimen(&str
, errorfn
);
90 if (*str
) (*usagefn
)();
94 static char *prologue
[] = { /* PStoPS procset */
97 "[/showpage/erasepage/copypage]{dup where{pop dup load", /* prevent */
98 " type/operatortype eq{1 array cvx dup 0 3 index cvx put", /* binding */
99 " bind def}{pop}ifelse}{pop}ifelse}forall", /* in prolog */
102 "[/showpage/copypage/erasepage]{dup 10 string cvs dup",
103 " length 6 add string dup 0 (PStoPS) putinterval dup",
104 " 6 4 -1 roll putinterval 2 copy cvn dup where",
105 " {pop pop pop}{exch load def}ifelse cvx cvn 1 array cvx",
106 " dup 0 4 -1 roll put def}forall",
108 "[/letter/legal/executivepage/a4/a4small/b5/com10envelope", /* nullify */
109 " /monarchenvelope/c5envelope/dlenvelope/lettersmall/note", /* paper */
110 " /folio/quarto/a5]{dup where{dup wcheck{exch{}put}", /* operators */
111 " {pop{}def}ifelse}{pop}ifelse}forall",
112 "/setpagedevice {pop}bind 1 index where{dup wcheck{3 1 roll put}",
113 " {pop def}ifelse}{def}ifelse",
114 "/PStoPSmatrix matrix currentmatrix def",
115 "/PStoPSxform matrix def/PStoPSclip{clippath}def",
116 "/defaultmatrix{PStoPSmatrix exch PStoPSxform exch concatmatrix}bind def",
117 "/initmatrix{matrix defaultmatrix setmatrix}bind def",
118 "/initclip[{matrix currentmatrix PStoPSmatrix setmatrix",
119 " [{currentpoint}stopped{$error/newerror false put{newpath}}",
120 " {/newpath cvx 3 1 roll/moveto cvx 4 array astore cvx}ifelse]",
121 " {[/newpath cvx{/moveto cvx}{/lineto cvx}",
122 " {/curveto cvx}{/closepath cvx}pathforall]cvx exch pop}",
123 " stopped{$error/errorname get/invalidaccess eq{cleartomark",
124 " $error/newerror false put cvx exec}{stop}ifelse}if}bind aload pop",
125 " /initclip dup load dup type dup/operatortype eq{pop exch pop}",
126 " {dup/arraytype eq exch/packedarraytype eq or",
127 " {dup xcheck{exch pop aload pop}{pop cvx}ifelse}",
128 " {pop cvx}ifelse}ifelse",
129 " {newpath PStoPSclip clip newpath exec setmatrix} bind aload pop]cvx def",
130 "/initgraphics{initmatrix newpath initclip 1 setlinewidth",
131 " 0 setlinecap 0 setlinejoin []0 setdash 0 setgray",
132 " 10 setmiterlimit}bind def",
137 void pstops(int modulo
, int pps
, int nobind
, PageSpec
*specs
, double draw
)
145 maxpage
= ((pages
+modulo
-1)/modulo
)*modulo
;
147 /* rearrange pages: doesn't cope properly with loaded definitions */
148 writeheader((maxpage
/modulo
)*pps
);
149 #ifndef SHOWPAGE_LOAD
150 writestring("%%BeginProcSet: PStoPS");
152 writestring("%%BeginProcSet: PStoPS-spload");
155 writestring("-nobind");
156 writestring(" 1 15\n");
157 for (pro
= prologue
; *pro
; pro
++) {
161 if (nobind
) /* desperation measures */
162 writestring("/bind{}def\n");
163 writestring("%%EndProcSet\n");
164 /* save transformation from original to current matrix */
165 if (writepartprolog()) {
166 writestring("userdict/PStoPSxform PStoPSmatrix matrix currentmatrix\n");
167 writestring(" matrix invertmatrix matrix concatmatrix\n");
168 writestring(" matrix invertmatrix put\n");
171 for (thispg
= 0; thispg
< maxpage
; thispg
+= modulo
) {
174 for (ps
= specs
; ps
!= NULL
; ps
= ps
->next
) {
176 int add_next
= ((ps
->flags
& ADD_NEXT
) != 0);
178 actualpg
= maxpage
-thispg
-modulo
+ps
->pageno
;
180 actualpg
= thispg
+ps
->pageno
;
181 if (actualpg
< pages
)
183 if (!add_last
) { /* page label contains original pages */
185 char *eob
= pagelabel
;
190 sprintf(eob
, "%d", maxpage
-thispg
-modulo
+np
->pageno
);
192 sprintf(eob
, "%d", thispg
+np
->pageno
);
193 eob
= eob
+ strlen(eob
);
195 } while ((np
->flags
& ADD_NEXT
) && (np
= np
->next
));
197 writepageheader(pagelabel
, ++pageindex
);
199 writestring("userdict/PStoPSsaved save put\n");
200 if (ps
->flags
& GSAVE
) {
202 writestring("PStoPSmatrix setmatrix\n");
203 if (ps
->flags
& OFFSET
) {
204 sprintf(buffer
, "%f %f translate\n", ps
->xoff
, ps
->yoff
);
207 if (ps
->flags
& ROTATE
) {
208 sprintf(buffer
, "%d rotate\n", ps
->rotate
);
211 if (ps
->flags
& SCALE
) {
212 sprintf(buffer
, "%f dup scale\n", ps
->scale
);
215 writestring("userdict/PStoPSmatrix matrix currentmatrix put\n");
216 if (width
> 0 && height
> 0) {
218 writestring("userdict/PStoPSclip{0 0 moveto\n");
219 sprintf(buffer
, " %f 0 rlineto 0 %f rlineto -%f 0 rlineto\n",
220 width
, height
, width
);
222 writestring(" closepath}put initclip\n");
224 sprintf(buffer
, "gsave clippath 0 setgray %f setlinewidth stroke grestore\n", draw
);
230 #ifndef SHOWPAGE_LOAD
231 writestring("/showpage{}def/copypage{}def/erasepage{}def\n");
233 writestring("/PStoPSshowpage{}store/PStoPScopypage{}store/PStoPSerasepage{}store\n");
236 if (actualpg
< pages
) {
238 writestring("PStoPSxform concat\n");
239 writepagebody(actualpg
);
241 writestring("PStoPSxform concat\n");
242 writestring("showpage\n");
244 writestring("PStoPSsaved restore\n");