1
//========================================================================
5
// Copyright 2005 AXE,Inc.
7
// 2007,2008,2009 Modified by BBR Inc.
8
//========================================================================
16
#include "goo/GooString.h"
17
#define GSTRING_H // for old GooString.h
19
#include "GlobalParams.h"
22
#include "splash/SplashBitmap.h"
24
#include "OPVPOutputDev.h"
26
#include <cups/cups.h>
31
#define MMPERINCH (25.4)
33
static int resolution = 300;
34
static int hResolution = 0;
35
static int vResolution = 0;
36
static GBool mono = gFalse;
37
static GBool reverse = gFalse;
38
static GBool gray = gFalse;
39
static char enableFreeTypeStr[16] = "";
40
static GBool quiet = gFalse;
41
static char outputOrderStr[256] = "";
42
static GBool oldLipsDriver = gFalse;
43
static GBool HPDriver = gFalse;
44
static GBool NECDriver = gFalse;
45
static GBool clipPathNotSaved = gFalse;
46
static GBool noShearImage = gFalse;
47
static GBool noLineStyle = gFalse;
48
static GBool noImageMask = gFalse;
49
static GBool noClipPath = gFalse;
50
static GBool ignoreMiterLimit = gFalse;
51
static GBool noMiterLimit = gFalse;
52
static char printerDriver[1024] = "";
53
static char printerModel[1024] = "";
54
static char jobInfo[4096] = "";
55
static char docInfo[1024] = "";
56
static char pageInfo[1024] = "";
57
static GBool noBitmapChar = gFalse;
58
static char bitmapCharThreshold[20] = "2000";
59
static char maxClipPathLength[20] = "2000";
60
static char maxFillPathLength[20] = "4000";
61
static int pageWidth = -1;
62
static int pageHeight = -1;
64
static int outOnePage(PDFDoc *doc, OPVPOutputDev *opvpOut, int pg)
68
double pw = doc->getPageMediaWidth(pg);
69
double ph = doc->getPageMediaHeight(pg);
73
if (pw != pageWidth || ph != pageHeight) {
74
if (pageInfo[0] != '\0') {
75
snprintf(buf,sizeof(buf),"%s;MediaSize=%dx%dmm",pageInfo,
76
(int)(pw*MMPERINCH/72),
77
(int)(ph*MMPERINCH/72));
79
snprintf(buf,sizeof(buf),"MediaSize=%dx%dmm",
80
(int)(pw*MMPERINCH/72),
81
(int)(ph*MMPERINCH/72));
90
paperWidth = (int)(pw*hResolution/72+0.5);
91
paperHeight = (int)(ph*vResolution/72+0.5);
92
if (opvpOut->OPVPStartPage(p,paperWidth,paperHeight) < 0) {
93
error(-1,"Start Page failed");
96
opvpOut->setScale(1.0,1.0,0,0,0,0,paperHeight);
97
doc->displayPage(opvpOut, pg, resolution, resolution,
98
0, gTrue, gTrue, gFalse);
99
if (opvpOut->outSlice() < 0) {
100
error(-1,"OutSlice failed");
103
if (opvpOut->OPVPEndPage() < 0) {
104
error(-1,"End Page failed");
110
#define MAX_OPVP_OPTIONS 20
112
void CDECL myErrorFun(int pos, char *msg, va_list args)
115
fprintf(stderr, "ERROR (%d): ", pos);
117
fprintf(stderr, "ERROR: ");
119
vfprintf(stderr, msg, args);
120
fprintf(stderr, "\n");
124
static GBool getColorProfilePath(ppd_file_t *ppd, GooString *path)
126
// get color profile path
128
char *cupsICCQualifier2;
129
char *cupsICCQualifier2Choice;
130
char *cupsICCQualifier3;
131
char *cupsICCQualifier3Choice;
133
ppd_choice_t *choice;
135
if ((attr = ppdFindAttr(ppd,"ColorModel",NULL)) != NULL) {
136
colorModel = attr->value;
140
if ((attr = ppdFindAttr(ppd,"cupsICCQualifier2",NULL)) != NULL) {
141
cupsICCQualifier2 = attr->value;
143
cupsICCQualifier2 = "MediaType";
145
if ((choice = ppdFindMarkedChoice(ppd,cupsICCQualifier2)) != NULL) {
146
cupsICCQualifier2Choice = choice->choice;
148
cupsICCQualifier2Choice = NULL;
150
if ((attr = ppdFindAttr(ppd,"cupsICCQualifier3",NULL)) != NULL) {
151
cupsICCQualifier3 = attr->value;
153
cupsICCQualifier3 = "Resolution";
155
if ((choice = ppdFindMarkedChoice(ppd,cupsICCQualifier3)) != NULL) {
156
cupsICCQualifier3Choice = choice->choice;
158
cupsICCQualifier3Choice = NULL;
161
for (attr = ppdFindAttr(ppd,"cupsICCProfile",NULL);attr != NULL;
162
attr = ppdFindNextAttr(ppd,"cupsICCProfile",NULL)) {
164
char buf[PPD_MAX_NAME];
167
strncpy(buf,attr->spec,sizeof(buf));
168
if ((p = strchr(buf,'.')) != NULL) {
171
if (colorModel != NULL && buf[0] != '\0'
172
&& strcasecmp(buf,colorModel) != 0) continue;
177
if ((r = strchr(p,'.')) != 0) {
181
if (cupsICCQualifier2Choice != NULL && p[0] != '\0'
182
&& strcasecmp(p,cupsICCQualifier2Choice) != 0) continue;
187
if ((p = strchr(r,'.')) != 0) {
191
if (cupsICCQualifier3Choice == NULL || r[0] == '\0'
192
|| strcasecmp(r,cupsICCQualifier3Choice) == 0) break;
197
if (attr->value[0] != '/') {
198
path->append(CUPS_DATADIR);
199
path->append("/profiles/");
201
path->append(attr->value);
207
int main(int argc, char *argv[]) {
212
SplashColor paperColor;
213
OPVPOutputDev *opvpOut;
216
char *optionKeys[MAX_OPVP_OPTIONS];
217
char *optionVals[MAX_OPVP_OPTIONS];
222
GooString colorProfilePath("opvp.icc");
225
setErrorFunction(::myErrorFun);
229
cups_option_t *options;
234
GooString jobInfoStr;
235
GooString docInfoStr;
236
GooString pageInfoStr;
237
GBool colorProfile = gFalse;
240
if (argc < 6 || argc > 7) {
241
error(-1,"ERROR: %s job-id user title copies options [file]",
246
if ((ppdFileName = getenv("PPD")) != 0) {
247
if ((ppd = ppdOpenFile(ppdFileName)) != 0) {
248
/* get attributes from PPD File */
249
if ((attr = ppdFindAttr(ppd,"opvpJobInfo",0)) != 0) {
250
jobInfoStr.append(attr->value);
252
if ((attr = ppdFindAttr(ppd,"opvpDocInfo",0)) != 0) {
253
docInfoStr.append(attr->value);
255
if ((attr = ppdFindAttr(ppd,"opvpPageInfo",0)) != 0) {
256
pageInfoStr.append(attr->value);
258
if ((attr = ppdFindAttr(ppd,"pdftoopvpOldLipsDriver",0)) != 0) {
259
if (strcasecmp(attr->value,"true") == 0) {
260
oldLipsDriver = gTrue;
262
oldLipsDriver = gFalse;
265
if ((attr = ppdFindAttr(ppd,"pdftoopvpHPDriver",0)) != 0) {
266
if (strcasecmp(attr->value,"true") == 0) {
272
if ((attr = ppdFindAttr(ppd,"pdftoopvpNECDriver",0)) != 0) {
273
if (strcasecmp(attr->value,"true") == 0) {
279
if ((attr = ppdFindAttr(ppd,"pdftoopvpClipPathNotSaved",0)) != 0) {
280
if (strcasecmp(attr->value,"true") == 0) {
281
clipPathNotSaved = gTrue;
283
clipPathNotSaved = gFalse;
286
if ((attr = ppdFindAttr(ppd,"pdftoopvpShearImage",0)) != 0) {
287
if (strcasecmp(attr->value,"true") == 0) {
288
noShearImage = gFalse;
290
noShearImage = gTrue;
293
if ((attr = ppdFindAttr(ppd,"pdftoopvpLineStyle",0)) != 0) {
294
if (strcasecmp(attr->value,"true") == 0) {
295
noLineStyle = gFalse;
300
if ((attr = ppdFindAttr(ppd,"pdftoopvpImageMask",0)) != 0) {
301
if (strcasecmp(attr->value,"true") == 0) {
302
noImageMask = gFalse;
307
if ((attr = ppdFindAttr(ppd,"pdftoopvpClipPath",0)) != 0) {
308
if (strcasecmp(attr->value,"true") == 0) {
314
if ((attr = ppdFindAttr(ppd,"pdftoopvpMiterLimit",0)) != 0) {
315
if (strcasecmp(attr->value,"true") == 0) {
316
noMiterLimit = gFalse;
318
noMiterLimit = gTrue;
321
if ((attr = ppdFindAttr(ppd,"pdftoopvpIgnoreMiterLimit",0)) != 0) {
322
if (strcasecmp(attr->value,"true") == 0) {
323
ignoreMiterLimit = gTrue;
325
ignoreMiterLimit = gFalse;
328
if ((attr = ppdFindAttr(ppd,"pdftoopvpBitmapCharThreshold",0)) != 0) {
329
strncpy(bitmapCharThreshold,attr->value,
330
sizeof(bitmapCharThreshold)-1);
332
if ((attr = ppdFindAttr(ppd,"pdftoopvpMaxClipPathLength",0)) != 0) {
333
strncpy(maxClipPathLength,attr->value,
334
sizeof(maxClipPathLength)-1);
336
if ((attr = ppdFindAttr(ppd,"pdftoopvpMaxFillPathLength",0)) != 0) {
337
strncpy(maxFillPathLength,attr->value,
338
sizeof(maxFillPathLength)-1);
340
if ((attr = ppdFindAttr(ppd,"pdftoopvpBitmapChar",0)) != 0) {
341
if (strcasecmp(attr->value,"true") == 0) {
342
noBitmapChar = gFalse;
344
noBitmapChar = gTrue;
347
if ((attr = ppdFindAttr(ppd,"opvpDriver",0)) != 0) {
348
strncpy(printerDriver,attr->value,sizeof(printerDriver)-1);
349
printerDriver[sizeof(printerDriver)-1] = '\0';
351
if ((attr = ppdFindAttr(ppd,"opvpModel",0)) != 0) {
352
strncpy(printerModel,attr->value,sizeof(printerModel)-1);
353
printerModel[sizeof(printerModel)-1] = '\0';
355
ppdMarkDefaults(ppd);
358
/* get attributes and options from command line option */
359
num_options = cupsParseOptions(argv[5],0,&options);
360
cupsMarkOptions(ppd,num_options,options);
362
for (i = 0;i < num_options;i++) {
363
if (strcasecmp(options[i].name,"Resolution") == 0) {
364
resolution = atoi(options[i].value);
365
} else if (strcasecmp(options[i].name,"pdftoopvpOldLipsDriver") == 0) {
366
oldLipsDriver = gTrue;
367
} else if (strcasecmp(options[i].name,"pdftoopvpHPDriver") == 0) {
369
} else if (strcasecmp(options[i].name,"pdftoopvpNECDriver") == 0) {
371
} else if (strcasecmp(options[i].name,"pdftoopvpClipPathNotSaved") == 0) {
372
clipPathNotSaved = gTrue;
373
} else if (strcasecmp(options[i].name,"pdftoopvpShearImage") == 0) {
374
if (strcasecmp(options[i].value,"false") == 0) {
375
noShearImage = gTrue;
377
} else if (strcasecmp(options[i].name,"pdftoopvpLineStyle") == 0) {
378
if (strcasecmp(options[i].value,"false") == 0) {
381
} else if (strcasecmp(options[i].name,"pdftoopvpImageMask") == 0) {
382
if (strcasecmp(options[i].value,"false") == 0) {
385
} else if (strcasecmp(options[i].name,"pdftoopvpClipPath") == 0) {
386
if (strcasecmp(options[i].value,"false") == 0) {
389
} else if (strcasecmp(options[i].name,"pdftoopvpMiterLimit") == 0) {
390
if (strcasecmp(options[i].value,"false") == 0) {
391
noMiterLimit = gTrue;
393
} else if (strcasecmp(options[i].name,"pdftoopvpIgnoreMiterLimit") == 0) {
394
if (strcasecmp(options[i].value,"true") == 0) {
395
ignoreMiterLimit = gTrue;
398
else if (strcasecmp(options[i].name,"pdftoopvpBitmapChar") == 0) {
399
if (strcasecmp(options[i].value,"false") == 0) {
400
noBitmapChar = gTrue;
402
} else if (strcasecmp(options[i].name,"pdftoopvpBitmapCharThreshold") == 0) {
403
strncpy(bitmapCharThreshold,options[i].value,
404
sizeof(bitmapCharThreshold)-1);
405
} else if (strcasecmp(options[i].name,"pdftoopvpMaxClipPathLength") == 0) {
406
strncpy(maxClipPathLength,options[i].value,
407
sizeof(maxClipPathLength)-1);
408
} else if (strcasecmp(options[i].name,"pdftoopvpMaxFillPathLength") == 0) {
409
strncpy(maxFillPathLength,options[i].value,
410
sizeof(maxFillPathLength)-1);
411
} else if (strcasecmp(options[i].name,"opvpDriver") == 0) {
412
strncpy(printerDriver,options[i].value,sizeof(printerDriver)-1);
413
printerDriver[sizeof(printerDriver)-1] = '\0';
414
} else if (strcasecmp(options[i].name,"opvpModel") == 0) {
415
strncpy(printerModel,options[i].value,sizeof(printerModel)-1);
416
printerModel[sizeof(printerModel)-1] = '\0';
417
} else if (strcasecmp(options[i].name,"opvpJobInfo") == 0) {
418
/* do nothing here */;
419
} else if (strcasecmp(options[i].name,"opvpDocInfo") == 0) {
420
/* do nothing here */;
421
} else if (strcasecmp(options[i].name,"opvpPageInfo") == 0) {
422
/* do nothing here */;
427
ppd_choice_t **choices;
428
ppd_size_t *pagesize;
430
if ((pagesize = ppdPageSize(ppd,0)) != 0) {
431
pageWidth = (int)pagesize->width;
432
pageHeight = (int)pagesize->length;
434
for (section = (int)PPD_ORDER_ANY;
435
section <= (int)PPD_ORDER_PROLOG;section++) {
438
n = ppdCollect(ppd,(ppd_section_t)section,&choices);
439
for (i = 0;i < n;i++) {
441
if (strcasecmp(((ppd_option_t *)(choices[i]->option))->keyword,
442
"Resolution") == 0) {
443
resolution = atoi(choices[i]->choice);
446
if (choices != 0) free(choices);
449
strncpy(jobInfo,jobInfoStr.getCString(),sizeof(jobInfo)-1);
450
jobInfo[sizeof(jobInfo)-1] = '\0';
451
strncpy(docInfo,docInfoStr.getCString(),sizeof(docInfo)-1);
452
docInfo[sizeof(docInfo)-1] = '\0';
453
strncpy(pageInfo,pageInfoStr.getCString(),sizeof(pageInfo)-1);
454
pageInfo[sizeof(pageInfo)-1] = '\0';
456
colorProfile = getColorProfilePath(ppd,&colorProfilePath);
460
if ((val = cupsGetOption("opvpJobInfo",num_options, options)) != 0) {
461
/* override ppd value */
462
strncpy(jobInfo,val,sizeof(jobInfo)-1);
463
jobInfo[sizeof(jobInfo)-1] = '\0';
465
if ((val = cupsGetOption("opvpDocInfo",num_options, options)) != 0) {
466
/* override ppd value */
467
strncpy(docInfo,val,sizeof(docInfo)-1);
468
docInfo[sizeof(docInfo)-1] = '\0';
470
if ((val = cupsGetOption("opvpPageInfo",num_options, options)) != 0) {
471
/* override ppd value */
472
strncpy(pageInfo,val,sizeof(pageInfo)-1);
473
pageInfo[sizeof(pageInfo)-1] = '\0';
476
cupsFreeOptions(num_options,options);
478
/* for debug parameters */
479
fprintf(stderr,"WARNING:resolution=%d\n",resolution);
480
fprintf(stderr,"WARNING:sliceHeight=%d\n",sliceHeight);
481
fprintf(stderr,"WARNING:oldLipsDriver=%d\n",oldLipsDriver);
482
fprintf(stderr,"WARNING:HPDriver=%d\n",HPDriver);
483
fprintf(stderr,"WARNING:NECDriver=%d\n",NECDriver);
484
fprintf(stderr,"WARNING:clipPathNotSaved=%d\n",clipPathNotSaved);
485
fprintf(stderr,"WARNING:noShearImage=%d\n",noShearImage);
486
fprintf(stderr,"WARNING:noLineStyle=%d\n",noLineStyle);
487
fprintf(stderr,"WARNING:noClipPath=%d\n",noClipPath);
488
fprintf(stderr,"WARNING:noMiterLimit=%d\n",noMiterLimit);
489
fprintf(stderr,"WARNING:printerDriver=%s\n",printerDriver);
490
fprintf(stderr,"WARNING:printerModel=%s\n",printerModel);
491
fprintf(stderr,"WARNING:jobInfo=%s\n",jobInfo);
492
fprintf(stderr,"WARNING:docInfo=%s\n",docInfo);
493
fprintf(stderr,"WARNING:pageInfo=%s\n",pageInfo);
494
fprintf(stderr,"WARNING:noBitmapChar=%d\n",noBitmapChar);
495
fprintf(stderr,"WARNING:bitmapCharThreshold=%s\n",bitmapCharThreshold);
496
fprintf(stderr,"WARNING:maxClipPathLength=%s\n",maxClipPathLength);
497
fprintf(stderr,"WARNING:maxFillPathLength=%s\n",maxFillPathLength);
502
optionKeys[nOptions] = "OPVP_OLDLIPSDRIVER";
503
optionVals[nOptions] = "1";
505
clipPathNotSaved = gTrue;
506
noShearImage = gTrue;
511
noShearImage = gTrue;
514
noMiterLimit = gTrue;
515
strcpy(maxClipPathLength,"6");
516
noShearImage = gTrue;
518
if (clipPathNotSaved) {
519
optionKeys[nOptions] = "OPVP_CLIPPATHNOTSAVED";
520
optionVals[nOptions] = "1";
524
optionKeys[nOptions] = "OPVP_NOSHEARIMAGE";
525
optionVals[nOptions] = "1";
529
optionKeys[nOptions] = "OPVP_NOLINESTYLE";
530
optionVals[nOptions] = "1";
534
optionKeys[nOptions] = "OPVP_NOIMAGEMASK";
535
optionVals[nOptions] = "1";
539
optionKeys[nOptions] = "OPVP_NOCLIPPATH";
540
optionVals[nOptions] = "1";
544
optionKeys[nOptions] = "OPVP_NOMITERLIMIT";
545
optionVals[nOptions] = "1";
549
optionKeys[nOptions] = "OPVP_NOBITMAPCHAR";
550
optionVals[nOptions] = "1";
553
if (ignoreMiterLimit) {
554
optionKeys[nOptions] = "OPVP_IGNOREMITERLIMIT";
555
optionVals[nOptions] = "1";
558
optionKeys[nOptions] = "OPVP_BITMAPCHARTHRESHOLD";
559
optionVals[nOptions] = bitmapCharThreshold;
561
optionKeys[nOptions] = "OPVP_MAXCLIPPATHLENGTH";
562
optionVals[nOptions] = maxClipPathLength;
564
optionKeys[nOptions] = "OPVP_MAXFILLPATHLENGTH";
565
optionVals[nOptions] = maxFillPathLength;
567
if (hResolution == 0) hResolution = resolution;
568
if (hResolution == 0) hResolution = resolution;
569
if (vResolution == 0) vResolution = resolution;
570
if (strcasecmp(outputOrderStr,"reverse") == 0) {
575
fileName.append(argv[6]);
577
fileName.append("-");
581
globalParams = new GlobalParams();
582
if (enableFreeTypeStr[0]) {
583
if (!globalParams->setEnableFreeType(enableFreeTypeStr)) {
584
error(-1,"Bad '-freetype' value on command line");
588
globalParams->setAntialias("no");
590
globalParams->setErrQuiet(quiet);
597
if (fileName.cmp("-") == 0) {
608
/* create a tmp file */
609
if ((s = getenv("TMPDIR")) != 0) {
614
name.append("/XXXXXX");
615
fd = mkstemp(name.getCString());
617
unlink(name.getCString());
619
error(-1,"Can't create temporary file");
625
while (fgets(buf,sizeof(buf)-1,stdin) != NULL
626
&& strncmp(buf,"%PDF",4) != 0) {
627
if (strncmp(buf,"pdftoopvp jobInfo:",18) == 0) {
628
/* JCL jobInfo exists, override jobInfo */
629
strncpy(jobInfo,buf+18,sizeof(jobInfo)-1);
630
for (i = sizeof(jobInfo)-2;i >= 0
631
&& (jobInfo[i] == 0 || jobInfo[i] == '\n' || jobInfo[i] == ';')
636
if (strncmp(buf,"%PDF",4) != 0) {
637
error(-1,"Can't find PDF header");
641
/* copy PDF header */
643
if (write(fd,buf,n) != n) {
644
error(-1,"Can't copy stdin to temporary file");
649
/* copy rest stdin to the tmp file */
650
while ((n = fread(buf,1,sizeof(buf),stdin)) > 0) {
651
if (write(fd,buf,n) != n) {
652
error(-1,"Can't copy stdin to temporary file");
658
if (lseek(fd,0,SEEK_SET) < 0) {
659
error(-1,"Can't rewind temporary file");
665
if ((fp = fdopen(fd,"rb")) == 0) {
666
error(-1,"Can't fdopen temporary file");
673
str = new FileStream(fp,0,gFalse,0,&obj);
674
doc = new PDFDoc(str);
677
doc = new PDFDoc(fileName.copy());
680
error(-1," Parsing PDF failed: error code %d",
681
doc->getErrorCode());
686
if (doc->isEncrypted() && !doc->okToPrint()) {
687
error(-1,"Print Permission Denied");
692
/* paperColor is white */
697
/* set color profile file name */
698
GfxColorSpace::setDisplayProfileName(&colorProfilePath);
700
opvpOut = new OPVPOutputDev();
701
if (opvpOut->init(mono ? splashModeMono1 :
702
gray ? splashModeMono8 :
706
printerDriver,1,printerModel,
707
nOptions,optionKeys,optionVals) < 0) {
708
error(-1,"OPVPOutputDev Initialize fail");
713
opvpOut->startDoc(doc->getXRef());
716
fprintf(stderr,"JobInfo=%s\n",jobInfo);
718
if (opvpOut->OPVPStartJob(jobInfo) < 0) {
719
error(-1,"Start job failed");
723
if (opvpOut->OPVPStartDoc(docInfo) < 0) {
724
error(-1,"Start Document failed");
728
numPages = doc->getNumPages();
729
for (pg = 1; pg <= numPages; ++pg) {
730
if ((exitCode = outOnePage(doc,opvpOut,pg)) != 0) break;
732
if (opvpOut->OPVPEndDoc() < 0) {
733
error(-1,"End Document failed");
737
if (opvpOut->OPVPEndJob() < 0) {
738
error(-1,"End job failed");
750
// check for memory leaks
751
Object::memCheck(stderr);
759
/* for memory debug */
760
void *operator new(size_t size)
762
void *p = malloc(size);
766
void operator delete(void *p)