Bringing apdf from vendor into main branch.
[AROS-Contrib.git] / apdf / xpdf / pdftops.cc
blob7d5cce2f94a623cb021f2b57fc41b899c2d4be13
1 //========================================================================
2 //
3 // pdftops.cc
4 //
5 // Copyright 1996-2003 Glyph & Cog, LLC
6 //
7 //========================================================================
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 "config.h"
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 pageCrop = gFalse;
55 static GBool duplex = gFalse;
56 static char ownerPassword[33] = "\001";
57 static char userPassword[33] = "\001";
58 static GBool quiet = gFalse;
59 static char cfgFileName[256] = "";
60 static GBool printVersion = gFalse;
61 static GBool printHelp = gFalse;
63 static ArgDesc argDesc[] = {
64 {"-f", argInt, &firstPage, 0,
65 "first page to print"},
66 {"-l", argInt, &lastPage, 0,
67 "last page to print"},
68 {"-level1", argFlag, &level1, 0,
69 "generate Level 1 PostScript"},
70 {"-level1sep", argFlag, &level1Sep, 0,
71 "generate Level 1 separable PostScript"},
72 {"-level2", argFlag, &level2, 0,
73 "generate Level 2 PostScript"},
74 {"-level2sep", argFlag, &level2Sep, 0,
75 "generate Level 2 separable PostScript"},
76 {"-level3", argFlag, &level3, 0,
77 "generate Level 3 PostScript"},
78 {"-level3sep", argFlag, &level3Sep, 0,
79 "generate Level 3 separable PostScript"},
80 {"-eps", argFlag, &doEPS, 0,
81 "generate Encapsulated PostScript (EPS)"},
82 {"-form", argFlag, &doForm, 0,
83 "generate a PostScript form"},
84 #if OPI_SUPPORT
85 {"-opi", argFlag, &doOPI, 0,
86 "generate OPI comments"},
87 #endif
88 {"-noembt1", argFlag, &noEmbedT1Fonts, 0,
89 "don't embed Type 1 fonts"},
90 {"-noembtt", argFlag, &noEmbedTTFonts, 0,
91 "don't embed TrueType fonts"},
92 {"-noembcidps", argFlag, &noEmbedCIDPSFonts, 0,
93 "don't embed CID PostScript fonts"},
94 {"-noembcidtt", argFlag, &noEmbedCIDTTFonts, 0,
95 "don't embed CID TrueType fonts"},
96 {"-paper", argString, paperSize, sizeof(paperSize),
97 "paper size (letter, legal, A4, A3, match)"},
98 {"-paperw", argInt, &paperWidth, 0,
99 "paper width, in points"},
100 {"-paperh", argInt, &paperHeight, 0,
101 "paper height, in points"},
102 {"-nocrop", argFlag, &noCrop, 0,
103 "don't crop pages to CropBox"},
104 {"-expand", argFlag, &expand, 0,
105 "expand pages smaller than the paper size"},
106 {"-noshrink", argFlag, &noShrink, 0,
107 "don't shrink pages larger than the paper size"},
108 {"-nocenter", argFlag, &noCenter, 0,
109 "don't center pages smaller than the paper size"},
110 {"-pagecrop", argFlag, &pageCrop, 0,
111 "treat the CropBox as the page size"},
112 {"-duplex", argFlag, &duplex, 0,
113 "enable duplex printing"},
114 {"-opw", argString, ownerPassword, sizeof(ownerPassword),
115 "owner password (for encrypted files)"},
116 {"-upw", argString, userPassword, sizeof(userPassword),
117 "user password (for encrypted files)"},
118 {"-q", argFlag, &quiet, 0,
119 "don't print any messages or errors"},
120 {"-cfg", argString, cfgFileName, sizeof(cfgFileName),
121 "configuration file to use in place of .xpdfrc"},
122 {"-v", argFlag, &printVersion, 0,
123 "print copyright and version info"},
124 {"-h", argFlag, &printHelp, 0,
125 "print usage information"},
126 {"-help", argFlag, &printHelp, 0,
127 "print usage information"},
128 {"--help", argFlag, &printHelp, 0,
129 "print usage information"},
130 {"-?", argFlag, &printHelp, 0,
131 "print usage information"},
132 {NULL}
135 int main(int argc, char *argv[]) {
136 PDFDoc *doc;
137 GString *fileName;
138 GString *psFileName;
139 PSLevel level;
140 PSOutMode mode;
141 GString *ownerPW, *userPW;
142 PSOutputDev *psOut;
143 GBool ok;
144 char *p;
145 int exitCode;
147 exitCode = 99;
149 // parse args
150 ok = parseArgs(argDesc, &argc, argv);
151 if (!ok || argc < 2 || argc > 3 || printVersion || printHelp) {
152 fprintf(stderr, "pdftops version %s\n", xpdfVersion);
153 fprintf(stderr, "%s\n", xpdfCopyright);
154 if (!printVersion) {
155 printUsage("pdftops", "<PDF-file> [<PS-file>]", argDesc);
157 exit(1);
159 if ((level1 ? 1 : 0) +
160 (level1Sep ? 1 : 0) +
161 (level2 ? 1 : 0) +
162 (level2Sep ? 1 : 0) +
163 (level3 ? 1 : 0) +
164 (level3Sep ? 1 : 0) > 1) {
165 fprintf(stderr, "Error: use only one of the 'level' options.\n");
166 exit(1);
168 if (doEPS && doForm) {
169 fprintf(stderr, "Error: use only one of -eps and -form\n");
170 exit(1);
172 if (level1) {
173 level = psLevel1;
174 } else if (level1Sep) {
175 level = psLevel1Sep;
176 } else if (level2Sep) {
177 level = psLevel2Sep;
178 } else if (level3) {
179 level = psLevel3;
180 } else if (level3Sep) {
181 level = psLevel3Sep;
182 } else {
183 level = psLevel2;
185 if (doForm && level < psLevel2) {
186 fprintf(stderr, "Error: forms are only available with Level 2 output.\n");
187 exit(1);
189 mode = doEPS ? psModeEPS
190 : doForm ? psModeForm
191 : psModePS;
192 fileName = new GString(argv[1]);
194 // read config file
195 globalParams = new GlobalParams(cfgFileName);
196 if (paperSize[0]) {
197 if (!globalParams->setPSPaperSize(paperSize)) {
198 fprintf(stderr, "Invalid paper size\n");
199 delete fileName;
200 goto err0;
202 } else {
203 if (paperWidth) {
204 globalParams->setPSPaperWidth(paperWidth);
206 if (paperHeight) {
207 globalParams->setPSPaperHeight(paperHeight);
210 if (noCrop) {
211 globalParams->setPSCrop(gFalse);
213 if (expand) {
214 globalParams->setPSExpandSmaller(gTrue);
216 if (noShrink) {
217 globalParams->setPSShrinkLarger(gFalse);
219 if (noCenter) {
220 globalParams->setPSCenter(gFalse);
222 if (duplex) {
223 globalParams->setPSDuplex(duplex);
225 if (level1 || level1Sep || level2 || level2Sep || level3 || level3Sep) {
226 globalParams->setPSLevel(level);
228 if (noEmbedT1Fonts) {
229 globalParams->setPSEmbedType1(!noEmbedT1Fonts);
231 if (noEmbedTTFonts) {
232 globalParams->setPSEmbedTrueType(!noEmbedTTFonts);
234 if (noEmbedCIDPSFonts) {
235 globalParams->setPSEmbedCIDPostScript(!noEmbedCIDPSFonts);
237 if (noEmbedCIDTTFonts) {
238 globalParams->setPSEmbedCIDTrueType(!noEmbedCIDTTFonts);
240 #if OPI_SUPPORT
241 if (doOPI) {
242 globalParams->setPSOPI(doOPI);
244 #endif
245 if (quiet) {
246 globalParams->setErrQuiet(quiet);
249 // open PDF file
250 if (ownerPassword[0] != '\001') {
251 ownerPW = new GString(ownerPassword);
252 } else {
253 ownerPW = NULL;
255 if (userPassword[0] != '\001') {
256 userPW = new GString(userPassword);
257 } else {
258 userPW = NULL;
260 doc = new PDFDoc(fileName, ownerPW, userPW);
261 if (userPW) {
262 delete userPW;
264 if (ownerPW) {
265 delete ownerPW;
267 if (!doc->isOk()) {
268 exitCode = 1;
269 goto err1;
272 // check for print permission
273 if (!doc->okToPrint()) {
274 error(-1, "Printing this document is not allowed.");
275 exitCode = 3;
276 goto err1;
279 // construct PostScript file name
280 if (argc == 3) {
281 psFileName = new GString(argv[2]);
282 } else {
283 p = fileName->getCString() + fileName->getLength() - 4;
284 if (!strcmp(p, ".pdf") || !strcmp(p, ".PDF")) {
285 psFileName = new GString(fileName->getCString(),
286 fileName->getLength() - 4);
287 } else {
288 psFileName = fileName->copy();
290 psFileName->append(doEPS ? ".eps" : ".ps");
293 // get page range
294 if (firstPage < 1) {
295 firstPage = 1;
297 if (lastPage < 1 || lastPage > doc->getNumPages()) {
298 lastPage = doc->getNumPages();
301 // check for multi-page EPS or form
302 if ((doEPS || doForm) && firstPage != lastPage) {
303 error(-1, "EPS and form files can only contain one page.");
304 goto err2;
307 // write PostScript file
308 psOut = new PSOutputDev(psFileName->getCString(), doc->getXRef(),
309 doc->getCatalog(), firstPage, lastPage, mode);
310 if (psOut->isOk()) {
311 doc->displayPages(psOut, firstPage, lastPage, 72, 72,
312 0, !pageCrop, globalParams->getPSCrop(), gFalse);
313 } else {
314 delete psOut;
315 exitCode = 2;
316 goto err2;
318 delete psOut;
320 exitCode = 0;
322 // clean up
323 err2:
324 delete psFileName;
325 err1:
326 delete doc;
327 err0:
328 delete globalParams;
330 // check for memory leaks
331 Object::memCheck(stderr);
332 gMemReport(stderr);
334 return exitCode;