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
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
|
/* psspec.c
* Page spec routines for page rearrangement
*
* (c) Reuben Thomas 2012
* (c) Angus J. C. Duggan 1991-1997
* See file LICENSE for details.
*/
#include "config.h"
#include "psutil.h"
#include "psspec.h"
#include <string.h>
double width = -1;
double height = -1;
/* create a new page spec */
PageSpec *newspec(void)
{
PageSpec *temp = (PageSpec *)malloc(sizeof(PageSpec));
if (temp == NULL)
message(FATAL, "out of memory\n");
temp->pageno = temp->flags = temp->rotate = 0;
temp->scale = 1;
temp->xoff = temp->yoff = 0;
temp->next = NULL;
return (temp);
}
/* dimension parsing routines */
int parseint(char **sp)
{
char *s = *sp;
int num = atoi(s);
while (isdigit(*s))
s++;
if (*sp == s) argerror();
*sp = s;
return (num);
}
double parsedouble(char **sp)
{
char *s = *sp;
double num = atof(s);
while (isdigit(*s) || *s == '-' || *s == '.')
s++;
if (*sp == s) argerror();
*sp = s;
return (num);
}
double parsedimen(char **sp)
{
double num = parsedouble(sp);
char *s = *sp;
if (strncmp(s, "pt", 2) == 0) {
s += 2;
} else if (strncmp(s, "in", 2) == 0) {
num *= 72;
s += 2;
} else if (strncmp(s, "cm", 2) == 0) {
num *= 28.346456692913385211;
s += 2;
} else if (strncmp(s, "mm", 2) == 0) {
num *= 2.8346456692913385211;
s += 2;
} else if (*s == 'w') {
if (width < 0)
message(FATAL, "width not initialised\n");
num *= width;
s++;
} else if (*s == 'h') {
if (height < 0)
message(FATAL, "height not initialised\n");
num *= height;
s++;
}
*sp = s;
return (num);
}
double singledimen(char *str)
{
double num = parsedimen(&str);
if (*str) usage();
return (num);
}
static const char *prologue[] = { /* PStoPS procset */
/* Wrap these up with our own versions. We have to */
"userdict begin",
"[/showpage/erasepage/copypage]{dup where{pop dup load",
" type/operatortype eq{ /PStoPSenablepage cvx 1 index"
" load 1 array astore cvx {} bind /ifelse cvx 4 array"
" astore cvx def}{pop}ifelse}{pop}ifelse}forall"
" /PStoPSenablepage true def",
"[/letter/legal/executivepage/a4/a4small/b5/com10envelope", /* nullify */
" /monarchenvelope/c5envelope/dlenvelope/lettersmall/note", /* paper */
" /folio/quarto/a5]{dup where{dup wcheck{exch{}put}", /* operators */
" {pop{}def}ifelse}{pop}ifelse}forall",
"/setpagedevice {pop}bind 1 index where{dup wcheck{3 1 roll put}",
" {pop def}ifelse}{def}ifelse",
"/PStoPSmatrix matrix currentmatrix def",
"/PStoPSxform matrix def/PStoPSclip{clippath}def",
"/defaultmatrix{PStoPSmatrix exch PStoPSxform exch concatmatrix}bind def",
"/initmatrix{matrix defaultmatrix setmatrix}bind def",
"/initclip[{matrix currentmatrix PStoPSmatrix setmatrix",
" [{currentpoint}stopped{$error/newerror false put{newpath}}",
" {/newpath cvx 3 1 roll/moveto cvx 4 array astore cvx}ifelse]",
" {[/newpath cvx{/moveto cvx}{/lineto cvx}",
" {/curveto cvx}{/closepath cvx}pathforall]cvx exch pop}",
" stopped{$error/errorname get/invalidaccess eq{cleartomark",
" $error/newerror false put cvx exec}{stop}ifelse}if}bind aload pop",
" /initclip dup load dup type dup/operatortype eq{pop exch pop}",
" {dup/arraytype eq exch/packedarraytype eq or",
" {dup xcheck{exch pop aload pop}{pop cvx}ifelse}",
" {pop cvx}ifelse}ifelse",
" {newpath PStoPSclip clip newpath exec setmatrix} bind aload pop]cvx def",
"/initgraphics{initmatrix newpath initclip 1 setlinewidth",
" 0 setlinecap 0 setlinejoin []0 setdash 0 setgray",
" 10 setmiterlimit}bind def",
"end",
NULL
};
void pstops(int modulo, int pps, int nobind, PageSpec *specs, double draw) {
scanpages(NULL);
pstops_write(modulo, pps, nobind, specs, draw, NULL);
}
void pstops_write(int modulo, int pps, int nobind, PageSpec *specs, double draw, off_t *ignorelist)
{
int thispg, maxpage;
int pageindex = 0;
const char **pro;
maxpage = ((pages+modulo-1)/modulo)*modulo;
/* rearrange pages: doesn't cope properly with loaded definitions */
writeheadermedia((maxpage/modulo)*pps, ignorelist, width, height);
writestring("%%BeginProcSet: PStoPS");
if (nobind)
writestring("-nobind");
writestring(" 1 15\n");
for (pro = prologue; *pro; pro++) {
writestring(*pro);
writestring("\n");
}
if (nobind) /* desperation measures */
writestring("/bind{}def\n");
writestring("%%EndProcSet\n");
/* save transformation from original to current matrix */
if (writepartprolog()) {
writestring("userdict/PStoPSxform PStoPSmatrix matrix currentmatrix\n");
writestring(" matrix invertmatrix matrix concatmatrix\n");
writestring(" matrix invertmatrix put\n");
}
writesetup();
for (thispg = 0; thispg < maxpage; thispg += modulo) {
int add_last = 0;
PageSpec *ps;
for (ps = specs; ps != NULL; ps = ps->next) {
int actualpg;
int add_next = ((ps->flags & ADD_NEXT) != 0);
if (ps->flags & REVERSED)
actualpg = maxpage-thispg-modulo+ps->pageno;
else
actualpg = thispg+ps->pageno;
if (actualpg < pages)
seekpage(actualpg);
if (!add_last) { /* page label contains original pages */
PageSpec *np = ps;
char *eob = pagelabel;
char sep = '(';
do {
*eob++ = sep;
if (np->flags & REVERSED)
sprintf(eob, "%d", maxpage-thispg-modulo+np->pageno);
else
sprintf(eob, "%d", thispg+np->pageno);
eob = eob + strlen(eob);
sep = ',';
} while ((np->flags & ADD_NEXT) && (np = np->next));
strcpy(eob, ")");
writepageheader(pagelabel, ++pageindex);
}
writestring("userdict/PStoPSsaved save put\n");
if (ps->flags & GSAVE) {
char buffer[BUFSIZ];
writestring("PStoPSmatrix setmatrix\n");
if (ps->flags & OFFSET) {
sprintf(buffer, "%f %f translate\n", ps->xoff, ps->yoff);
writestring(buffer);
}
if (ps->flags & ROTATE) {
sprintf(buffer, "%d rotate\n", ps->rotate);
writestring(buffer);
}
if (ps->flags & HFLIP) {
sprintf(buffer, "[ -1 0 0 1 %f 0 ] concat\n", width*ps->scale);
writestring(buffer);
}
if (ps->flags & VFLIP) {
sprintf(buffer, "[ 1 0 0 -1 0 %f ] concat\n", height*ps->scale);
writestring(buffer);
}
if (ps->flags & SCALE) {
sprintf(buffer, "%f dup scale\n", ps->scale);
writestring(buffer);
}
writestring("userdict/PStoPSmatrix matrix currentmatrix put\n");
if (width > 0 && height > 0) {
writestring("userdict/PStoPSclip{0 0 moveto\n");
sprintf(buffer, " %f 0 rlineto 0 %f rlineto -%f 0 rlineto\n",
width, height, width);
writestring(buffer);
writestring(" closepath}put initclip\n");
if (draw > 0) {
sprintf(buffer, "gsave clippath 0 setgray %f setlinewidth stroke grestore\n", draw);
writestring(buffer);
}
}
}
if (add_next)
writestring("/PStoPSenablepage false def\n");
if (actualpg < pages) {
writepagesetup();
writestring("PStoPSxform concat\n");
writepagebody(actualpg);
} else {
writestring("PStoPSxform concat\n");
writestring("showpage\n");
}
writestring("PStoPSsaved restore\n");
add_last = add_next;
}
}
writetrailer();
}
|