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>