/*
# 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#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=<file>: write result to <file>\n");
printf(" --tmpfile=<file>: use <file> 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=<gs>: use <gs> to invoke ghostscript (default: %s)\n",GSEXEC);
printf(" --enlarge=<a>: enlarge BB by <a>/72 '' (default: 0.)\n");
printf(" -sDEVICE=<dev> : use <dev> as output device (default: pdfwrite)\n");
printf(" -r<a>: output resolution for gs (default: 600)\n");
printf(" --width=<a>: output width in pixels (default: none)\n");
printf(" --height=<a>: output height in pixels (default: none)\n");
printf(" --gsopt=<a>: add <a> 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<argc;i++){
/* printf("i=%d arg=>>%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<argc){
outfile=malloc(strlen(argv[i+1])+1);
strcpy(outfile, argv[i+1]);
i++;
continue;
}
if(!strncmp(argv[i],"--gsexec=",strlen("--gsexec="))){
gsexec=argv[i]+strlen("--gsexec=");
continue;
}
if(argv[i][0]!='-'){
if(infile) printf("\nCan process only one input file\n");
else infile=argv[i];
continue;
}
if(!strncmp(argv[i],"--enlarge=",strlen("--enlarge="))){
sscanf(argv[i]+strlen("--enlarge="),"%lf",&enlarge);
continue;
}
usage();
fprintf(stderr,"\nunknown option >>%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<Press a key> ");
getchar();
printf("\n");
}
return status;
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>