Annotation of ratfiv/epstopdf.c, revision 1.1.1.1
1.1 brouard 1: /*
2: # epstopdf: written by Kong Hoon Lee konghoon@hyowon.cc.pusan.ac.kr<4/1/1999>
3: #
4: # It converts an EPS file to an encapsulated PDF File and
5: # coded with the perl script 'epstopdf' by Sebastian Rahtz on
6: # http://tug.org/applications/pdftex/epstopdf .
7: # It works like as the perl script without 'perl' for Windows 95
8: # but requires 'Ghostscript' for Windows.
9: #
10: */
11:
12: #include <stdio.h>
13: #include <stdlib.h>
14: #include <string.h>
15: #include <math.h>
16: #define MAX_IN 10000
17:
18:
19: #ifndef GSEXEC
20: #ifdef __WIN32__
21: #define GSEXEC "gswin32c"
22: #else
23: #define GSEXEC "gs"
24: #endif
25: #endif
26:
27:
28: #define BEGINDOC "%%BeginDocument"
29: #define ENDDOC "%%EndDocument"
30: #define PSSTART "%!"
31: #define PSEOF "%%EOF"
32:
33: #define TRUE 1
34: #define FALSE 0
35:
36:
37: static void usage(void)
38:
39: {
40: printf("epstopdf 2.2.9:\n");
41: printf("written by Kong Hoon Lee, konghoon@dreamwiz.com <1999-4-1>\n");
42: printf("changes by Juergen Bausa, Juergen.Bausa@T-Online.de <2000-10-6>\n");
43: printf("bugfix by Pascal Perichon, Pascal.Perichon@u-bourgogne.fr <2000-5-25>\n\n");
44: printf("It converts an EPS file to an encapsulated PDF File and is written\n");
45: printf("based on the perl script 'epstopdf' by Sebastian Rahtz on\n");
46: printf("http://tug.org/applications/pdftex/epstopdf .\n");
47: printf("It works like the perl script without 'perl' but requires 'Ghostscript'.\n");
48: printf("The accompanied Makefile can be used to automate the update of all eps/pdf\n");
49: printf("files in a directory. Just put it in the directory where your eps files\n");
50: printf("are and type 'make' from the command line (you will need a version of\n");
51: printf("GNU-make)\n\n");
52:
53: printf("This program invokes '%s' and the path including '%s'\n",GSEXEC,GSEXEC);
54: printf("should be included to the environment variable 'PATH'.\n");
55: printf("'%s' should know, where to find its initialization files\n",GSEXEC);
56: printf("and fonts, using an registry entry (Windows) or an environment variable.\n\n");
57:
58: printf("Using a different output device, it is also possible to convert eps\n");
59: printf("files to bitmaps (e.g. -sDEVICE=bmpmono).\n\n");
60:
61: printf("Usage: epstopdf [options] filename-of-an-eps-file\n");
62: printf("Options:\n");
63: printf(" --help: print usage\n");
64: printf(" --outfile=<file>: write result to <file>\n");
65: printf(" --tmpfile=<file>: use <file> as temporary file\n");
66: printf(" --(no)filter: read/writ standard input/output (default: false)\n");
67: printf(" --(no)gs: run ghostscript (default: true)\n");
68: printf(" --(no)compress: use compression (default: true)\n");
69: printf(" --(no)hires: scan HiresBoundingBox (default: false)\n");
70: printf(" --(no)exact: scan ExactBoundingBox (default: false)\n");
71: printf(" --(no)debug: debug informations (default: false)\n");
72: printf(" --(no)wait: wait for keystroke (default: false)\n");
73: printf(" --gsexec=<gs>: use <gs> to invoke ghostscript (default: %s)\n",GSEXEC);
74: printf(" --enlarge=<a>: enlarge BB by <a>/72 '' (default: 0.)\n");
75: printf(" -sDEVICE=<dev> : use <dev> as output device (default: pdfwrite)\n");
76: printf(" -r<a>: output resolution for gs (default: 600)\n");
77: printf(" --width=<a>: output width in pixels (default: none)\n");
78: printf(" --height=<a>: output height in pixels (default: none)\n");
79: printf(" --gsopt=<a>: add <a> to the gs command line (default: none)\n");
80: }
81:
82:
83: static int round(double a)
84:
85: {
86: return floor(a+0.5);
87: }
88:
89: static int isint(double a)
90:
91: {
92: if(fabs(a-round(a))<1e-6) return 1;
93: else return 0;
94: }
95:
96:
97: int main(int argc,char *argv[])
98:
99: {
100: FILE *in,*out;
101: char *infile=NULL,*outfile=NULL,*tmpfile=NULL,*copt,*ptr,*gsexec,buf[21];
102: char command[MAX_IN],ch[MAX_IN],*BBname,*device,ropt[20],*gsopt;
103: double bbllx,bblly,bburx,bbury,xoffset,yoffset,enlarge;
104: int width,height,res,xpix,ypix;
105: int i,count,status,BBCorrected,did_CR,debug,compress,usegs,wait,
106: BBhires,BBexact,found,depth,filter,ngsopt,in_ps;
107: fpos_t fpos;
108:
109:
110: #if defined (__EMX__)
111: _wildcard (&argc, &argv);
112: #endif
113:
114: /* default parameter */
115: status=0;
116: BBCorrected=0;
117: BBhires=0;
118: BBexact=0;
119: debug=0;
120: compress=1;
121: usegs=1;
122: gsexec=GSEXEC;
123: wait=0;
124: filter=0;
125: enlarge=0.;
126: res=600;
127: device="pdfwrite";
128: xpix=0;
129: ypix=0;
130: ngsopt=100;
131: gsopt=malloc(ngsopt);
132: gsopt[0]='\0';
133:
134:
135: /******************************************************************
136:
137: Process command line options
138:
139: ******************************************************************/
140:
141: for(i=1;i<argc;i++){
142:
143: /* printf("i=%d arg=>>%s<<\n",i,argv[i]); */
144:
145: if(!strcmp(argv[i],"--help") || !strcmp(argv[i],"-h")){
146: usage();
147: status=0;
148: goto EXIT;
149: }
150:
151: if(!strcmp(argv[i],"--debug") || !strcmp(argv[i],"-d")){
152: debug=1;
153: continue;
154: }
155:
156: if(!strcmp(argv[i],"--nodebug")){
157: debug=0;
158: continue;
159: }
160:
161: if(!strcmp(argv[i],"--compress") || !strcmp(argv[i],"-c")){
162: compress=1;
163: continue;
164: }
165:
166: if(!strcmp(argv[i],"--nocompress")){
167: compress=0;
168: continue;
169: }
170:
171: if(!strcmp(argv[i],"--nogs")){
172: usegs=0;
173: continue;
174: }
175:
176: if(!strcmp(argv[i],"--gs")){
177: usegs=1;
178: continue;
179: }
180:
181: if(!strcmp(argv[i],"--wait") || !strcmp(argv[i],"-w")){
182: wait=1;
183: continue;
184: }
185:
186: if(!strcmp(argv[i],"--nowait")){
187: wait=0;
188: continue;
189: }
190:
191: if(!strcmp(argv[i],"--filter")){
192: filter=1;
193: continue;
194: }
195:
196: if(!strcmp(argv[i],"--nofilter")){
197: filter=0;
198: continue;
199: }
200:
201: if(!strcmp(argv[i],"--hires")){
202: BBhires=1;
203: continue;
204: }
205:
206: if(!strcmp(argv[i],"--nohires")){
207: BBhires=0;
208: continue;
209: }
210:
211: if(!strcmp(argv[i],"--exact")){
212: BBexact=1;
213: continue;
214: }
215:
216: if(!strcmp(argv[i],"--noexact")){
217: BBexact=0;
218: continue;
219: }
220:
221: if(!strncmp(argv[i],"--outfile=",strlen("--outfile="))){
222: outfile=malloc(strlen(argv[i])-strlen("--outfile=")+1);
223: strcpy(outfile, argv[i]+strlen("--outfile="));
224: continue;
225: }
226:
227: if(!strncmp(argv[i],"--tmpfile=",strlen("--tmpfile="))){
228: tmpfile=malloc(strlen(argv[i])-strlen("--tmpfile=")+1);
229: strcpy(tmpfile, argv[i]+strlen("--tmpfile="));
230: continue;
231: }
232:
233: if(!strncmp(argv[i],"-r",strlen("-r"))){
234: sscanf(argv[i]+strlen("-r"),"%d",&res);
235: continue;
236: }
237:
238: if(!strncmp(argv[i],"--width=",strlen("--width="))){
239: sscanf(argv[i]+strlen("--width="),"%d",&xpix);
240: continue;
241: }
242:
243: if(!strncmp(argv[i],"--height=",strlen("--height="))){
244: sscanf(argv[i]+strlen("--height="),"%d",&ypix);
245: continue;
246: }
247:
248: if(!strncmp(argv[i],"--gsopt=",strlen("--gsopt="))){
249: char *opt=argv[i]+strlen("--gsopt=");
250: if(strlen(gsopt)+strlen(opt)+2 < ngsopt){
251: ngsopt+=100;
252: gsopt=realloc(gsopt,ngsopt);
253: }
254: strcat(gsopt," ");
255: strcat(gsopt,opt);
256: continue;
257: }
258:
259: if(!strncmp(argv[i],"-sDEVICE=",strlen("-sDEVICE="))){
260: device=argv[i]+strlen("-sDEVICE=");
261: continue;
262: }
263:
264: if(!strcmp(argv[i],"-o") && i+1<argc){
265: outfile=malloc(strlen(argv[i+1])+1);
266: strcpy(outfile, argv[i+1]);
267: i++;
268: continue;
269: }
270:
271: if(!strncmp(argv[i],"--gsexec=",strlen("--gsexec="))){
272: gsexec=argv[i]+strlen("--gsexec=");
273: continue;
274: }
275:
276:
277: if(argv[i][0]!='-'){
278: if(infile) printf("\nCan process only one input file\n");
279: else infile=argv[i];
280: continue;
281: }
282:
283: if(!strncmp(argv[i],"--enlarge=",strlen("--enlarge="))){
284: sscanf(argv[i]+strlen("--enlarge="),"%lf",&enlarge);
285: continue;
286: }
287:
288: usage();
289: fprintf(stderr,"\nunknown option >>%s<<\n",argv[i]);
290: status=1;
291: goto EXIT;
292: }
293:
294:
295:
296: /******************************************************************
297:
298: check arguments and files
299:
300: ******************************************************************/
301:
302:
303: if(filter) debug=0;
304: if(filter) wait =0;
305:
306: if(BBexact && BBhires){
307: fprintf(stderr,"\nOptions --hires and --exact cannot be used together\n");
308: status=1;
309: goto EXIT;
310: }
311:
312: if (BBexact) BBname="%%ExactBoundingBox:";
313: else if(BBhires) BBname="%%HiresBoundingBox:";
314: else BBname="%%BoundingBox:";
315:
316: if(!filter) {
317:
318: if(!infile) {
319: usage();
320: fprintf(stderr,"no input file specified!\n");
321: status=1;
322: goto EXIT;
323: }
324:
325: if((in=fopen(infile,"r")) == NULL) {
326: usage();
327: fprintf(stderr,"%s: File not found!\n",infile);
328: status=1;
329: goto EXIT;
330: }
331: fclose(in);
332:
333: }else{
334:
335: if(infile) {
336: fprintf(stderr,"Input file cannot be used with filter option!\n");
337: status=1;
338: goto EXIT;
339: }
340:
341: infile="epstopdf"; /* dummy input filename to generate tmp-filename */
342: }
343:
344:
345:
346: /* find a temporary filename that does not exist yet */
347: if(usegs && !tmpfile){
348: tmpfile=malloc(strlen(infile)+9);
349: count=0;
350: do{
351: if(count>99) {
352: fprintf(stderr,"No temporary file available! Try deleting *.tmp.\n\n");
353: status=1;
354: goto EXIT;
355: }
356: sprintf(tmpfile,"%s.%d.tmp",infile,count);
357: if(debug) printf("checking temporary filename >>%s<<\n",tmpfile);
358: out=fopen(tmpfile,"r");
359: if(out) fclose(out);
360: count++;
361: }while(out);
362: }
363:
364: if(!filter){
365: if(!outfile){
366: outfile=malloc(strlen(infile)+6);
367: strcpy(outfile,infile);
368: ptr=outfile;
369: while(strpbrk(ptr,"\\/")) ptr=strpbrk(ptr,"\\/")+1;
370: ptr=strrchr(ptr,'.');
371: if(ptr) *ptr='\0';
372: if(usegs) strcat(outfile,".pdf");
373: else strcat(outfile,"2.eps");
374: }
375: }else{
376: if(outfile) {
377: fprintf(stderr,"Output file cannot be used with filter option!\n");
378: status=1;
379: goto EXIT;
380: }
381: outfile=malloc(2);
382: strcpy(outfile,"-");
383: }
384:
385:
386:
387: if(!filter) printf("Converting %s to %s ..... ",infile,outfile);
388:
389:
390: /******************************************************************
391:
392: put the pagesize from the bounding box into the eps file
393:
394: ******************************************************************/
395:
396:
397: if(debug) printf("\nAdding correct pagesize to EPS ... searching for %s ...\n",BBname);
398:
399: if (!filter) in = fopen(infile, "r");
400: else in = stdin;
401: if (usegs) out = fopen(tmpfile,"w");
402: else if(!filter) out = fopen(outfile,"w");
403: else out = stdout;
404: if(!in || !out){
405: fprintf(stderr,"cannot open files\n");
406: status=1;
407: goto EXIT;
408: }
409:
410: depth=0;
411: in_ps=FALSE;
412: while (fgets(ch,MAX_IN,in)){
413: if(!in_ps) { /* throw away binary junk before %! */
414: if(!strncmp(ch,PSSTART,strlen(PSSTART))) in_ps=TRUE;
415: else continue;
416: }
417: if(!strncmp(ch,BEGINDOC,strlen(BEGINDOC))) depth++; /* count included documents */
418: if(!strncmp(ch,ENDDOC, strlen(ENDDOC) )) depth--;
419: if(!strncmp(ch,BBname, strlen(BBname)) && depth==0) { /* look for BB comment in main doc only */
420: sscanf(ch,"%*s %20s",buf);
421: if(!strcmp(buf,"(atend)")){ /* BB is atended */
422: if(filter){
423: fprintf(stderr,"Cannot look for BoundingBox in the trailer "
424: "with option --filter\n");
425: if(usegs) remove(tmpfile);
426: status=1;
427: goto EXIT;
428: }
429: if(debug) printf("\n (atend)! ...\n");
430: fgetpos(in, &fpos); /* store file position */
431: found=0;
432: while (fgets(ch,MAX_IN,in)){
433: if(!strncmp(ch,BEGINDOC,strlen(BEGINDOC))) depth++; /* count included documents */
434: if(!strncmp(ch,ENDDOC, strlen(ENDDOC) )) depth--;
435: if(!strncmp(ch,BBname,strlen(BBname)) && depth==0) { /* look for bounding box in main doc only */
436: found=1;
437: fsetpos(in, &fpos); /* rewind to (atend) comment */
438: break;
439: }
440: }
441: if(!found){
442: fprintf(stderr,"atended %s not found\n",BBname);
443: if(usegs && !debug) remove(tmpfile);
444: if(!usegs && !debug) remove(outfile);
445: status=1;
446: goto EXIT;
447: }
448: }
449:
450:
451: /* No Idea what ExactBoundingBox means. Hope it also works with this code */
452:
453: /* I thought Postscript says that the bounding box should be integer.
454: However, some applications (like Corel Draw) use floats and gs has no
455: problem with it. So I use floats for translate that will result in a
456: more exact box. Since gs seems not to be able to use floats in
457: setpagedevice, these values are converted to integer */
458:
459: if(!BBCorrected){ /* write Bounding box one time only! */
460: if(sscanf(ch,"%*s %lf %lf %lf %lf",&bbllx,&bblly,&bburx,&bbury)!=4){
461: fprintf(stderr,"incorrect %s \n",BBname);
462: if(usegs && !debug) remove(tmpfile);
463: status=1;
464: goto EXIT;
465: }
466: if(debug) printf("BoundingBox: %f %f %f %f\n",bbllx,bblly,bburx,bbury);
467: bblly -= enlarge;
468: bbllx -= enlarge;
469: bbury += enlarge;
470: bburx += enlarge;
471: width = ceil(bburx-bbllx); /* make papersize integer and enlarge it a little bit */
472: height = ceil(bbury-bblly);
473: xoffset =-bbllx;
474: yoffset =-bblly;
475: fprintf(out,"%s %d %d %d %d\n",BBname,0,0,width,height);
476: fprintf(out,"<< /PageSize [%d %d] >> setpagedevice \n",width,height);
477: if(isint(xoffset) && isint(yoffset)) fprintf(out,"gsave %d %d translate\n",round(xoffset),round(yoffset));
478: else fprintf(out,"gsave %f %f translate\n",xoffset,yoffset);
479: if(!filter) printf(" (%dx%d mm) ... ",(int)(25.4/72.*width),(int)(25.4/72.*height));
480: did_CR=1;
481: BBCorrected=1;
482: }
483: }else{
484: fputs(ch,out);
485: if(strpbrk(ch, "\n")) did_CR=1;
486: else did_CR=0;
487: if(!strncmp(ch,PSEOF,strlen(PSEOF)) && depth==0) break; /* end of file */
488: }
489: }
490: if(BBCorrected){
491: if(!did_CR) fprintf(out,"\ngrestore\n");
492: else fprintf(out, "grestore\n");
493: }
494: if(in !=stdin ) fclose(in);
495: if(out!=stdout) fclose(out);
496:
497: if(width && height){
498: if (xpix) res=(72*xpix)/width;
499: else if (ypix) res=(72*ypix)/height;
500: }
501:
502:
503: /******************************************************************
504:
505: do the conversion eps->pdf using gs
506:
507: ******************************************************************/
508:
509:
510: if(usegs){
511:
512: if(compress) copt="-dUseFlateCompression=true";
513: else copt="-dUseFlateCompression=false";
514:
515: if(res) sprintf(ropt,"-r%d",res);
516: else ropt[0]='\0';
517:
518: if(res && debug) printf(" (%d dpi) ... ",res);
519:
520: /* The shell 4nt has Problems with double quotes in the command line.
521: Thus use them only if it is really necessary (if there are space
522: characters in a filename)
523: */
524: if(strchr(outfile,' ') || strchr(tmpfile,' '))
525: sprintf(command,"%s -q -dNOPAUSE -dBATCH %s -sDEVICE=%s %s %s"
526: " \"-sOutputFile=%s\" -f \"%s\"",
527: gsexec,copt,device,ropt,gsopt,outfile,tmpfile);
528: else
529: sprintf(command,"%s -q -dNOPAUSE -dBATCH %s -sDEVICE=%s %s %s"
530: " -sOutputFile=%s -f %s",
531: gsexec,copt,device,ropt,gsopt,outfile,tmpfile);
532:
533:
534: if(debug) printf("running ghostscript ...\n");
535: if(debug) puts(command);
536: status=system(command);
537: if(!debug) remove(tmpfile);
538: else printf("keeping temporary file >>%s<<\n",tmpfile);
539: }
540:
541: if(!filter) printf("Done\n");
542:
543:
544:
545: EXIT:
546:
547: free(outfile);
548: free(tmpfile);
549: free(gsopt);
550:
551: if(wait){
552: printf("\n<Press a key> ");
553: getchar();
554: printf("\n");
555: }
556:
557: return status;
558: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>