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