# -*- perl -*-
# MainCell.pm $Id: MainCell.pm,v 1.7 1999/03/27 15:09:08 jens Exp $
# From epsmerge =>Id: MainCell.pm,v 1.9 1999/01/30 15:42:29 jens Exp<=
# (C) Copyright Jens G Jensen <jens@math.u-strasbg.fr>
# This file is part of epssplit and is distributed under GNU GPL


package MainCell;

use strict;
use Options;
use Eps;
use Cropmarks;


# Pass filename of poster file
# This reads the eps and figures out how many output files to create
# Should formatting go to a formatter class?  Maybe if it gets more
# complicated.
sub new {
    my ($class, $filename) = @_;
    my $opt = Options->new();

    # begin width and height stuff
    my ($w, $h) = ($opt->getopts('pw') || 0, $opt->getopts('ph') || 0);
    if( $w == 0 || $h == 0 ) {
	my $paper = $opt->getopts('p');
	($w, $h) = @$paper;
    }
    $opt->setopts( pw => $w, ph => $h );
    # end width and height stuff

    my $self = { cont => Margin->new( Cropmarks->new( Eps->new( $filename ) ) ) };
    $self->{fn} = $filename;

    # get the physical size of each image
    my @physbox = $self->{cont}->getsize( 0, 0, $w, $h );
    ($w, $h) = ($self->{physx}, $self->{physy}) = ($physbox[2]-$physbox[0], $physbox[3]-$physbox[1]);

    my @epsbox = $self->{cont}->box();
    my ($ew, $eh) = ( $epsbox[2]-$epsbox[0], $epsbox[3]-$epsbox[1] );

    # scaling stuff
    no integer;
    if( $opt->getopts('x') ) {
	print STDERR "Warning: ignoring -y\n" if $opt->getopts('y');
	print STDERR "Warning: ignoring --scale\n" if $opt->getopts('sc') ne 'default';
	($w, $h) = ($h, $w) if $opt->getopts('O') eq 'L';
	my $sc = $opt->getopts('x') * $w / $ew;
	$self->{'x'} = $opt->getopts('x');
	$self->{'y'} = ceil( $sc * $eh / $h );
	$opt->setopts( sc => $sc );
    }
    elsif( $opt->getopts('y') ) {
	print STDERR "Warning: ignoring --scale\n" if $opt->getopts('sc') ne 'default';
	($w, $h) = ($h, $w) if $opt->getopts('O') eq 'L';
	my $sc = $opt->getopts('y') * $h / $eh;
	$self->{'y'} = $opt->getopts('y');
	$self->{'x'} = ceil( $sc * $ew / $w );
	$opt->setopts( sc => $sc );
    }
    else {
	if( $opt->getopts('sc') ne 'default' ) {
	    $ew *= $opt->getopts('sc');
	    $eh *= $opt->getopts('sc');
	}
	if( $opt->getopts('O') eq 'default' ) {
	    my @format = _bestformat( $w, $h, $ew, $eh );
	    $self->{'x'} = $format[0];
	    $self->{'y'} = $format[1];
	}
	elsif( $opt->getopts('O') eq 'P' ) {
	    ($self->{'x'}, $self->{'y'}) = _format( $w, $h, $ew, $eh );
	}
	elsif( $opt->getopts('O') eq 'L' ) {
	    ($self->{'x'}, $self->{'y'}) = _format( $h, $w, $ew, $eh );
	}
	else {
	    die 'Eep!  Disorientation!';
	}
    }

    # page orientation stuff
    ($self->{physx}, $self->{physy}) = ($self->{physy}, $self->{physx})
      if $opt->getopts('O') eq 'L';
    $self->{offx} = 0;
    $self->{offy} = int( $self->{'y'}*$self->{physy}-$opt->getopts('sc')*$eh);

    # bookkeeping stuff
    $self->{'page'} = 0;
    $self->{'hdr'} = 1;
    $opt->setopts( pages => $self->{'x'}*$self->{'y'}, 'format' => [ $self->{'x'}, $self->{'y'} ] );
    $self->{'curx'} = $self->{'cury'} = 0;

    bless $self, $class;
    return $self;
}

