]> www.fi.muni.cz Git - evince.git/blob - pdf/xpdf/pdftops.cc
Import of xpdf code from gpdf.
[evince.git] / pdf / xpdf / pdftops.cc
1 //========================================================================
2 //
3 // pdftops.cc
4 //
5 // Copyright 1996-2003 Glyph & Cog, LLC
6 //
7 //========================================================================
8
9 #include <aconf.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <stddef.h>
13 #include <string.h>
14 #include "parseargs.h"
15 #include "GString.h"
16 #include "gmem.h"
17 #include "GlobalParams.h"
18 #include "Object.h"
19 #include "Stream.h"
20 #include "Array.h"
21 #include "Dict.h"
22 #include "XRef.h"
23 #include "Catalog.h"
24 #include "Page.h"
25 #include "PDFDoc.h"
26 #include "PSOutputDev.h"
27 #include "Error.h"
28 #include "xpdfconfig.h"
29
30 static int firstPage = 1;
31 static int lastPage = 0;
32 static GBool level1 = gFalse;
33 static GBool level1Sep = gFalse;
34 static GBool level2 = gFalse;
35 static GBool level2Sep = gFalse;
36 static GBool level3 = gFalse;
37 static GBool level3Sep = gFalse;
38 static GBool doEPS = gFalse;
39 static GBool doForm = gFalse;
40 #if OPI_SUPPORT
41 static GBool doOPI = gFalse;
42 #endif
43 static GBool noEmbedT1Fonts = gFalse;
44 static GBool noEmbedTTFonts = gFalse;
45 static GBool noEmbedCIDPSFonts = gFalse;
46 static GBool noEmbedCIDTTFonts = gFalse;
47 static char paperSize[15] = "";
48 static int paperWidth = 0;
49 static int paperHeight = 0;
50 static GBool noCrop = gFalse;
51 static GBool expand = gFalse;
52 static GBool noShrink = gFalse;
53 static GBool noCenter = gFalse;
54 static GBool duplex = gFalse;
55 static char ownerPassword[33] = "\001";
56 static char userPassword[33] = "\001";
57 static GBool quiet = gFalse;
58 static char cfgFileName[256] = "";
59 static GBool printVersion = gFalse;
60 static GBool printHelp = gFalse;
61
62 static ArgDesc argDesc[] = {
63   {"-f",          argInt,      &firstPage,      0,
64    "first page to print"},
65   {"-l",          argInt,      &lastPage,       0,
66    "last page to print"},
67   {"-level1",     argFlag,     &level1,         0,
68    "generate Level 1 PostScript"},
69   {"-level1sep",  argFlag,     &level1Sep,      0,
70    "generate Level 1 separable PostScript"},
71   {"-level2",     argFlag,     &level2,         0,
72    "generate Level 2 PostScript"},
73   {"-level2sep",  argFlag,     &level2Sep,      0,
74    "generate Level 2 separable PostScript"},
75   {"-level3",     argFlag,     &level3,         0,
76    "generate Level 3 PostScript"},
77   {"-level3sep",  argFlag,     &level3Sep,      0,
78    "generate Level 3 separable PostScript"},
79   {"-eps",        argFlag,     &doEPS,          0,
80    "generate Encapsulated PostScript (EPS)"},
81   {"-form",       argFlag,     &doForm,         0,
82    "generate a PostScript form"},
83 #if OPI_SUPPORT
84   {"-opi",        argFlag,     &doOPI,          0,
85    "generate OPI comments"},
86 #endif
87   {"-noembt1",    argFlag,     &noEmbedT1Fonts, 0,
88    "don't embed Type 1 fonts"},
89   {"-noembtt",    argFlag,     &noEmbedTTFonts, 0,
90    "don't embed TrueType fonts"},
91   {"-noembcidps", argFlag,     &noEmbedCIDPSFonts, 0,
92    "don't embed CID PostScript fonts"},
93   {"-noembcidtt", argFlag, &noEmbedCIDTTFonts,  0,
94    "don't embed CID TrueType fonts"},
95   {"-paper",      argString,   paperSize,       sizeof(paperSize),
96    "paper size (letter, legal, A4, A3, match)"},
97   {"-paperw",     argInt,      &paperWidth,     0,
98    "paper width, in points"},
99   {"-paperh",     argInt,      &paperHeight,    0,
100    "paper height, in points"},
101   {"-nocrop",     argFlag,     &noCrop,         0,
102    "don't crop pages to CropBox"},
103   {"-expand",     argFlag,     &expand,         0,
104    "expand pages smaller than the paper size"},
105   {"-noshrink",   argFlag,     &noShrink,       0,
106    "don't shrink pages larger than the paper size"},
107   {"-nocenter",   argFlag,     &noCenter,       0,
108    "don't center pages smaller than the paper size"},
109   {"-duplex",     argFlag,     &duplex,         0,
110    "enable duplex printing"},
111   {"-opw",        argString,   ownerPassword,   sizeof(ownerPassword),
112    "owner password (for encrypted files)"},
113   {"-upw",        argString,   userPassword,    sizeof(userPassword),
114    "user password (for encrypted files)"},
115   {"-q",          argFlag,     &quiet,          0,
116    "don't print any messages or errors"},
117   {"-cfg",        argString,      cfgFileName,    sizeof(cfgFileName),
118    "configuration file to use in place of .xpdfrc"},
119   {"-v",          argFlag,     &printVersion,   0,
120    "print copyright and version info"},
121   {"-h",          argFlag,     &printHelp,      0,
122    "print usage information"},
123   {"-help",       argFlag,     &printHelp,      0,
124    "print usage information"},
125   {"--help",      argFlag,     &printHelp,      0,
126    "print usage information"},
127   {"-?",          argFlag,     &printHelp,      0,
128    "print usage information"},
129   {NULL}
130 };
131
132 int main(int argc, char *argv[]) {
133   PDFDoc *doc;
134   GString *fileName;
135   GString *psFileName;
136   PSLevel level;
137   PSOutMode mode;
138   GString *ownerPW, *userPW;
139   PSOutputDev *psOut;
140   GBool ok;
141   char *p;
142   int exitCode;
143
144   exitCode = 99;
145
146   // parse args
147   ok = parseArgs(argDesc, &argc, argv);
148   if (!ok || argc < 2 || argc > 3 || printVersion || printHelp) {
149     fprintf(stderr, "pdftops version %s\n", xpdfVersion);
150     fprintf(stderr, "%s\n", xpdfCopyright);
151     if (!printVersion) {
152       printUsage("pdftops", "<PDF-file> [<PS-file>]", argDesc);
153     }
154     exit(1);
155   }
156   if ((level1 ? 1 : 0) +
157       (level1Sep ? 1 : 0) +
158       (level2 ? 1 : 0) +
159       (level2Sep ? 1 : 0) +
160       (level3 ? 1 : 0) +
161       (level3Sep ? 1 : 0) > 1) {
162     fprintf(stderr, "Error: use only one of the 'level' options.\n");
163     exit(1);
164   }
165   if (doEPS && doForm) {
166     fprintf(stderr, "Error: use only one of -eps and -form\n");
167     exit(1);
168   }
169   if (level1) {
170     level = psLevel1;
171   } else if (level1Sep) {
172     level = psLevel1Sep;
173   } else if (level2Sep) {
174     level = psLevel2Sep;
175   } else if (level3) {
176     level = psLevel3;
177   } else if (level3Sep) {
178     level = psLevel3Sep;
179   } else {
180     level = psLevel2;
181   }
182   if (doForm && level < psLevel2) {
183     fprintf(stderr, "Error: forms are only available with Level 2 output.\n");
184     exit(1);
185   }
186   mode = doEPS ? psModeEPS
187                : doForm ? psModeForm
188                         : psModePS;
189   fileName = new GString(argv[1]);
190
191   // read config file
192   globalParams = new GlobalParams(cfgFileName);
193   if (paperSize[0]) {
194     if (!globalParams->setPSPaperSize(paperSize)) {
195       fprintf(stderr, "Invalid paper size\n");
196       delete fileName;
197       goto err0;
198     }
199   } else {
200     if (paperWidth) {
201       globalParams->setPSPaperWidth(paperWidth);
202     }
203     if (paperHeight) {
204       globalParams->setPSPaperHeight(paperHeight);
205     }
206   }
207   if (noCrop) {
208     globalParams->setPSCrop(gFalse);
209   }
210   if (expand) {
211     globalParams->setPSExpandSmaller(gTrue);
212   }
213   if (noShrink) {
214     globalParams->setPSShrinkLarger(gFalse);
215   }
216   if (noCenter) {
217     globalParams->setPSCenter(gFalse);
218   }
219   if (duplex) {
220     globalParams->setPSDuplex(duplex);
221   }
222   if (level1 || level1Sep || level2 || level2Sep || level3 || level3Sep) {
223     globalParams->setPSLevel(level);
224   }
225   if (noEmbedT1Fonts) {
226     globalParams->setPSEmbedType1(!noEmbedT1Fonts);
227   }
228   if (noEmbedTTFonts) {
229     globalParams->setPSEmbedTrueType(!noEmbedTTFonts);
230   }
231   if (noEmbedCIDPSFonts) {
232     globalParams->setPSEmbedCIDPostScript(!noEmbedCIDPSFonts);
233   }
234   if (noEmbedCIDTTFonts) {
235     globalParams->setPSEmbedCIDTrueType(!noEmbedCIDTTFonts);
236   }
237 #if OPI_SUPPORT
238   if (doOPI) {
239     globalParams->setPSOPI(doOPI);
240   }
241 #endif
242   if (quiet) {
243     globalParams->setErrQuiet(quiet);
244   }
245
246   // open PDF file
247   if (ownerPassword[0] != '\001') {
248     ownerPW = new GString(ownerPassword);
249   } else {
250     ownerPW = NULL;
251   }
252   if (userPassword[0] != '\001') {
253     userPW = new GString(userPassword);
254   } else {
255     userPW = NULL;
256   }
257   doc = new PDFDoc(fileName, ownerPW, userPW);
258   if (userPW) {
259     delete userPW;
260   }
261   if (ownerPW) {
262     delete ownerPW;
263   }
264   if (!doc->isOk()) {
265     exitCode = 1;
266     goto err1;
267   }
268
269   // check for print permission
270   if (!doc->okToPrint()) {
271     error(-1, "Printing this document is not allowed.");
272     exitCode = 3;
273     goto err1;
274   }
275
276   // construct PostScript file name
277   if (argc == 3) {
278     psFileName = new GString(argv[2]);
279   } else {
280     p = fileName->getCString() + fileName->getLength() - 4;
281     if (!strcmp(p, ".pdf") || !strcmp(p, ".PDF")) {
282       psFileName = new GString(fileName->getCString(),
283                                fileName->getLength() - 4);
284     } else {
285       psFileName = fileName->copy();
286     }
287     psFileName->append(doEPS ? ".eps" : ".ps");
288   }
289
290   // get page range
291   if (firstPage < 1) {
292     firstPage = 1;
293   }
294   if (lastPage < 1 || lastPage > doc->getNumPages()) {
295     lastPage = doc->getNumPages();
296   }
297
298   // check for multi-page EPS or form
299   if ((doEPS || doForm) && firstPage != lastPage) {
300     error(-1, "EPS and form files can only contain one page.");
301     goto err2;
302   }
303
304   // write PostScript file
305   psOut = new PSOutputDev(psFileName->getCString(), doc->getXRef(),
306                           doc->getCatalog(), firstPage, lastPage, mode);
307   if (psOut->isOk()) {
308     doc->displayPages(psOut, firstPage, lastPage, 72, 72,
309                       0, globalParams->getPSCrop(), gFalse);
310   } else {
311     delete psOut;
312     exitCode = 2;
313     goto err2;
314   }
315   delete psOut;
316
317   exitCode = 0;
318
319   // clean up
320  err2:
321   delete psFileName;
322  err1:
323   delete doc;
324  err0:
325   delete globalParams;
326
327   // check for memory leaks
328   Object::memCheck(stderr);
329   gMemReport(stderr);
330
331   return exitCode;
332 }