The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
=head1 NAME

Gtk2::CV::PostScript - a class for writing postscript files

=head1 SYNOPSIS

  use Gtk2::CV::PostScript;

  # nothing gets exported

=head1 DESCRIPTION

=head2 FUNCTIONS

=over 4

=cut

package Gtk2::CV::PostScript;

use common::sense;
use Carp;

my @papersize = map [
                       $_->[0],
                       $_->[1],
                       __PACKAGE__->ps2mm (@_[2,3]),
                    ],
(
   ["maximize", "Maximize", 0, 0],
   ["a0", "A0", 2384, 3370], ["a1", "A1", 1684, 2384], ["a2", "A2", 1191, 1684],
   ["a3", "A3", 842, 1191], ["a4", "A4", 595, 842], ["a5", "A5", 420, 595],
   ["a6", "A6", 297, 420], ["a7", "A7", 210, 297], ["a8", "A8", 148, 210],
   ["a9", "A9", 105, 148], ["a10", "A10", 73, 105],

   ["b0", "B0", 2835, 4008], ["b1", "B1", 2004, 2835], ["b2", "B2", 1417, 2004],
   ["b3", "B3", 1001, 1417], ["b4", "B4", 709, 1001], ["b5", "B5", 499, 709],
   ["b6", "B6", 354, 499],

   ["c0", "C0", 2599, 3677], ["c1", "C1", 1837, 2599], ["c2", "C2", 1298, 1837],
   ["c3", "C3", 918, 1298], ["c4", "C4", 649, 918], ["c5", "C5", 459, 649],
   ["c6", "C6", 323, 459],

   ["jisb0", "B0 (jis)", 2920, 4127], ["jisb1", "B1 (jis)", 2064, 2920], ["jisb2", "B2 (jis)", 1460, 2064],
   ["jisb3", "B3 (jis)", 1032, 1460], ["jisb4", "B4 (jis)", 729, 1032], ["jisb5", "B5 (jis)", 516, 729],
   ["jisb6", "B6 (jis)", 363, 516],

   ["archE", "Arch E", 2592, 3456], ["archD", "Arch D", 1728, 2592], ["archC", "Arch C", 1296, 1728],
   ["archB", "Arch B", 864, 1296], ["archA", "Arch A", 648, 864],

   ["11x17", "11x17", 792, 1224], ["ledger", "Ledger", 1224, 792], ["legal", "Legal", 612, 1008],
   ["letter", "Letter", 612, 792], ["foolscap", "Fools Cap", 612, 936], ["halfletter", "Half Letter", 396, 612],
);

=item Gtk2::CV::PostScript::papersizes

Return an array of paper sizes. Each element contains an arrayref:

  [$name, $description, $width_mm, $height_mm]

i.e.:

   ["a0", "A0", 2384, 3370]

=cut

sub papersizes {
   @papersize
}

=item new Gtk2::CV::PostScript fh => $filehandle, pixbuf => $gdk_pixbuf_object, ...

 fh => $filehandle
 pixbuf => $pixbuf
 size =>
 aspect =>
 binary =>
 interpolate =>
 margin =>

=cut

sub new {
   my $class = shift;

   my $self = bless { @_ }, $class;

   $self->{fh} or croak "required argument 'fh' mising";
   $self->{pixbuf} or croak "required argument 'pixbuf' missing";

   $self;
}

sub mm2ps {
   shift; map $_ * (72 / 25.4), @_;
}

sub ps2mm {
   shift; map $_ * (2.54 / 72), @_;
}

=item $ps->print

Write the pixbuf.

=cut

sub print {
   my ($self) = @_;

   my $fh = $self->{fh};
   my $pb = $self->{pixbuf};

   my ($iw, $ih) = ($pb->get_width, $pb->get_height);

   $a = $self->{aspect} || $iw / $ih;

   my $mb = 1024 * 1024 * $self->{interpolate};

   $mb *= 4/5 unless $self->{binary};

   if ($mb) {
      if ($iw * $ih * 3 < $mb) {
         $iw = int 0.5 + sqrt $mb / ($a * 3);
         $ih = int 0.5 + $iw * $a;
         $pb = $pb->scale_simple ($iw, $ih, "hyper");
      }
   }

   $self->print_top;

   my ($w, $h) = $self->mm2ps ($self->{size} ? @{$self->{size}}[-2,-1] : (0, 0));

   $self->print_detectpage;

   if (my ($m) = $self->mm2ps ($self->{margin})) {
      print $fh <<EOF;
/x x $m 2 div add def /w w $m sub def
/y y $m 2 div add def /h h $m sub def
EOF
   }

   if ($w && $h) {
      print $fh <<EOF;
/x x w $w sub 2 div add def /w $w def
/y y h $h sub 2 div add def /h $h def
EOF
   }

   print $fh <<EOF;
/a $a def

a 1 gt w h div 1 gt eq
   {
     x y translate

     /W w def
     /H h def
   }
   {
     x w add y translate

     /W h def
     /H w def
     90 rotate
   }
ifelse

a W H div gt
  {
    W
    W a div
  }
  {
    H a mul
    H
  }
ifelse

2 copy
exch W sub neg 2 div
exch H sub neg 2 div translate
scale
    
$iw $ih 8
[ $iw 0 0 -$ih 0 $ih ]
EOF
   if ($self->{binary}) {
      my $operator = <<EOF;
currentfile
false 3
colorimage
EOF
      my $len = $iw * $ih * 3 + length $operator;
      print $fh "%%BeginData: $len Binary Bytes\n$operator";
      dump_binary $fh, $pb;
      print $fh "\n%%EndData\n";
   } else {
      print $fh <<EOF;
currentfile /ASCII85Decode filter
false 3
colorimage
EOF
      dump_ascii85 $fh, $pb;
   }

   $self->print_bot;
}

sub print_top {
   my ($self) = @_;

   # I use %%Page: xyz without the second agrument to get a better response
   # from gv. If this is a problem, mail me at <cv@plan9.de>.

   print {$self->{fh}} <<EOF;
%!PS-Adobe-3.0
%%Pages: 1
%%Creator: Gtk2::CV::PostScript
%%DocumentData: ${\($self->{binary} ? "Binary" : "Clean7Bit")}
%%LanguageLevel: 2
%%EndComments

%%Page: img

%%BeginPageSetup
/pgsave save def
%%EndPageSetup

EOF
}

sub print_detectpage {
   print {$_[0]{fh}} <<EOF;
newpath clippath pathbbox
/y2 exch def
/x2 exch def
/y exch def
/x exch def

/w x2 x sub def
/h y2 y sub def

EOF
}

sub print_bot {
   print {$_[0]{fh}} <<EOF;

pgsave restore
showpage

%%EOF
EOF
}

=back

=head1 AUTHOR

Marc Lehmann <schmorp@schmorp.de>

=cut

1