diff options
Diffstat (limited to 'pdftool.pl')
| -rwxr-xr-x | pdftool.pl | 88 | 
1 files changed, 47 insertions, 41 deletions
| @@ -10,7 +10,7 @@  $VERSION = "0.4, 12 May 2011";  use Getopt::Long qw(:config posix_default no_ignore_case gnu_compat -                            bundling auto_version auto_help);  +                            bundling auto_version auto_help);  use Pod::Usage;  use IPC::Open2;  use IPC::Open3; @@ -47,7 +47,7 @@ If no output file is given, or if a single hyphen-minus (B<->) is given as  file name, B<PDFTool> will send the data to the standard output.  By default, B<PDFTool> rotates the pages in order to ensure that your pdf will -be printable using your favorite duplex mode for portrait documents (tumble if +be printable using your favorite duplex mode for portrait documents (Tumble if  you prefer to turn the pages like those of a book). See the B<--screen>  option to bypass this behavior. @@ -55,15 +55,17 @@ The document will be treated as follows:  =over 4 -=item * Conversion from PDF to PostScript (if necessary), +=item * Convert from PDF to PostScript (if necessary), -=item * Selection of the page range, +=item * Select of the page range, -=item * Rearranging pages for printing books or booklets, +=item * Calculate the minimal bounding box -=item * Putting multiple pages per sheets, +=item * Rearrange pages for printing books or booklets, -=item * Conversion back from PS to PDF. +=item * Put multiple pages per sheets, + +=item * Convert back from PS to PDF.  =back @@ -140,7 +142,10 @@ demanding for the CPU. See the note for the border option (B<-b>) above.  =item B<--book> -Rearrange pages for printing books or booklets. +Rearrange pages for printing books or booklets. If your "default" duplex +mode (see B<DESCRIPTION>) is "NoTumble", you should either use lpr with +the option "Tumble" manually, or consider the B<PDFTool> option +B<--screen> instead.  =item B<-n, --nup=>I<num> @@ -185,9 +190,10 @@ Display the manual page.  =head1 EXAMPLES  The following comand can be used to remotely crop a PDF file, convert it -to A4 paper, and rearrange the pages to print a booklet:  +to A4 paper, and rearrange the pages to print a booklet: -C<< ssh remote pdftool.pl -cpA4 --book -2 -b2cm -m-1cm < in.pdf | lpr >> +C<< ssh remote pdftool.pl -cpA4 --book -2 -b2cm -m-1cm < in.pdf | \ +    lpr -o Duplex=DumplexTumble >>  =head1 REQUIREMENTS @@ -206,7 +212,7 @@ conditions.  my $tmpdir   = '/tmp';  # -# Options & arguments  +# Options & arguments  #  my $select; @@ -291,7 +297,7 @@ if (defined $infile && $infile ne "-") {      $infile_display = "(stdin)";  }  # After the pipe, it won't be detected as seekable -my $inseek = (seek FIN, 0, 1) ? 1 : undef;  +my $inseek = (seek FIN, 0, 1) ? 1 : undef;  if (defined $outfile && $outfile ne "-") { @@ -320,7 +326,7 @@ while (not (defined $filetype) && defined (my $l = <FIN>)) {          $filetype = "PS";      } elsif (defined $l && $l =~ /^%PDF/) {          $filetype = "PDF"; -    }  +    }  }  die "Cannot recognise FileType"  unless  defined $filetype; @@ -329,7 +335,7 @@ unless (my $pid = fork) {      # Child: cat FIN > WRITE in background      die "Can't fork: $!" unless defined $pid;      close READ  or  die "Can't close: $!"; -         +      while (<FIN>) {          print WRITE  or  die "Can't print: $!";      } @@ -339,7 +345,7 @@ unless (my $pid = fork) {  close WRITE  or  die "Can't close: $!";  close FIN  or  die "Can't close: $!"; -         +  open *FIN, "<&READ"  or  die "Can't dup: $!"; @@ -353,14 +359,14 @@ my @pids;  # -# Conversion from PDF to PS, if necessary  +# Conversion from PDF to PS, if necessary  #  my @cmd;  if ($filetype eq "PDF") {      unless (defined $infile && $inseek) {          # Need to copy the whole input to an auxiliary file, since          # conversion from PDF to PS requires random access to the data -         +          $infile = "$tmpdir/pdftool-stdin-$$" . lc ".$filetype";          open FINAUX, '>', "$infile" @@ -383,12 +389,12 @@ if ($filetype eq "PDF") {              undef $first if defined $rmin && not $rmin;              undef $last if defined $rmax && not $rmax;              if (defined $rmin && $rmin) { -                $first = $rmin if defined $first && $rmin < $first;  -                $last = $rmin if defined $last && $rmin > $last;  +                $first = $rmin if defined $first && $rmin < $first; +                $last = $rmin if defined $last && $rmin > $last;              }              if (defined $rmax && $rmax) { -                $first = $rmax if defined $first && $rmax < $first;  -                $last = $rmax if defined $last && $rmax > $last;  +                $first = $rmax if defined $first && $rmax < $first; +                $last = $rmax if defined $last && $rmax > $last;              }          } @@ -404,15 +410,15 @@ if ($filetype eq "PDF") {              $r .= $rmax if defined $rmax;              push @newselect, $r;          } -         +          $select = join ',', @newselect;      } -         +      # Convert to PS      @cmd = ('pdftops', '-origpagesizes', "$infile", '-'); -    push @cmd, '-f', $first if defined $first;  -    push @cmd, '-l', $last if defined $last;  +    push @cmd, '-f', $first if defined $first; +    push @cmd, '-l', $last if defined $last;      push @cmd, '-q'  if  defined $quiet;      my $pid = open *PSIN, "-|", @cmd                    or die "Can't run `" . &printcmd (@cmd) . "'"; @@ -433,7 +439,7 @@ if (defined $select) {      my $pid = open3 "<&IN", *OUT, ">&LOG", @cmd;      push @pids, [$pid, @cmd];      open *IN, "<&OUT"  or  die "Can't dup: $!"; -}  +} @@ -443,7 +449,7 @@ if (defined $select) {  my @bbox;  if (defined $crop) {      # Calculate the maximal bounding box -     +      unless (seek IN, 0, 1) {          # The input is not seekable: have to create a seekable auxiliary file @@ -462,13 +468,13 @@ if (defined $crop) {          open IN, '<', "$auxfile"  or  die "Can't read `$auxfile': $!";      } -  +      # Need to duplicate IN, since it will be closed in the parent process      open *GSIN, '<&IN';      @cmd = ('gs', '-sDEVICE=bbox', '-dBATCH', '-dNOPAUSE', '-');      my $pid = open3 "<&GSIN", ">&GSOUT", *GSOUT, @cmd; -     +      my ($p,$c) = (0,0); # Page & character counter      my ($x0, $y0, $x1, $y1) = (1<<16, 1<<16, -(1<<16), -(1<<16));      while (<GSOUT>) { @@ -490,11 +496,11 @@ if (defined $crop) {      }      close GSOUT  or  die "Can't close: $!";;      print LOG "\n"  or  die "Can't close: $!"  unless  defined $quiet; -     +      # No zombie processes      waitpid $pid, 0;      die "Can't run `" . &printcmd (@cmd) . "'"  if  $? >> 8; -     +      die "Error when calculating bounding box" if ($x0 >= $x1 || $y0 >= $y1);      @bbox = ($x0, $y0, $x1, $y1); @@ -505,7 +511,7 @@ if (defined $crop) {      @bbox = (0, 0, $inwidth, $inheight);  } else {      # Guess page size from the input file -    +      # To avoid to seek into IN, it gonna be copied from WRITE to READ      # in background, once the Bounding Box has been read      pipe *READ, *WRITE  or  die "Can't pipe: $!"; @@ -515,14 +521,14 @@ if (defined $crop) {          @bbox = ($1, $2, $3, $4)              if ($l =~ m/^\%\%BoundingBox: (\d+) (\d+) (\d+) (\d+)/);      } -    +      die "Cannot guess input page size!"  unless  @bbox;      unless (my $pid = fork) {          # Child: cat IN > WRITE in background          die "Can't fork: $!" unless defined $pid;          close READ  or  die "Can't close: $!";; -         +          while (<IN>) {              print WRITE  or  die "Can't close: $!";          } @@ -532,7 +538,7 @@ if (defined $crop) {      close WRITE  or  die "Can't close: $!";      close IN  or  die "Can't close: $!"; -         +      open *IN, "<&READ"  or  die "Can't dup: $!";  } @@ -553,7 +559,7 @@ if (defined $book) {  # -# PSNup +# PSNup (inlined here, to keep track of the possible rotation)  #  my $landscape;  if ((($bbox[2]-$bbox[0] > $bbox[3]-$bbox[1]) @@ -646,7 +652,7 @@ sub calc_layout {      my ($inwidth, $inheight) = ($bbox[2]-$bbox[0], $bbox[3]-$bbox[1]);      my ($horiz, $vert, $rotate, $scale, $hshift, $vshift); -     +      my $tolerance = 100000; # layout tolerance      my $best = $tolerance; @@ -654,7 +660,7 @@ sub calc_layout {          my $ver = $nup / $hor;          # try normal orientation first          my $scl = &min ($outheight/($inheight*$ver), $outwidth/($inwidth*$hor)); -     +          my $optim = ($outwidth-$scl*$inwidth*$hor)*($outwidth-$scl*$inwidth*$hor)                    + ($outheight-$scl*$inheight*$ver)*($outheight-$scl*$inheight*$ver);          if ($optim < $best) { @@ -682,7 +688,7 @@ sub calc_layout {             $rotate = 3;          }      } -     +      # fail if nothing better than worst tolerance was found      die "Can't find acceptable layout for $nup-up" if $best == $tolerance; @@ -750,7 +756,7 @@ sub calc_specs {  sub topoints {      my $l = $_[0];      return unless defined $$l; -  +      $$l =~ /^([+-]?\d*\.?\d+)(\w*)$/  or  die "Unable to parse `$$l'";      my $r = $1; @@ -829,7 +835,7 @@ sub printcmd {          push @cmd, $s;      } -    join ' ', @cmd;  +    join ' ', @cmd;  } | 
