From 6eb709b9a854321acdb740cf3403a55e76298e92 Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Sat, 21 Jan 2012 22:01:42 +0100 Subject: %config --- pdftool.pl | 306 +++++++++++++++++++++++++++++++------------------------------ 1 file changed, 158 insertions(+), 148 deletions(-) diff --git a/pdftool.pl b/pdftool.pl index fd8e4c7..51c57b2 100755 --- a/pdftool.pl +++ b/pdftool.pl @@ -253,51 +253,46 @@ my @gs = ('gs', '-dSAFER'); # Options & arguments # -my $select; -my ($outwidth,$outheight, $inwidth,$inheight); -my ($margin, $border); -my $crop; -my $book; -my $nup = 1; -my $column; -my $quiet; -my $man; -my $autorotate; -my $psout; - -GetOptions( "select|s=s" => \$select, - "w|width=s" => \$outwidth, - "h|height=s" => \$outheight, - "p|paper=s" => sub { &papersize ($_[1],\$outwidth,\$outheight) }, - "W|Width=s" => \$inwidth, - "H|Height=s" => \$inheight, - "P|Paper=s" => sub { &papersize ($_[1],\$inwidth,\$inheight) }, - "margin|m=s" => \$margin, - "border|b=s" => \$border, - "crop|c" => \$crop, - "book" => \$book, - "ps" => \$psout, - "nup|n=i" => \$nup, - "auto-rotate"=> \$autorotate, - "1" => sub { $nup = 1 }, - "2" => sub { $nup = 2 }, - "3" => sub { $nup = 3 }, - "4" => sub { $nup = 4 }, - "5" => sub { $nup = 5 }, - "6" => sub { $nup = 6 }, - "7" => sub { $nup = 7 }, - "8" => sub { $nup = 8 }, - "9" => sub { $nup = 9 }, - "column" => \$column, - "q|quiet" => \$quiet, - "man" => \$man ) - or pod2usage(2); +my %config; + +GetOptions( "select|s=s" => sub { $config{select} = $_[1] }, + "w|width=s" => sub { $config{outwidth} = $_[1] }, + "h|height=s" => sub { $config{outheight} = $_[1] }, + "p|paper=s" => sub { my ($w,$h) = &papersize ($_[1]); + $config{outwidth} = $w; + $config{outheight} = $h; }, + "W|Width=s" => sub { $config{inwidth} = $_[1] }, + "H|Height=s" => sub { $config{inheight} = $_[1] }, + "P|Paper=s" => sub { my ($w,$h) = &papersize ($_[1]); + $config{inwidth} = $w; + $config{inheight} = $h; }, + "margin|m=s" => sub { $config{margin} = $_[1] }, + "border|b=s" => sub { $config{border} = $_[1] }, + "crop|c" => sub { $config{crop} = 1 }, + "book" => sub { $config{book} = 1 }, + "ps" => sub { $config{psout} = 1 }, + "nup|n=i" => sub { $config{nup} = $_[1] }, + "auto-rotate"=> sub { $config{autorotate} = 1 }, + "1" => sub { $config{nup} = 1 }, + "2" => sub { $config{nup} = 2 }, + "3" => sub { $config{nup} = 3 }, + "4" => sub { $config{nup} = 4 }, + "5" => sub { $config{nup} = 5 }, + "6" => sub { $config{nup} = 6 }, + "7" => sub { $config{nup} = 7 }, + "8" => sub { $config{nup} = 8 }, + "9" => sub { $config{nup} = 9 }, + "column" => sub { $config{column} = 1 }, + "q|quiet" => sub { $config{quiet} = 1}, + "man" => sub { pod2usage(-exitstatus => 0, -verbose => 2) } +) or pod2usage(2); pod2usage(2) if ($#ARGV > 1); -pod2usage(-exitstatus => 0, -verbose => 2) if defined $man; # Input and output files my ($infile, $outfile) = @ARGV; +$config{infile} = $infile; +$config{outfile} = $outfile; @@ -305,36 +300,42 @@ my ($infile, $outfile) = @ARGV; # Default values # +$config{nup} = 1 unless exists $config{nup}; + # Default margin & border -$margin = 0 unless defined $margin; -unless (defined $border) { - if (defined $crop) { - $border = '1cm'; +$config{margin} = 0 unless exists $config{margin}; +unless (exists $config{border}) { + if (exists $config{crop}) { + $config{border} = '1cm'; } else { - $border = 0; + $config{border} = 0; } } # Default output papersize -&papersize ("a4", \$outwidth, \$outheight) - unless (defined $outwidth and defined $outheight); +unless (exists $config{outwidth} and exists $config{outheight}) { + my ($w,$h) = &papersize ("a4"); + $config{outwidth} = $w; + $config{outheight} = $h; +} # Default unit: PostScript point -map {&topoints ($_)} ( \$outwidth, \$outheight, - \$inwidth, \$inheight, - \$margin, \$border ); -die "Margins are too big.\n" if $outwidth <= $margin*2 or $outheight <= $margin*2; +map { $config{$_} = &topoints($config{$_}) if exists $config{$_} } + qw /outwidth outheight inwidth inheight margin border/; +die "Error: Margins are too big.\n" + if $config{outwidth} <= 2*$config{margin} + or $config{outheight} <= $config{margin}; # # Check options # -die "Bad page range: `" .$select. "'.\n" if - defined $select && not $select =~ /^(_?\d*-?_?\d*,)*_?\d*-?_?\d*$/; +die "Error: Bad page range: `" .$config{select}. "'.\n" if + defined $config{select} && not $config{select} =~ /^(_?\d*-?_?\d*,)*_?\d*-?_?\d*$/; -die "Bad nup: `" .$nup. "'.\n" if - defined $nup && not ($nup =~ /^\d+$/ && $nup > 0); +die "Error: Bad nup: `" .$config{nup}. "'.\n" if + defined $config{nup} && not ($config{nup} =~ /^\d+$/ && $config{nup} > 0); @@ -342,16 +343,18 @@ die "Bad nup: `" .$nup. "'.\n" if # Open input and output files # my ($FIN, $FOUT); -if (defined $infile && $infile ne "-") { - open $FIN, '<', $infile or die "Cannot read `" .$infile. "': $!\n"; +if (defined $config{infile} && $config{infile} ne "-") { + open $FIN, '<', $config{infile} + or die "Error: Cannot read `" .$config{infile}. "': $!\n"; } else { - undef $infile; + delete $config{infile}; $FIN = *STDIN; } -if (defined $outfile && $outfile ne "-") { - open $FOUT, '>', "$outfile" or die "Cannot create `" .$outfile. "': $!\n"; +if (defined $config{outfile} && $config{outfile} ne "-") { + open $FOUT, '>', $config{outfile} + or die "Error: Cannot create `" .$config{outfile}. "': $!\n"; } else { $FOUT = *STDOUT; } @@ -370,17 +373,17 @@ my @pids; my $return = 0; try { - my $FD = &pdftops($FIN); + my $FD = &pdftops($FIN, \%config); - $FD = &psselect($FD) if defined $select; + $FD = &psselect($FD, \%config) if exists $config{select}; - my ($FD2, @bbox) = &psbbox($FD); + my ($FD2, $bbox) = &psbbox($FD, \%config); - $FD2 = &psbook($FD2) if defined $book; + $FD2 = &psbook($FD2, \%config) if exists $config{book}; - my ($FD3, $landscape, $rotate) = &psnup ($FD2, @bbox); + my ($FD3, $landscape, $rotate) = &psnup ($FD2, $bbox, \%config); - &pswrite ($FD3, $FOUT, $landscape, $rotate); + &pswrite ($FD3, $FOUT, $landscape, $rotate, \%config); } catch Error with { @@ -429,7 +432,7 @@ close OUT; # sub pdftops { - my $IN = $_[0]; + my ($IN, $config) = @_; my $OUT; # @@ -467,7 +470,7 @@ sub pdftops { close $WRITE or die "Cannot close: $!"; - return $READ if $filetype eq "PS"; + return $READ if $filetype eq "PS"; # @@ -493,11 +496,11 @@ sub pdftops { my ($first, $last); # pdftops doesn't provide any way to have page numbers relative to # the end of the document, hence there is no detection of the - # smallest interval if $select contains `_' - if (defined $select && not $select =~ /_/) { + # smallest interval if $config->{select} contains `_' + if (defined $config->{select} && not $config->{select} =~ /_/) { # Convert to PS only the pages we are interested in ($first, $last) = (1<<16,-(1<<16)); - for (split /,/, $select) { + for (split /,/, $config->{select}) { $_ =~ /^(\d*)(-?)(\d*)$/; my ($rmin,$sep,$rmax) = ($1,$2,$3); undef $first if $sep && not $rmin; @@ -514,7 +517,7 @@ sub pdftops { # Calculate the new page range my @newselect; - for (split /,/, $select) { + for (split /,/, $config->{select}) { $_ =~ /^(\d*)(-?)(\d*)$/; my ($rmin,$sep,$rmax) = ($1,$2,$3); if (defined $first) { @@ -524,7 +527,7 @@ sub pdftops { push @newselect, "$rmin$sep$rmax"; } - $select = join ',', @newselect; + $config->{select} = join ',', @newselect; } # Convert to PS @@ -532,7 +535,7 @@ sub pdftops { my @cmd = ('pdftops', '-origpagesizes', $infile, '-'); push @cmd, '-f', $first if defined $first; push @cmd, '-l', $last if defined $last; - push @cmd, '-q' if defined $quiet; + push @cmd, '-q' if exists $config->{quiet}; my $pid = open $OUT, '-|', @cmd; push @pids, [$pid, @cmd]; @@ -546,11 +549,11 @@ sub pdftops { # Select some pages in the document # sub psselect { - my $IN = $_[0]; + my ($IN, $config) = @_; my $OUT; - my @cmd = ('psselect', '-p'. $select); - push @cmd, '-q' if defined $quiet; + my @cmd = ('psselect', '-p'. $config->{select}); + push @cmd, '-q' if exists $config->{quiet}; *IN = $IN; my $pid = open3 '<&IN', $OUT, '>&LOG', @cmd; @@ -565,10 +568,10 @@ sub psselect { # Detect / calculate the bounding box # sub psbbox { - my $IN = $_[0]; + my ($IN, $config) = @_; my ($OUT, @bbox); - if (defined $crop) { + if (exists $config->{crop}) { # Calculate the maximal bounding box unless (seek $IN, 0, 1) { @@ -605,7 +608,7 @@ sub psbbox { $y0 = $2 if $2 < $y0; $x1 = $3 if $3 > $x1; $y1 = $4 if $4 > $y1; - unless (defined $quiet) { + unless (exists $config->{quiet}) { my $s = "[" . ++$p . "] "; $c += length $s; if ($c >= 80) { @@ -617,7 +620,7 @@ sub psbbox { } } close OUT or die "Cannot close: $!"; - print LOG "\n" or die "Cannot print: $!" unless defined $quiet; + print LOG "\n" or die "Cannot print: $!" unless exists $config->{quiet}; # No zombie processes waitpid $pid, 0; @@ -630,12 +633,12 @@ sub psbbox { # Let's go back to the beginning of the input seek $IN, 0, 0 or die "Cannot seek: $!"; $OUT = $IN; - - } elsif (defined $inwidth and defined $inheight) { - @bbox = (0, 0, $inwidth, $inheight); + } + elsif (exists $config->{inwidth} and exists $config->{inheight}) { + @bbox = (0, 0, $config->{inwidth}, $config->{inheight}); $OUT = $IN; - - } else { + } + else { # Guess page size from the input file # To avoid to seek into IN, it gonna be copied from WRITE to READ @@ -643,6 +646,7 @@ sub psbbox { my ($READ, $WRITE); pipe $READ, $WRITE or die "Cannot pipe: $!"; + # TODO: consider PageBoundingBox (and take the biggest) while (not (@bbox) && defined (my $l = <$IN>)) { print $WRITE ($l) or die "Cannot print: $!"; @bbox = ($1, $2, $3, $4) @@ -668,7 +672,7 @@ sub psbbox { $OUT = $READ; } - return ($OUT, @bbox); + return ($OUT, \@bbox); } @@ -677,11 +681,11 @@ sub psbbox { # PSBook # sub psbook { - my $IN = $_[0]; + my ($IN, $config) = @_; my $OUT; my @cmd = ('psbook'); - push @cmd, '-q' if defined $quiet; + push @cmd, '-q' if exists $config->{quiet}; *IN = $IN; my $pid = open3 '<&IN', $OUT, '>&LOG', @cmd; @@ -696,17 +700,20 @@ sub psbook { # PSNup (inlined here, to keep track of the possible rotation) # sub psnup { - my ($IN, @bbox) = @_; + my ($IN, $bbox, $config) = @_; my ($OUT, $landscape, $rotate); - if ((($bbox[2]-$bbox[0] > $bbox[3]-$bbox[1]) - and not ($outwidth-2*$margin > $outheight-2*$margin)) + if ((($bbox->[2]-$bbox->[0] > $bbox->[3]-$bbox->[1]) + and not ($config->{outwidth}-2*$config->{margin} > + $config->{outheight}-2*$config->{margin})) or - (not (defined $autorotate) - and not ($bbox[2]-$bbox[0] > $bbox[3]-$bbox[1]) - and ($outwidth-2*$margin > $outheight-2*$margin))) { - ($outheight, $outwidth) = ($outwidth, $outheight); + (not (exists $config->{autorotate}) + and not ($bbox->[2]-$bbox->[0] > $bbox->[3]-$bbox->[1]) + and ($config->{outwidth}-2*$config->{margin} > + $config->{outheight}-2*$config->{margin}))) { + ($config->{outheight}, $config->{outwidth}) = + ($config->{outwidth}, $config->{outheight}); $landscape = 1; } @@ -716,16 +723,17 @@ sub psnup { # combinations of width*height in both normal and rotated form, and # minimise the wasted space. # - my ($ow,$oh) = ($outwidth-2*$margin, $outheight-2*$margin); + my ($ow,$oh) = ($config->{outwidth}-2*$config->{margin}, + $config->{outheight}-2*$config->{margin}); - my ($iw, $ih) = ($bbox[2]-$bbox[0], $bbox[3]-$bbox[1]); + my ($iw, $ih) = ($bbox->[2]-$bbox->[0], $bbox->[3]-$bbox->[1]); my ($horiz, $vert, $scale, $hshift, $vshift); my $tolerance = 100000; # layout tolerance my $best = $tolerance; - for (my $hor = 1; $hor; $hor = &nextdiv($hor, $nup)) { - my $ver = $nup / $hor; + for (my $hor = 1; $hor; $hor = &nextdiv($hor, $config->{nup})) { + my $ver = $config->{nup} / $hor; # try normal orientation first my $scl = &min ($oh/($ih*$ver), $ow/($iw*$hor)); @@ -734,10 +742,10 @@ sub psnup { if ($optim < $best) { $best = $optim; # recalculate scale to allow for internal borders - $scale = &min (($oh-2*$border*$ver)/($ih*$ver), - ($ow-2*$border*$hor)/($iw*$hor)); - $hshift = ($ow/$hor - ($bbox[2]+$bbox[0])*$scale)/2; - $vshift = ($oh/$ver - ($bbox[3]+$bbox[1])*$scale)/2; + $scale = &min (($oh-2*$config->{border}*$ver)/($ih*$ver), + ($ow-2*$config->{border}*$hor)/($iw*$hor)); + $hshift = ($ow/$hor - ($bbox->[2]+$bbox->[0])*$scale)/2; + $vshift = ($oh/$ver - ($bbox->[3]+$bbox->[1])*$scale)/2; ($horiz, $vert) = ($hor, $ver); $rotate = 0; } @@ -748,17 +756,18 @@ sub psnup { if ($optim < $best) { $best = $optim; # recalculate scale to allow for internal borders - $scale = &min (($oh-2*$border*$hor)/($iw*$hor), - ($ow-2*$border*$ver)/($ih*$ver)); - $hshift = ($ow/$ver - ($bbox[3]+$bbox[1])*$scale)/2; - $vshift = ($oh/$hor - ($bbox[2]+$bbox[0])*$scale)/2; + $scale = &min (($oh-2*$config->{border}*$hor)/($iw*$hor), + ($ow-2*$config->{border}*$ver)/($ih*$ver)); + $hshift = ($ow/$ver - ($bbox->[3]+$bbox->[1])*$scale)/2; + $vshift = ($oh/$hor - ($bbox->[2]+$bbox->[0])*$scale)/2; ($horiz, $vert) = ($ver, $hor); $rotate = 3; } } # Fail if nothing better than worst tolerance was found - die "Cannot find acceptable layout for $nup-up.\n" if $best == $tolerance; + die "Error: Cannot find acceptable layout for $config->{nup}-up.\n" + if $best == $tolerance; # @@ -774,7 +783,7 @@ sub psnup { if ($rotate) { - if (defined $column) { + if (exists $config->{column}) { # column=0; leftright=1; topbottom=0; $across = $pageno % $horiz; $up = floor ($pageno / $horiz); @@ -786,7 +795,7 @@ sub psnup { ($orot,$erot) = ('L','R'); $xoff = ($across+1)*$ow/$horiz - $hshift; } else { - if (defined $column) { + if (exists $config->{column}) { # column=1; leftright=1; topbottom=1; $across = floor($pageno / $vert); $up = $vert-1 - floor($pageno % $vert); @@ -801,24 +810,26 @@ sub psnup { push @ospecs, sprintf ("%d%s@%.3f(%.3f,%.3f)", $pageno, $orot, $scale, - $xoff+$margin, $yoff+$margin); + $xoff+$config->{margin}, + $yoff+$config->{margin}); push @especs, sprintf ("%d%s@%.3f(%.3f,%.3f)", $n + $pageno, $erot, $scale, - $ow-$xoff+$margin, $oh-$yoff+$margin); + $ow-$xoff+$config->{margin}, + $oh-$yoff+$config->{margin}); } ($ow,$oh) = ($oh,$ow) if $rotate%2; my $pagespecs; - if (not (defined $autorotate) || $ow < $oh) { - $pagespecs = $nup . ':' . join ('+', @ospecs); + if (not (exists $config->{autorotate}) || $ow < $oh) { + $pagespecs = $config->{nup} . ':' . join ('+', @ospecs); } else { - $pagespecs = 2*$nup . ':' . join ('+', @ospecs) - . ',' . join ('+', @especs); + $pagespecs = 2*$config->{nup} . ':' . join ('+', @ospecs) + . ',' . join ('+', @especs); } - my @cmd = ('pstops', '-w'. $bbox[2], '-h'. $bbox[3], $pagespecs); - push @cmd, '-q' if defined $quiet; + my @cmd = ('pstops', '-w'. $bbox->[2], '-h'. $bbox->[3], $pagespecs); + push @cmd, '-q' if exists $config->{quiet}; *IN = $IN; my $pid = open3 '<&IN', $OUT, '>&LOG', @cmd; @@ -834,21 +845,21 @@ sub psnup { # PDF if necessary # sub pswrite { - my ($IN, $OUT, $landscape, $rotate) = @_; + my ($IN, $OUT, $landscape, $rotate, $config) = @_; - my ($ow,$oh) = ($outwidth,$outheight); + my ($ow, $oh) = ($config->{outwidth}, $config->{outheight}); ($ow,$oh) = ($oh,$ow) if $rotate%2; my $pagedevice; - if (not (defined $autorotate) || $oh < $oh || $landscape) { - $rotate = ($rotate+1)%4 if (defined $autorotate) and $oh < $ow; - $pagedevice = "/Orientation $rotate /PageSize [$outwidth $outheight]"; + if (not (exists $config->{autorotate}) || $oh < $oh || $landscape) { + $rotate = ($rotate+1)%4 if (exists $config->{autorotate}) and $oh < $ow; + $pagedevice = "/Orientation $rotate /PageSize [$config->{outwidth} $config->{outheight}]"; } else { - $pagedevice = "/PageSize [$outwidth $outheight]"; + $pagedevice = "/PageSize [$config->{outwidth} $config->{outheight}]"; } my $device = '-sDEVICE=pdfwrite'; - $device = '-sDEVICE=ps2write' if defined $psout; + $device = '-sDEVICE=ps2write' if exists $config->{psout}; my @cmd = (@gs, '-dQUIET', '-dBATCH', '-dNOPAUSE', $device, '-dAutoRotatePages=/None', '-dDetectDuplicateImages=false', @@ -874,9 +885,9 @@ sub pswrite { # sub topoints { my $l = $_[0]; - return unless defined $$l; + return unless defined $l; - $$l =~ /^([+-]?\d*\.?\d+)(\w*)$/ or die "Unable to parse `" .$$l. "'.\n"; + $l =~ /^([+-]?\d*\.?\d+)(\w*)$/ or die "Unable to parse `" .$l. "'.\n"; my $r = $1; if ($2 eq "" or $2 eq "pt") { @@ -890,7 +901,7 @@ sub topoints { } else { die "Unknown unit: `$2'.\n"; } - $$l = floor ($r + .5); + return floor ($r + .5); } @@ -899,43 +910,42 @@ sub topoints { # In-place set the given width and height to the predefined papersize # sub papersize { - my ($p,$w,$h) = @_; - $p = lc $p; + my $p = lc $_[0]; if ($p eq "a0") { - ($$w,$$h) = (2384, 3370); # 84.1cm * 118.9cm + return (2384, 3370); # 84.1cm * 118.9cm } elsif ($p eq "a1") { - ($$w,$$h) = (1684, 2384); # 59.4cm * 84.1cm + return (1684, 2384); # 59.4cm * 84.1cm } elsif ($p eq "a2") { - ($$w,$$h) = (1191, 1684); # 42cm * 59.4cm + return (1191, 1684); # 42cm * 59.4cm } elsif ($p eq "a3") { - ($$w,$$h) = (842, 1191); # 29.7cm * 42cm + return (842, 1191); # 29.7cm * 42cm } elsif ($p eq "a4") { - ($$w,$$h) = (595, 842); # 21cm * 29.7cm + return (595, 842); # 21cm * 29.7cm } elsif ($p eq "a5") { - ($$w,$$h) = (421, 595); # 14.85cm * 21cm + return (421, 595); # 14.85cm * 21cm } elsif ($p eq "b5") { - ($$w,$$h) = (516, 729); # 18.2cm * 25.72cm + return (516, 729); # 18.2cm * 25.72cm } elsif ($p eq "letter") { - ($$w,$$h) = (612, 792); # 8.5in * 11in + return (612, 792); # 8.5in * 11in } elsif ($p eq "legal") { - ($$w,$$h) = (612, 1008); # 8.5in * 14in + return (612, 1008); # 8.5in * 14in } elsif ($p eq "ledger") { - ($$w,$$h) = (1224, 792); # 17in * 11in + return (1224, 792); # 17in * 11in } elsif ($p eq "tabloid") { - ($$w,$$h) = (792, 1224); # 11in * 17in + return (792, 1224); # 11in * 17in } elsif ($p eq "statement") { - ($$w,$$h) = (396, 612); # 5.5in * 8.5in + return (396, 612); # 5.5in * 8.5in } elsif ($p eq "executive") { - ($$w,$$h) = (540, 720); # 7.6in * 10in + return (540, 720); # 7.6in * 10in } elsif ($p eq "folio") { - ($$w,$$h) = (612, 936); # 8.5in * 13in + return (612, 936); # 8.5in * 13in } elsif ($p eq "quarto") { - ($$w,$$h) = (610, 780); # 8.5in * 10.83in + return (610, 780); # 8.5in * 10.83in } elsif ($p eq "10x14") { - ($$w,$$h) = ("10in", "14in"); + return ("10in", "14in"); } else { - die "Unknown paper size: `" .$p. "'.\n"; + die "Error: Unknown paper size: `" .$p. "'.\n"; } } -- cgit v1.2.3