/* # epstopdf: written by Kong Hoon Lee konghoon@hyowon.cc.pusan.ac.kr<4/1/1999> # # It converts an EPS file to an encapsulated PDF File and # coded with the perl script 'epstopdf' by Sebastian Rahtz on # http://tug.org/applications/pdftex/epstopdf . # It works like as the perl script without 'perl' for Windows 95 # but requires 'Ghostscript' for Windows. # */ #include #include #include #include #define MAX_IN 10000 #ifndef GSEXEC #ifdef __WIN32__ #define GSEXEC "gswin32c" #else #define GSEXEC "gs" #endif #endif #define BEGINDOC "%%BeginDocument" #define ENDDOC "%%EndDocument" #define PSSTART "%!" #define PSEOF "%%EOF" #define TRUE 1 #define FALSE 0 static void usage(void) { printf("epstopdf 2.2.9:\n"); printf("written by Kong Hoon Lee, konghoon@dreamwiz.com <1999-4-1>\n"); printf("changes by Juergen Bausa, Juergen.Bausa@T-Online.de <2000-10-6>\n"); printf("bugfix by Pascal Perichon, Pascal.Perichon@u-bourgogne.fr <2000-5-25>\n\n"); printf("It converts an EPS file to an encapsulated PDF File and is written\n"); printf("based on the perl script 'epstopdf' by Sebastian Rahtz on\n"); printf("http://tug.org/applications/pdftex/epstopdf .\n"); printf("It works like the perl script without 'perl' but requires 'Ghostscript'.\n"); printf("The accompanied Makefile can be used to automate the update of all eps/pdf\n"); printf("files in a directory. Just put it in the directory where your eps files\n"); printf("are and type 'make' from the command line (you will need a version of\n"); printf("GNU-make)\n\n"); printf("This program invokes '%s' and the path including '%s'\n",GSEXEC,GSEXEC); printf("should be included to the environment variable 'PATH'.\n"); printf("'%s' should know, where to find its initialization files\n",GSEXEC); printf("and fonts, using an registry entry (Windows) or an environment variable.\n\n"); printf("Using a different output device, it is also possible to convert eps\n"); printf("files to bitmaps (e.g. -sDEVICE=bmpmono).\n\n"); printf("Usage: epstopdf [options] filename-of-an-eps-file\n"); printf("Options:\n"); printf(" --help: print usage\n"); printf(" --outfile=: write result to \n"); printf(" --tmpfile=: use as temporary file\n"); printf(" --(no)filter: read/writ standard input/output (default: false)\n"); printf(" --(no)gs: run ghostscript (default: true)\n"); printf(" --(no)compress: use compression (default: true)\n"); printf(" --(no)hires: scan HiresBoundingBox (default: false)\n"); printf(" --(no)exact: scan ExactBoundingBox (default: false)\n"); printf(" --(no)debug: debug informations (default: false)\n"); printf(" --(no)wait: wait for keystroke (default: false)\n"); printf(" --gsexec=: use to invoke ghostscript (default: %s)\n",GSEXEC); printf(" --enlarge=: enlarge BB by /72 '' (default: 0.)\n"); printf(" -sDEVICE= : use as output device (default: pdfwrite)\n"); printf(" -r: output resolution for gs (default: 600)\n"); printf(" --width=: output width in pixels (default: none)\n"); printf(" --height=: output height in pixels (default: none)\n"); printf(" --gsopt=: add to the gs command line (default: none)\n"); } static int round(double a) { return floor(a+0.5); } static int isint(double a) { if(fabs(a-round(a))<1e-6) return 1; else return 0; } int main(int argc,char *argv[]) { FILE *in,*out; char *infile=NULL,*outfile=NULL,*tmpfile=NULL,*copt,*ptr,*gsexec,buf[21]; char command[MAX_IN],ch[MAX_IN],*BBname,*device,ropt[20],*gsopt; double bbllx,bblly,bburx,bbury,xoffset,yoffset,enlarge; int width,height,res,xpix,ypix; int i,count,status,BBCorrected,did_CR,debug,compress,usegs,wait, BBhires,BBexact,found,depth,filter,ngsopt,in_ps; fpos_t fpos; #if defined (__EMX__) _wildcard (&argc, &argv); #endif /* default parameter */ status=0; BBCorrected=0; BBhires=0; BBexact=0; debug=0; compress=1; usegs=1; gsexec=GSEXEC; wait=0; filter=0; enlarge=0.; res=600; device="pdfwrite"; xpix=0; ypix=0; ngsopt=100; gsopt=malloc(ngsopt); gsopt[0]='\0'; /****************************************************************** Process command line options ******************************************************************/ for(i=1;i>%s<<\n",i,argv[i]); */ if(!strcmp(argv[i],"--help") || !strcmp(argv[i],"-h")){ usage(); status=0; goto EXIT; } if(!strcmp(argv[i],"--debug") || !strcmp(argv[i],"-d")){ debug=1; continue; } if(!strcmp(argv[i],"--nodebug")){ debug=0; continue; } if(!strcmp(argv[i],"--compress") || !strcmp(argv[i],"-c")){ compress=1; continue; } if(!strcmp(argv[i],"--nocompress")){ compress=0; continue; } if(!strcmp(argv[i],"--nogs")){ usegs=0; continue; } if(!strcmp(argv[i],"--gs")){ usegs=1; continue; } if(!strcmp(argv[i],"--wait") || !strcmp(argv[i],"-w")){ wait=1; continue; } if(!strcmp(argv[i],"--nowait")){ wait=0; continue; } if(!strcmp(argv[i],"--filter")){ filter=1; continue; } if(!strcmp(argv[i],"--nofilter")){ filter=0; continue; } if(!strcmp(argv[i],"--hires")){ BBhires=1; continue; } if(!strcmp(argv[i],"--nohires")){ BBhires=0; continue; } if(!strcmp(argv[i],"--exact")){ BBexact=1; continue; } if(!strcmp(argv[i],"--noexact")){ BBexact=0; continue; } if(!strncmp(argv[i],"--outfile=",strlen("--outfile="))){ outfile=malloc(strlen(argv[i])-strlen("--outfile=")+1); strcpy(outfile, argv[i]+strlen("--outfile=")); continue; } if(!strncmp(argv[i],"--tmpfile=",strlen("--tmpfile="))){ tmpfile=malloc(strlen(argv[i])-strlen("--tmpfile=")+1); strcpy(tmpfile, argv[i]+strlen("--tmpfile=")); continue; } if(!strncmp(argv[i],"-r",strlen("-r"))){ sscanf(argv[i]+strlen("-r"),"%d",&res); continue; } if(!strncmp(argv[i],"--width=",strlen("--width="))){ sscanf(argv[i]+strlen("--width="),"%d",&xpix); continue; } if(!strncmp(argv[i],"--height=",strlen("--height="))){ sscanf(argv[i]+strlen("--height="),"%d",&ypix); continue; } if(!strncmp(argv[i],"--gsopt=",strlen("--gsopt="))){ char *opt=argv[i]+strlen("--gsopt="); if(strlen(gsopt)+strlen(opt)+2 < ngsopt){ ngsopt+=100; gsopt=realloc(gsopt,ngsopt); } strcat(gsopt," "); strcat(gsopt,opt); continue; } if(!strncmp(argv[i],"-sDEVICE=",strlen("-sDEVICE="))){ device=argv[i]+strlen("-sDEVICE="); continue; } if(!strcmp(argv[i],"-o") && i+1>%s<<\n",argv[i]); status=1; goto EXIT; } /****************************************************************** check arguments and files ******************************************************************/ if(filter) debug=0; if(filter) wait =0; if(BBexact && BBhires){ fprintf(stderr,"\nOptions --hires and --exact cannot be used together\n"); status=1; goto EXIT; } if (BBexact) BBname="%%ExactBoundingBox:"; else if(BBhires) BBname="%%HiresBoundingBox:"; else BBname="%%BoundingBox:"; if(!filter) { if(!infile) { usage(); fprintf(stderr,"no input file specified!\n"); status=1; goto EXIT; } if((in=fopen(infile,"r")) == NULL) { usage(); fprintf(stderr,"%s: File not found!\n",infile); status=1; goto EXIT; } fclose(in); }else{ if(infile) { fprintf(stderr,"Input file cannot be used with filter option!\n"); status=1; goto EXIT; } infile="epstopdf"; /* dummy input filename to generate tmp-filename */ } /* find a temporary filename that does not exist yet */ if(usegs && !tmpfile){ tmpfile=malloc(strlen(infile)+9); count=0; do{ if(count>99) { fprintf(stderr,"No temporary file available! Try deleting *.tmp.\n\n"); status=1; goto EXIT; } sprintf(tmpfile,"%s.%d.tmp",infile,count); if(debug) printf("checking temporary filename >>%s<<\n",tmpfile); out=fopen(tmpfile,"r"); if(out) fclose(out); count++; }while(out); } if(!filter){ if(!outfile){ outfile=malloc(strlen(infile)+6); strcpy(outfile,infile); ptr=outfile; while(strpbrk(ptr,"\\/")) ptr=strpbrk(ptr,"\\/")+1; ptr=strrchr(ptr,'.'); if(ptr) *ptr='\0'; if(usegs) strcat(outfile,".pdf"); else strcat(outfile,"2.eps"); } }else{ if(outfile) { fprintf(stderr,"Output file cannot be used with filter option!\n"); status=1; goto EXIT; } outfile=malloc(2); strcpy(outfile,"-"); } if(!filter) printf("Converting %s to %s ..... ",infile,outfile); /****************************************************************** put the pagesize from the bounding box into the eps file ******************************************************************/ if(debug) printf("\nAdding correct pagesize to EPS ... searching for %s ...\n",BBname); if (!filter) in = fopen(infile, "r"); else in = stdin; if (usegs) out = fopen(tmpfile,"w"); else if(!filter) out = fopen(outfile,"w"); else out = stdout; if(!in || !out){ fprintf(stderr,"cannot open files\n"); status=1; goto EXIT; } depth=0; in_ps=FALSE; while (fgets(ch,MAX_IN,in)){ if(!in_ps) { /* throw away binary junk before %! */ if(!strncmp(ch,PSSTART,strlen(PSSTART))) in_ps=TRUE; else continue; } if(!strncmp(ch,BEGINDOC,strlen(BEGINDOC))) depth++; /* count included documents */ if(!strncmp(ch,ENDDOC, strlen(ENDDOC) )) depth--; if(!strncmp(ch,BBname, strlen(BBname)) && depth==0) { /* look for BB comment in main doc only */ sscanf(ch,"%*s %20s",buf); if(!strcmp(buf,"(atend)")){ /* BB is atended */ if(filter){ fprintf(stderr,"Cannot look for BoundingBox in the trailer " "with option --filter\n"); if(usegs) remove(tmpfile); status=1; goto EXIT; } if(debug) printf("\n (atend)! ...\n"); fgetpos(in, &fpos); /* store file position */ found=0; while (fgets(ch,MAX_IN,in)){ if(!strncmp(ch,BEGINDOC,strlen(BEGINDOC))) depth++; /* count included documents */ if(!strncmp(ch,ENDDOC, strlen(ENDDOC) )) depth--; if(!strncmp(ch,BBname,strlen(BBname)) && depth==0) { /* look for bounding box in main doc only */ found=1; fsetpos(in, &fpos); /* rewind to (atend) comment */ break; } } if(!found){ fprintf(stderr,"atended %s not found\n",BBname); if(usegs && !debug) remove(tmpfile); if(!usegs && !debug) remove(outfile); status=1; goto EXIT; } } /* No Idea what ExactBoundingBox means. Hope it also works with this code */ /* I thought Postscript says that the bounding box should be integer. However, some applications (like Corel Draw) use floats and gs has no problem with it. So I use floats for translate that will result in a more exact box. Since gs seems not to be able to use floats in setpagedevice, these values are converted to integer */ if(!BBCorrected){ /* write Bounding box one time only! */ if(sscanf(ch,"%*s %lf %lf %lf %lf",&bbllx,&bblly,&bburx,&bbury)!=4){ fprintf(stderr,"incorrect %s \n",BBname); if(usegs && !debug) remove(tmpfile); status=1; goto EXIT; } if(debug) printf("BoundingBox: %f %f %f %f\n",bbllx,bblly,bburx,bbury); bblly -= enlarge; bbllx -= enlarge; bbury += enlarge; bburx += enlarge; width = ceil(bburx-bbllx); /* make papersize integer and enlarge it a little bit */ height = ceil(bbury-bblly); xoffset =-bbllx; yoffset =-bblly; fprintf(out,"%s %d %d %d %d\n",BBname,0,0,width,height); fprintf(out,"<< /PageSize [%d %d] >> setpagedevice \n",width,height); if(isint(xoffset) && isint(yoffset)) fprintf(out,"gsave %d %d translate\n",round(xoffset),round(yoffset)); else fprintf(out,"gsave %f %f translate\n",xoffset,yoffset); if(!filter) printf(" (%dx%d mm) ... ",(int)(25.4/72.*width),(int)(25.4/72.*height)); did_CR=1; BBCorrected=1; } }else{ fputs(ch,out); if(strpbrk(ch, "\n")) did_CR=1; else did_CR=0; if(!strncmp(ch,PSEOF,strlen(PSEOF)) && depth==0) break; /* end of file */ } } if(BBCorrected){ if(!did_CR) fprintf(out,"\ngrestore\n"); else fprintf(out, "grestore\n"); } if(in !=stdin ) fclose(in); if(out!=stdout) fclose(out); if(width && height){ if (xpix) res=(72*xpix)/width; else if (ypix) res=(72*ypix)/height; } /****************************************************************** do the conversion eps->pdf using gs ******************************************************************/ if(usegs){ if(compress) copt="-dUseFlateCompression=true"; else copt="-dUseFlateCompression=false"; if(res) sprintf(ropt,"-r%d",res); else ropt[0]='\0'; if(res && debug) printf(" (%d dpi) ... ",res); /* The shell 4nt has Problems with double quotes in the command line. Thus use them only if it is really necessary (if there are space characters in a filename) */ if(strchr(outfile,' ') || strchr(tmpfile,' ')) sprintf(command,"%s -q -dNOPAUSE -dBATCH %s -sDEVICE=%s %s %s" " \"-sOutputFile=%s\" -f \"%s\"", gsexec,copt,device,ropt,gsopt,outfile,tmpfile); else sprintf(command,"%s -q -dNOPAUSE -dBATCH %s -sDEVICE=%s %s %s" " -sOutputFile=%s -f %s", gsexec,copt,device,ropt,gsopt,outfile,tmpfile); if(debug) printf("running ghostscript ...\n"); if(debug) puts(command); status=system(command); if(!debug) remove(tmpfile); else printf("keeping temporary file >>%s<<\n",tmpfile); } if(!filter) printf("Done\n"); EXIT: free(outfile); free(tmpfile); free(gsopt); if(wait){ printf("\n "); getchar(); printf("\n"); } return status; }