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>