monotone

monotone Mtn Source Tree

Root/figures/pdfcrop.pl

1eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' && eval 'exec perl -S $0 $argv:q'
2 if 0;
3use strict;
4$^W=1; # turn warning on
5#
6# pdfcrop.pl
7#
8# Copyright (C) 2002, 2004 Heiko Oberdiek.
9#
10# This program may be distributed and/or modified under the
11# conditions of the LaTeX Project Public License, either version 1.2
12# of this license or (at your option) any later version.
13# The latest version of this license is in
14# http://www.latex-project.org/lppl.txt
15# and version 1.2 or later is part of all distributions of LaTeX
16# version 1999/12/01 or later.
17#
18# See file "readme.txt" for a list of files that belong to this project.
19#
20# This file "pdfcrop.pl" may be renamed to "pdfcrop"
21# for installation purposes.
22#
23my $file = "pdfcrop.pl";
24my $program = uc($&) if $file =~ /^\w+/;
25my $version = "1.5";
26my $date = "2004/06/24";
27my $author = "Heiko Oberdiek";
28my $copyright = "Copyright (c) 2002, 2004 by $author.";
29#
30# Reqirements: Perl5, Ghostscript
31# History:
32# 2002/10/30 v1.0: First release.
33# 2002/10/30 v1.1: Option --hires added.
34# 2002/11/04 v1.2: "nul" instead of "/dev/null" for windows.
35# 2002/11/23 v1.3: Use of File::Spec module's "devnull" call.
36# 2002/11/29 v1.4: Option --papersize added.
37# 2004/06/24 v1.5: Clear map file entries so that pdfTeX
38# does not touch the fonts.
39#
40
41### program identification
42my $title = "$program $version, $date - $copyright\n";
43
44### error strings
45my $Error = "!!! Error:"; # error prefix
46
47### string constants for Ghostscript run
48# get Ghostscript command name
49my $GS = "gs";
50$GS = "gs386" if $^O =~ /dos/i;
51$GS = "gsos2" if $^O =~ /os2/i;
52$GS = "gswin32c" if $^O =~ /mswin32/i;
53$GS = "gswin32c" if $^O =~ /cygwin/i;
54
55# Windows detection (no SIGHUP)
56my $Win = 0;
57$Win = 1 if $^O =~ /mswin32/i;
58$Win = 1 if $^O =~ /cygwin/i;
59
60# "null" device
61use File::Spec::Functions qw(devnull);
62my $null = devnull();
63
64### variables
65my $inputfile = "";
66my $outputfile = "";
67my $tmp = "tmp-\L$program\E-$$";
68
69### option variables
70my @bool = ("false", "true");
71$::opt_help = 0;
72$::opt_debug = 0;
73$::opt_verbose = 0;
74$::opt_gscmd = $GS;
75$::opt_pdftexcmd = "pdftex";
76$::opt_margins = "0 0 0 0";
77$::opt_clip = 0;
78$::opt_hires = 0;
79$::opt_papersize = "";
80
81my $usage = <<"END_OF_USAGE";
82${title}Syntax: \L$program\E [options] <input[.pdf]> [output file]
83Function: Margins are calculated and removed for each page in the file.
84Options: (defaults:)
85 --help print usage
86 --(no)verbose verbose printing ($bool[$::opt_verbose])
87 --(no)debug debug informations ($bool[$::opt_debug])
88 --gscmd <name> call of ghostscript ($::opt_gscmd)
89 --pdftexcmd <name> call of pdfTeX ($::opt_pdftexcmd)
90 --margins "<left> <top> <right> <bottom>" ($::opt_margins)
91 add extra margins, unit is bp. If only one number is
92 given, then it is used for all margins, in the case
93 of two numbers they are also used for right and bottom.
94 --(no)clip clipping support, if margins are set ($bool[$::opt_clip])
95 --(no)hires using `%%HiResBoundingBox' ($bool[$::opt_hires])
96 instead of `%%BoundingBox'
97 --papersize <foo> parameter for gs's -sPAPERSIZE=<foo>,
98 use only with older gs versions <7.32 ($::opt_papersize)
99Examples:
100 \L$program\E --margins 10 input.pdf output.pdf
101 \L$program\E --margins '5 10 5 20' --clip input.pdf output.pdf
102END_OF_USAGE
103
104### process options
105my @OrgArgv = @ARGV;
106use Getopt::Long;
107GetOptions(
108 "help!",
109 "debug!",
110 "verbose!",
111 "gscmd=s",
112 "pdftexcmd=s",
113 "margins=s",
114 "clip!",
115 "hires!",
116 "papersize=s",
117) or die $usage;
118!$::opt_help or die $usage;
119
120$::opt_verbose = 1 if $::opt_debug;
121
122@ARGV >= 1 or die $usage;
123
124print $title;
125
126@ARGV <= 2 or die "$Error Too many files!\n";
127
128### input file
129$inputfile = shift @ARGV;
130
131if (! -f $inputfile) {
132 if (-f "$inputfile.pdf") {
133 $inputfile .= ".pdf";
134 }
135 else {
136 die "$Error Input file `$inputfile' not found!\n";
137 }
138}
139
140print "* Input file: $inputfile\n" if $::opt_debug;
141
142### output file
143if (@ARGV) {
144 $outputfile = shift @ARGV;
145}
146else {
147 $outputfile = $inputfile;
148 $outputfile =~ s/\.pdf$//i;
149 $outputfile .= "-crop.pdf";
150}
151
152print "* Output file: $outputfile\n" if $::opt_debug;
153
154### margins
155my ($llx, $lly, $urx, $ury) = (0, 0, 0, 0);
156if ($::opt_margins =~
157 /^\s*([\-\.\d]+)\s+([\-\.\d]+)\s+([\-\.\d]+)\s+([\-\.\d]+)\s*$/) {
158 ($llx, $lly, $urx, $ury) = ($1, $2, $3, $4);
159}
160else {
161 if ($::opt_margins =~ /^\s*([\-\.\d]+)\s+([\-\.\d]+)\s*$/) {
162 ($llx, $lly, $urx, $ury) = ($1, $2, $1, $2);
163 }
164 else {
165 if ($::opt_margins =~ /^\s*([\-\.\d]+)\s*$/) {
166 ($llx, $lly, $urx, $ury) = ($1, $1, $1, $1);
167 }
168 else {
169 die "$Error Parse error (option --margins)!\n";
170 }
171 }
172}
173print "* Margins: $llx $lly $urx $ury\n" if $::opt_debug;
174
175### cleanup system
176my @unlink_files = ();
177my $exit_code = 1;
178sub clean {
179 print "* Cleanup\n" if $::opt_debug;
180 if ($::opt_debug) {
181 print "* Temporary files: @unlink_files\n";
182 }
183 else {
184 for (; @unlink_files>0; ) {
185 unlink shift @unlink_files;
186 }
187 }
188}
189sub cleanup {
190 clean();
191 exit($exit_code);
192}
193$SIG{'INT'} = \&cleanup;
194$SIG{'__DIE__'} = \&clean;
195
196### Calculation of BoundingBoxes
197
198my $cmd = "$::opt_gscmd -sDEVICE=bbox -dBATCH -dNOPAUSE ";
199$cmd .= "-sPAPERSIZE=$::opt_papersize " if $::opt_papersize;
200$cmd .= "-c save pop -f " . $inputfile;
201my $cmdpipe = $cmd . " 2>&1 1>$null |";
202
203my $tmpfile = "$tmp.tex";
204push @unlink_files, $tmpfile;
205open(TMP, ">$tmpfile") or
206 die "$Error Cannot write tmp file `$tmpfile'!\n";
207print TMP "\\def\\pdffile{$inputfile}\n";
208print TMP <<'END_TMP_HEAD';
209\csname pdfmapfile\endcsname{}
210\def\page #1 [#2 #3 #4 #5]{%
211 \count0=#1\relax
212 \setbox0=\hbox{%
213 \pdfximage page #1{\pdffile}%
214 \pdfrefximage\pdflastximage
215 }%
216 \pdfhorigin=-#2bp\relax
217 \pdfvorigin=#3bp\relax
218 \pdfpagewidth=#4bp\relax
219 \advance\pdfpagewidth by -#2bp\relax
220 \pdfpageheight=#5bp\relax
221 \advance\pdfpageheight by -#3bp\relax
222 \ht0=\pdfpageheight
223 \shipout\box0\relax
224}
225\def\pageclip #1 [#2 #3 #4 #5][#6 #7 #8 #9]{%
226 \count0=#1\relax
227 \dimen0=#4bp\relax \advance\dimen0 by -#2bp\relax
228 \edef\imagewidth{\the\dimen0}%
229 \dimen0=#5bp\relax \advance\dimen0 by -#3bp\relax
230 \edef\imageheight{\the\dimen0}%
231 \pdfximage page #1{\pdffile}%
232 \setbox0=\hbox{%
233 \kern -#2bp\relax
234 \lower #3bp\hbox{\pdfrefximage\pdflastximage}%
235 }%
236 \wd0=\imagewidth\relax
237 \ht0=\imageheight\relax
238 \dp0=0pt\relax
239 \pdfhorigin=#6pt\relax
240 \pdfvorigin=#7bp\relax
241 \pdfpagewidth=\imagewidth
242 \advance\pdfpagewidth by #6bp\relax
243 \advance\pdfpagewidth by #8bp\relax
244 \pdfpageheight=\imageheight\relax
245 \advance\pdfpageheight by #7bp\relax
246 \advance\pdfpageheight by #9bp\relax
247 \pdfxform0\relax
248 \shipout\hbox{\pdfrefxform\pdflastxform}%
249}%
250END_TMP_HEAD
251
252print "* Running ghostscript for BoundingBox calculation ...\n"
253 if $::opt_verbose;
254print "* Ghostscript pipe: $cmdpipe\n" if $::opt_debug;
255
256my $page = 0;
257open(CMD, $cmdpipe) or
258 die "$Error Cannot call ghostscript!\n";
259while (<CMD>) {
260 my $bb = ($::opt_hires) ? "%%HiResBoundingBox" : "%%BoundingBox";
261 next unless
262 /^$bb:\s*([\.\d]+) ([\.\d]+) ([\.\d]+) ([\.\d]+)/o;
263 $page++;
264 print "* Page $page: $1 $2 $3 $4\n" if $::opt_verbose;
265 if ($::opt_clip) {
266 print TMP "\\pageclip $page [$1 $2 $3 $4][$llx $lly $urx $ury]\n";
267 }
268 else {
269 my ($a, $b, $c, $d) = ($1 - $llx, $2 - $ury, $3 + $urx, $4 + $lly);
270 print TMP "\\page $page [$a $b $c $d]\n";
271 }
272}
273close(CMD);
274
275print TMP "\\csname \@\@end\\endcsname\n\\end\n";
276close(TMP);
277
278### Run pdfTeX
279
280push @unlink_files, "$tmp.log";
281if ($::opt_verbose) {
282 $cmd = "$::opt_pdftexcmd -interaction=nonstopmode $tmp";
283}
284else {
285 $cmd = "$::opt_pdftexcmd -interaction=batchmode $tmp";
286}
287print "* Running pdfTeX ...\n" if $::opt_verbose;
288print "* pdfTeX call: $cmd\n" if $::opt_debug;
289if ($::opt_verbose) {
290 system($cmd);
291}
292else {
293 `$cmd`;
294}
295if ($?) {
296 die "$Error pdfTeX run failed!\n";
297}
298
299### Move temp file to output
300rename "$tmp.pdf", $outputfile or
301 die "$Error Cannot move `$tmp.pdf' to `$outputfile'!\n";
302
303print "==> $page pages written on `$outputfile'.\n";
304
305$exit_code = 0;
306cleanup();
307
308__END__

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status