]> git.ipfire.org Git - thirdparty/cups.git/blob - pdftops/pdftops.cxx
Merge changes from CUPS 1.4svn-r7199.
[thirdparty/cups.git] / pdftops / pdftops.cxx
1 //
2 // "$Id: pdftops.cxx 6649 2007-07-11 21:46:42Z mike $"
3 //
4 // PDF to PostScript filter front-end for the Common UNIX Printing
5 // System (CUPS).
6 //
7 // Copyright 2007 by Apple Inc.
8 // Copyright 1997-2006 by Easy Software Products.
9 //
10 // These coded instructions, statements, and computer programs are the
11 // property of Apple Inc. and are protected by Federal copyright
12 // law. Distribution and use rights are outlined in the file "LICENSE.txt"
13 // which should have been included with this file. If this file is
14 // file is missing or damaged, see the license at "http://www.cups.org/".
15 //
16 // Contents:
17 //
18 // main() - Main entry for filter...
19 //
20
21 //
22 // Include necessary headers...
23 //
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <stddef.h>
28 #include <cups/string.h>
29 #include <cups/i18n.h>
30 #include "parseargs.h"
31 #include "GString.h"
32 #include "gmem.h"
33 #include "Object.h"
34 #include "Stream.h"
35 #include "Array.h"
36 #include "Dict.h"
37 #include "XRef.h"
38 #include "Catalog.h"
39 #include "Page.h"
40 #include "PDFDoc.h"
41 #include "PSOutputDev.h"
42 #include "GlobalParams.h"
43 #include "Error.h"
44 #include "config.h"
45
46 #include <cups/cups.h>
47
48
49 //
50 // 'main()' - Main entry for filter...
51 //
52
53 int // O - Exit status
54 main(int argc, // I - Number of command-line args
55 char *argv[]) // I - Command-line arguments
56 {
57 PDFDoc *doc; // Input file
58 GString *fileName; // Input filename
59 GString *psFileName; // Output filename
60 PSLevel level; // PostScript level
61 PSOutputDev *psOut; // Output device
62 int num_options; // Number of options
63 cups_option_t *options; // Options
64 const char *val; // Option value
65 ppd_file_t *ppd; // Current PPD
66 ppd_size_t *size; // Current media size
67 int fd; // Copy file descriptor
68 const char *server_root; // Location of config files
69 char tempfile[1024]; // Temporary file
70 char buffer[8192]; // Copy buffer
71 int bytes; // Bytes copied
72 int width, length; // Size in points
73 int left, bottom, right, top;
74 // Imageable area in points
75 int orientation; // Orientation
76 int temp; // Temporary var
77 int duplex; // Duplex the output?
78 int fit; // Fit the pages to the output
79 int printCommands; // Output debug info for commands?
80
81
82 // Make sure status messages are not buffered...
83 setbuf(stderr, NULL);
84
85 // Make sure we have the right number of arguments for CUPS!
86 if (argc < 6 || argc > 7) {
87 fprintf(stderr, _("Usage: %s job user title copies options [filename]\n"),
88 argv[0]);
89 return (1);
90 }
91
92 // Copy stdin if needed...
93 if (argc == 6) {
94 if ((fd = cupsTempFd(tempfile, sizeof(tempfile))) < 0) {
95 perror(_("ERROR: Unable to copy PDF file"));
96 return (1);
97 }
98
99 fprintf(stderr, "DEBUG: pdftops - copying to temp print file \"%s\"\n",
100 tempfile);
101
102 while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0)
103 write(fd, buffer, bytes);
104 close(fd);
105
106 fileName = new GString(tempfile);
107 } else {
108 fileName = new GString(argv[6]);
109 tempfile[0] = '\0';
110 }
111
112 // Default to "Universal" size - min of A4 and Letter...
113 left = 0;
114 bottom = 0;
115 right = 595;
116 top = 792;
117 width = 595;
118 length = 792;
119 level = psLevel2;
120 duplex = 0;
121 fit = 0;
122
123 // Get PPD and initialize options as needed...
124 num_options = cupsParseOptions(argv[5], 0, &options);
125
126 if ((ppd = ppdOpenFile(getenv("PPD"))) != NULL)
127 {
128 fprintf(stderr, "DEBUG: pdftops - opened PPD file \"%s\"...\n", getenv("PPD"));
129
130 ppdMarkDefaults(ppd);
131 cupsMarkOptions(ppd, num_options, options);
132
133 if ((size = ppdPageSize(ppd, NULL)) != NULL)
134 {
135 left = (int)size->left;
136 bottom = (int)size->bottom;
137 right = (int)size->right;
138 top = (int)size->top;
139 width = (int)size->width;
140 length = (int)size->length;
141 }
142
143 level = ppd->language_level == 1 ? psLevel1 : psLevel2;
144 }
145
146 // Track the orientation of the print job and update the page
147 // dimensions and margins as needed...
148 orientation = 0;
149
150 if ((val = cupsGetOption("landscape", num_options, options)) != NULL)
151 {
152 if (strcasecmp(val, "no") != 0 && strcasecmp(val, "off") != 0 &&
153 strcasecmp(val, "false") != 0)
154 orientation = 1;
155 }
156 else if ((val = cupsGetOption("orientation-requested", num_options, options)) != NULL)
157 {
158 /*
159 * Map IPP orientation values to 0 to 3:
160 *
161 * 3 = 0 degrees = 0
162 * 4 = 90 degrees = 1
163 * 5 = -90 degrees = 3
164 * 6 = 180 degrees = 2
165 */
166
167 orientation = atoi(val) - 3;
168 if (orientation >= 2)
169 orientation ^= 1;
170 }
171
172 switch (orientation & 3)
173 {
174 case 0 : /* Portait */
175 break;
176
177 case 1 : /* Landscape */
178 temp = left;
179 left = bottom;
180 bottom = temp;
181
182 temp = right;
183 right = top;
184 top = temp;
185
186 temp = width;
187 width = length;
188 length = temp;
189 break;
190
191 case 2 : /* Reverse Portrait */
192 temp = width - left;
193 left = width - right;
194 right = temp;
195
196 temp = length - bottom;
197 bottom = length - top;
198 top = temp;
199 break;
200
201 case 3 : /* Reverse Landscape */
202 temp = width - left;
203 left = width - right;
204 right = temp;
205
206 temp = length - bottom;
207 bottom = length - top;
208 top = temp;
209
210 temp = left;
211 left = bottom;
212 bottom = temp;
213
214 temp = right;
215 right = top;
216 top = temp;
217
218 temp = width;
219 width = length;
220 length = temp;
221 break;
222 }
223
224 if ((val = cupsGetOption("debug", num_options, options)) != NULL &&
225 strcasecmp(val, "no") && strcasecmp(val, "off") &&
226 strcasecmp(val, "false"))
227 printCommands = 1;
228 else
229 printCommands = 0;
230
231 if ((val = cupsGetOption("fitplot", num_options, options)) != NULL &&
232 strcasecmp(val, "no") && strcasecmp(val, "off") &&
233 strcasecmp(val, "false"))
234 fit = 1;
235
236 if ((val = cupsGetOption("sides", num_options, options)) != NULL &&
237 strncasecmp(val, "two-", 4) == 0)
238 duplex = 1;
239 else if ((val = cupsGetOption("Duplex", num_options, options)) != NULL &&
240 strncasecmp(val, "Duplex", 6) == 0)
241 duplex = 1;
242 else if ((val = cupsGetOption("JCLDuplex", num_options, options)) != NULL &&
243 strncasecmp(val, "Duplex", 6) == 0)
244 duplex = 1;
245 else if ((val = cupsGetOption("EFDuplex", num_options, options)) != NULL &&
246 strncasecmp(val, "Duplex", 6) == 0)
247 duplex = 1;
248 else if ((val = cupsGetOption("KD03Duplex", num_options, options)) != NULL &&
249 strncasecmp(val, "Duplex", 6) == 0)
250 duplex = 1;
251 else if (ppdIsMarked(ppd, "Duplex", "DuplexNoTumble") ||
252 ppdIsMarked(ppd, "Duplex", "DuplexTumble") ||
253 ppdIsMarked(ppd, "JCLDuplex", "DuplexNoTumble") ||
254 ppdIsMarked(ppd, "JCLDuplex", "DuplexTumble") ||
255 ppdIsMarked(ppd, "EFDuplex", "DuplexNoTumble") ||
256 ppdIsMarked(ppd, "EFDuplex", "DuplexTumble") ||
257 ppdIsMarked(ppd, "KD03Duplex", "DuplexNoTumble") ||
258 ppdIsMarked(ppd, "KD03Duplex", "DuplexTumble"))
259 duplex = 1;
260
261 if (ppd != NULL)
262 ppdClose(ppd);
263
264 fprintf(stderr, "DEBUG: pdftops - level = %d, width = %d, length = %d\n",
265 level, width, length);
266
267 // read config file
268 if ((server_root = getenv("CUPS_SERVERROOT")) == NULL)
269 server_root = CUPS_SERVERROOT;
270
271 snprintf(buffer, sizeof(buffer), "%s/pdftops.conf", server_root);
272
273 globalParams = new GlobalParams(buffer);
274
275 if (fit || globalParams->getPSPaperWidth() > 0)
276 {
277 // Only set paper size and area if we are fitting to the job's
278 // page size or the pdftops.conf file does not contain
279 // "psPaperSize match"...
280 globalParams->setPSPaperWidth(width);
281 globalParams->setPSPaperHeight(length);
282 globalParams->setPSImageableArea(left, bottom, right, top);
283 }
284
285 globalParams->setPSDuplex(duplex);
286 globalParams->setPSExpandSmaller(fit);
287 globalParams->setPSShrinkLarger(fit);
288 globalParams->setPSLevel(level);
289 globalParams->setPSASCIIHex(level == psLevel1);
290 globalParams->setPSEmbedType1(1);
291 globalParams->setPSEmbedTrueType(1);
292 globalParams->setPSEmbedCIDPostScript(1);
293 globalParams->setErrQuiet(0);
294 globalParams->setPrintCommands(printCommands);
295
296 if (printCommands)
297 setbuf(stdout, NULL);
298
299 // open PDF file
300 doc = new PDFDoc(fileName, NULL, NULL);
301
302 // check for print permission
303 if (doc->isOk() && doc->okToPrint())
304 {
305 // CUPS always writes to stdout...
306 psFileName = new GString("-");
307
308 // write PostScript file
309 psOut = new PSOutputDev(psFileName->getCString(), doc->getXRef(),
310 doc->getCatalog(), 1, doc->getNumPages(),
311 psModePS, 0, 0, 0, 0, gFalse, NULL);
312 if (psOut->isOk())
313 doc->displayPages(psOut, 1, doc->getNumPages(), 72.0, 72.0, 0,
314 gTrue, gFalse, gFalse);
315 delete psOut;
316
317 // clean up
318 delete psFileName;
319 }
320 else
321 {
322 error(-1, "Unable to print this document.");
323 }
324
325 cupsFreeOptions(num_options, options);
326
327 delete doc;
328 delete globalParams;
329
330 // check for memory leaks
331 Object::memCheck(stderr);
332 gMemReport(stderr);
333
334 // Remove temp file if needed...
335 if (tempfile[0])
336 unlink(tempfile);
337
338 return 0;
339 }
340
341
342 //
343 // End of "$Id: pdftops.cxx 6649 2007-07-11 21:46:42Z mike $".
344 //