# In: (width,height) of paper, (width,height) of eps
# Out: x, y, waste
# Priority:
# (1) minimize # pages printed,
# (2) minimize blank space,
# (3) prefer portrait
sub _bestformat {
    my ($w, $h, $ew, $eh) = @_;
    my @portrait = _format($w, $h, $ew, $eh);
    my @landscape = _format($h, $w, $ew, $eh);
    my $p = $portrait[0]*$portrait[1];
    my $l = $landscape[0]*$landscape[1];
    if( $p < $l || $p == $l && $portrait[2] <= $landscape[2] ) {
	Options->new()->setopts( O => 'P' );
	return @portrait;
    }
    Options->new()->setopts( O => 'L' );
    return @landscape;
}

# In: (width,height) of paper, (width,height) of eps
# Out: x, y, waste
sub _format {
    my ($w, $h, $ew, $eh) = @_;
    my ($x, $y);
    no integer;
    $x = ceil( $ew / $w ); $y = ceil( $eh / $h );
    return ($x, $y, $x*$y*$w*$h - $ew*$eh);
}

sub is_done {
    my $self = shift;
    return $self->{page} >= Options->new()->getopts('pages');
}

sub get_xy {
  my $self = shift;
  return ($self->{curx}, $self->{cury});
}

# This write method does not need a boundingbox since it knows the paper size
# from when the MainCell was created.
sub write {
    my $self = shift;
    my $opt = Options->new();
    my @box = (0, 0, $opt->getopts('pw', 'ph'));
    my $label = sprintf '%s (%d, %d)', $self->{fn}, $self->{curx}, $self->{cury};

    if( $self->{hdr} ) {
	if( $opt->getopts('ps') ) {
	    print "%!PS-Adobe-3.0\n";
	    $self->{hdr} = 0;
	}
	else {
	    print "%!PS-Adobe-3.0 EPSF-3.0\n";
	}
	printf "%%%%BoundingBox: %d %d %d %d\n", @box;
	printf "%%%%Creator: (epssplit %s)\n", $opt->getopts('v');
	print "%%CreationDate: ", scalar localtime, "\n";
	if($ENV{USER}) {
	    if($ENV{HOSTNAME}) {
		print "%%For: $ENV{USER} at $ENV{HOSTNAME}\n";
	    }
	    else {
		print "%%For: $ENV{USER}\n";
	    }
	}
	printf "%%%%Title: (%s)\n", $opt->getopts('o');
	print "%%Orientation: ", $opt->getopts('O') eq 'L' ? "Landscape\n" : "Portrait\n";
	if( $opt->getopts('ps') ) {
	    printf "%%%%Pages: %d\n", $opt->getopts( 'pages' );
	    print "%%PageOrder: Ascend\n";
	}
# TODO: write resources, languagelevel information picked up by the cells, etc.
	print "%%EndComments\n";
    }
    ++$self->{page};
    if( $opt->getopts('ps') ) {
	printf "%%%%Page: %d %d\n", $self->{page}, $self->{page};
    }

print <<SETUP;
0 setgray 0 setlinecap 1 setlinewidth
0 setlinejoin 10 setmiterlimit
[ ] 0 setdash newpath
SETUP

# if( $self->{cont}->getresource('LanguageLevel:') >= 2 ) {
# print "false setoverprint false setstrokeadjust\n"
# }

    my $atx = -$self->{offx}+$self->{curx}*$self->{physx};
    my $aty = -$self->{offy}+($self->{'y'}-$self->{cury}-1)*$self->{physy};

    # rotate image if we print in landscape mode
    if( $opt->getopts('O') eq 'L' ) {
	printf "%d 0 translate 90 rotate\n", $opt->getopts('pw');
	$self->{cont}->write( $box[1], $box[0], $box[3], $box[2], $atx, $aty, $label );
    }
    else {
	$self->{cont}->write( @box, $atx, $aty, $label );
    }
    # unrotate image if in landscape mode (coordinate system being preserved by save/restore pair)
    if( $opt->getopts('O') eq 'L' ) {
	printf "-90 rotate %d 0 translate\n", $opt->getopts('pw');
    }
    printf "%d %d translate\n", -$box[0], -$box[1];
    print "showpage\n" if $opt->getopts('print') || $opt->getopts('ps');
    print "%%EOF\n" if ! $opt->getopts('ps') || $self->{page} == $opt->getopts('pages');

    # eps (x,y) stuff
    ++ $self->{curx};
    if( $self->{curx} == $self->{'x'} ) {
	$self->{curx} = 0;
	++ $self->{cury};
    }
}

# quick and dirty replacement for Posix::ceil
sub ceil {
    return int( $_[0] + 0.99999999 );
}


1;
