Annotation of ratfiv/epstopdf_perl.txt, revision 1.1.1.1

1.1       brouard     1: eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' && eval 'exec perl -S $0 $argv:q'
                      2:   if 0;
                      3: use strict;
                      4: 
                      5: # Change by Thomas Esser, Sept. 1998: The above lines allows us to find
                      6: # perl along $PATH rather than guessing a fixed location. The above
                      7: # construction should work with most shells.
                      8: 
                      9: # A script to transform an EPS file so that:
                     10: #   a) it is guarenteed to start at the 0,0 coordinate
                     11: #   b) it sets a page size exactly corresponding to the BoundingBox
                     12: # This means that when Ghostscript renders it, the result needs no
                     13: # cropping, and the PDF MediaBox is correct.
                     14: #   c) the result is piped to Ghostscript and a PDF version written
                     15: #
                     16: # It needs a Level 2 PS interpreter.
                     17: # If the bounding box is not right, of course, you have problems...
                     18: #
                     19: # The only thing I have not allowed for is the case of
                     20: # "%%BoundingBox: (atend)", which is more complicated.
                     21: #
                     22: # Sebastian Rahtz, for Elsevier Science
                     23: #
                     24: # now with extra tricks from Hans Hagen's texutil.
                     25: #
                     26: # History
                     27: #  1999/05/06 v2.5 (Heiko Oberdiek)
                     28: #    * New options: --hires, --exact, --filter, --help.
                     29: #    * Many cosmetics: title, usage, ...
                     30: #    * New code for debug, warning, error
                     31: #    * Detecting of cygwin perl
                     32: #    * Scanning for %%{Hires,Exact,}BoundingBox.
                     33: #    * Scanning only the header in order not to get a wrong
                     34: #      BoundingBox of an included file.
                     35: #    * (atend) supported.
                     36: #    * uses strict; (earlier error detecting).
                     37: #    * changed first comment from '%!PS' to '%!';
                     38: #    * corrected (atend) pattern: '\s*\(atend\)'
                     39: #    * using of $bbxpat in all BoundingBox cases,
                     40: #      correct the first white space to '...Box:\s*$bb...'
                     41: #    * corrected first line (one line instead of two before 'if 0;';
                     42: #
                     43: 
                     44: ### program identification
                     45: my $program = "epstopdf";
                     46: my $filedate="1999/05/06";
                     47: my $fileversion="2.5";
                     48: my $copyright = "Copyright 1998,1999 by Sebastian Rahtz et al.";
                     49: my $title = "\U$program\E $fileversion, $filedate - $copyright\n";
                     50: 
                     51: ### ghostscript command name
                     52: my $GS = "gs";
                     53: $GS = "gswin32c" if $^O eq 'MSWin32';
                     54: $GS = "gswin32c" if $^O =~ /cygwin/;
                     55: 
                     56: ### options
                     57: $::opt_help=0;
                     58: $::opt_debug=0;
                     59: $::opt_compress=1;
                     60: $::opt_gs=1;
                     61: $::opt_hires=0;
                     62: $::opt_exact=0;
                     63: $::opt_filter=0;
                     64: $::opt_outfile="";
                     65: 
                     66: ### usage
                     67: my @bool = ("false", "true");
                     68: my $usage = <<"END_OF_USAGE";
                     69: ${title}Syntax:  $program [options] <eps file>
                     70: Options:
                     71:   --help:           print usage
                     72:   --outfile=<file>: write result to <file>
                     73:   --(no)filter:     read standard input   (default: $bool[$::opt_filter])
                     74:   --(no)gs:         run ghostscript       (default: $bool[$::opt_gs])
                     75:   --(no)compress:   use compression       (default: $bool[$::opt_compress])
                     76:   --(no)hires:      scan HiresBoundingBox (default: $bool[$::opt_hires])
                     77:   --(no)exact:      scan ExactBoundingBox (default: $bool[$::opt_exact])
                     78:   --(no)debug:      debug informations    (default: $bool[$::opt_debug])
                     79: Examples for producing 'test.pdf':
                     80:   * $program test.eps
                     81:   * produce postscript | $program --filter >test.pdf
                     82:   * produce postscript | $program -f -d -o=test.pdf
                     83: Example: look for HiresBoundingBox and produce corrected PostScript:
                     84:   * $program -d --nogs -hires test.ps>testcorr.ps 
                     85: END_OF_USAGE
                     86: 
                     87: ### process options
                     88: use Getopt::Long;
                     89: GetOptions (
                     90:   "help!",
                     91:   "debug!",
                     92:   "filter!",
                     93:   "compress!",
                     94:   "gs!",
                     95:   "hires!",
                     96:   "exact!",
                     97:   "outfile=s",
                     98: ) or die $usage;
                     99: 
                    100: ### help functions
                    101: sub debug {
                    102:   print STDERR "* @_\n" if $::opt_debug;
                    103: }
                    104: sub warning {
                    105:   print STDERR "==> Warning: @_!\n";
                    106: }
                    107: sub error {
                    108:   die "$title!!! Error: @_!\n";
                    109: }
                    110: sub errorUsage {
                    111:   die "$usage\n!!! Error: @_!\n";
                    112: }
                    113: 
                    114: ### option help
                    115: die $usage if $::opt_help;
                    116: 
                    117: ### get input filename
                    118: my $InputFilename = "";
                    119: if ($::opt_filter) {
                    120:   @ARGV == 0 or 
                    121:     die errorUsage "Input file cannot be used with filter option";
                    122:   $InputFilename = "-";
                    123:   debug "Input file: standard input";
                    124: }
                    125: else {
                    126:   @ARGV > 0 or die errorUsage "Input filename missing";
                    127:   @ARGV < 2 or die errorUsage "Unknown option or too many input files";
                    128:   $InputFilename = $ARGV[0];
                    129:   -f $InputFilename or error "'$InputFilename' does not exist";
                    130:   debug "Input filename:", $InputFilename;
                    131: }
                    132: 
                    133: ### option compress
                    134: my $GSOPTS = "";
                    135: $GSOPTS = "-dUseFlateCompression=false " unless $::opt_compress;
                    136: 
                    137: ### option BoundingBox types
                    138: my $BBName = "%%BoundingBox:";
                    139: !($::opt_hires and $::opt_exact) or
                    140:   error "Options --hires and --exact cannot be used together";
                    141: $BBName = "%%HiresBoundingBox:" if $::opt_hires;
                    142: $BBName = "%%ExactBoundingBox:" if $::opt_exact;
                    143: debug "BoundingBox comment:", $BBName;
                    144: 
                    145: ### option outfile
                    146: my $OutputFilename = $::opt_outfile;
                    147: if ($OutputFilename eq "") {
                    148:   if ($::opt_gs) {
                    149:     $OutputFilename = $InputFilename;
                    150:     if (!$::opt_filter) {
                    151:       $OutputFilename =~ s/\.[^\.]*$//;
                    152:       $OutputFilename .= ".pdf";
                    153:     }
                    154:   }
                    155:   else {
                    156:     $OutputFilename = "-"; # standard output
                    157:   }
                    158: }
                    159: if ($::opt_filter) {
                    160:   debug "Output file: standard output";
                    161: }
                    162: else {
                    163:   debug "Output filename:", $OutputFilename;
                    164: }
                    165: 
                    166: ### option gs
                    167: if ($::opt_gs) {
                    168:   debug "Ghostscript command:", $GS;
                    169:   debug "Compression:", ($::opt_compress) ? "on" : "off";
                    170: }
                    171: 
                    172: ### open input file
                    173: open(IN,"<$InputFilename") or error "Cannot open", 
                    174:   ($::opt_filter) ? "standard input" : "'$InputFilename'";
                    175: binmode IN;
                    176: 
                    177: ### open output file
                    178: if ($::opt_gs) {
                    179:   my $pipe = "$GS -q -sDEVICE=pdfwrite $GSOPTS " .
                    180:           "-sOutputFile=$OutputFilename - -c quit";
                    181:   debug "Ghostscript pipe:", $pipe;
                    182:   open(OUT,"|$pipe") or error "Cannot open Ghostscript for piped input";
                    183: }
                    184: else {
                    185:   open(OUT,">$OutputFilename") or error "Cannot write '$OutputFilename";
                    186: }
                    187: 
                    188: ### scan first line
                    189: my $header = 0;
                    190: $_ = <IN>;
                    191: if (/%!/) {
                    192:   # throw away binary junk before %!
                    193:   s/(.*)%!/%!/o;
                    194: }
                    195: $header = 1 if /^%/;
                    196: debug "Scanning header for BoundingBox";
                    197: print OUT;
                    198: 
                    199: ### variables and pattern for BoundingBox search
                    200: my $bbxpatt = '[0-9eE\.\-]';
                    201:                # protect backslashes: "\\" gets '\'
                    202: my $BBValues = "\\s*($bbxpatt+)\\s+($bbxpatt+)\\s+($bbxpatt+)\\s+($bbxpatt+)";
                    203: my $BBCorrected = 0;
                    204: 
                    205: sub CorrectBoundingBox {
                    206:   my ($llx, $lly, $urx, $ury) = @_;
                    207:   debug "Old BoundingBox:", $llx, $lly, $urx, $ury;
                    208:   my ($width, $height) = ($urx - $llx, $ury - $lly);
                    209:   my ($xoffset, $yoffset) = (-$llx, -$lly);
                    210:   debug "New BoundingBox: 0 0", $width, $height;
                    211:   debug "Offset:", $xoffset, $yoffset;
                    212: 
                    213:   print OUT "%%BoundingBox: 0 0 $width $height\n";
                    214:   print OUT "<< /PageSize [$width $height] >> setpagedevice\n";
                    215:   print OUT "gsave $xoffset $yoffset translate\n";
                    216: }
                    217: 
                    218: ### scan header
                    219: if ($header) {
                    220:   while (<IN>) {
                    221: 
                    222:     ### end of header
                    223:     if (!/^%/ or /^%%EndComments/) {
                    224:       print OUT;
                    225:       last;
                    226:     }
                    227: 
                    228:     ### BoundingBox with values
                    229:     if (/^$BBName$BBValues/) {
                    230:       CorrectBoundingBox $1, $2, $3, $4;
                    231:       $BBCorrected = 1;
                    232:       last;
                    233:     }
                    234: 
                    235:     ### BoundingBox with (atend)
                    236:     if (/^$BBName\s*\(atend\)/) {
                    237:       debug $BBName, "(atend)";
                    238:       if ($::opt_filter) {
                    239:         warning "Cannot look for BoundingBox in the trailer",
                    240:                 "with option --filter";
                    241:         last;
                    242:       }
                    243:       my $pos = tell(IN);
                    244:       debug "Current file position:", $pos;
                    245: 
                    246:       # looking for %%BoundingBox
                    247:       while (<IN>) {
                    248:         # skip over included documents
                    249:         if (/^%%BeginDocument/) {
                    250:           while (<IN>) {
                    251:             last if /^%%EndDocument/;
                    252:           }
                    253:         }
                    254:         if (/^$BBName$BBValues/) {
                    255:           CorrectBoundingBox $1, $2, $3, $4;
                    256:           $BBCorrected = 1;
                    257:           last;
                    258:         }
                    259:       }
                    260: 
                    261:       # go back
                    262:       seek(IN, $pos, 0) or error "Cannot go back to line '$BBName (atend)'";
                    263:       last;
                    264:     }
                    265:     
                    266:     # print header line
                    267:     print OUT;
                    268:   }
                    269: }
                    270: 
                    271: ### print rest of file
                    272: while (<IN>) {
                    273:   print OUT;
                    274: }
                    275: 
                    276: ### close files
                    277: close(IN);
                    278: print OUT "grestore\n" if $BBCorrected;
                    279: close(OUT);
                    280: warning "BoundingBox not found" unless $BBCorrected;
                    281: debug "Ready.";
                    282: ;

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>