#!/usr/bin/perl

# Peter Nermander <m8130@abc.se>, May 2004

# Script to help do the calculations when doing impositions
# using pstops.

# Impositions are defined by external files, see
# template.imp for template and some of the other
# *.imp files for examples.

while($_=$ARGV[0],/^-/) {
    shift;

    /^-help/ && do {print <<EOHELP; exit;};
Usage: 
impose {-A3|-A4|[-w <width> h <height>} [-c <creep>] imposition input_file

The sheet size must be specified since there is no way for the script to know.
It can be specified with a paper name switch (see below) or width and height 
in postscript points.

<creep> is the creep increment in postscript points. The value is for one
layer of paper.

Available paper sizes are:
-A4
-A3
(more to be added)
EOHELP

    /^-[Aa]4/ && do { $sw=595; $sh=842; next;};
    /^-[Aa]3/ && do { $sw=842; $sh=1191; next;};
# Need more predefined sheet sizes here

# Should maybe be changed to be the same as in mkpsfile
    /^-sh/ && do {$sh=shift; next;};
    /^-sw/ && do {$sw=shift; next;};

    /^-ph/ && do {$ph=shift; next;};
    /^-pw/ && do {$pw=shift; next;};

    /^-c/ && do {$creep=shift; next;};


    die "Unknown option $_!\n";
}

($sh & $sw) or die "Sheet size not specified\n";


$imposition = shift or die "No imposition specified\n";

# Set this before we add extention
$outfile="${imposition}_";

-f "$imposition.imp" or die "Can not find definition $imposition!\n";

$infile=shift or die "No input file specified\n";
-f $infile or die "Input files does not exist\n";

# Now set the full output filename
$outfile.=$infile;

# If page size not specified, use BBOX of input file
($pw & $ph) or do {
open INFILE, $infile;
    while(<INFILE>) {
       /(^%%BoundingBox: )(.*$)/ && do {
           ($llx,$lly,$pw,$ph) = split /\s+/, $2;
       };
    };
};

# Now let's get the array for the imposition
do "$imposition.imp";

# Cell size can be calculated now when we know matrix size
$ch=int($sh/$rows);
$cw=int($sw/$cols);


# End now for the page specifications for each sheet

for ($s=0; $s<$sheets; $s++) {

# First we do the front side
    for ($r=0; $r<$rows; $r++) {
	for ($loop=0; $loop<$cols; $loop++) {
	
	    $c=$loop; # Used thisto make mirroring easier
	    
	    # Page index is page number minus 1
	    $spec.=$sheet[$s][$r][$c]{'f_pg'}-1;

	    # Rotation is taken straight from the imposition
	    $spec.= $sheet[$s][$r][$c]{'rot'};
	    
	    # Location of the cell
	    $x=($c*$cw);
	    $y=($r*$ch);
	    
	    # Adjust location based on rotation
	    $sheet[$s][$r][$c]{'rot'} =~ /[uU]/ && do {$x+=$pw; $y+=$ph};
	    $sheet[$s][$r][$c]{'rot'} =~ /[lL]/ && do {$x+=$ph};
	    $sheet[$s][$r][$c]{'rot'} =~ /[rR]/ && do {$y+=$pw};

	    # Adjust within cell depending on orientation and adjustment
	    if ($sheet[$s][$r][$c]{'rot'} =~ /[rRlL]/) {
		$sheet[$s][$r][$c]{'adj'} =~ /[Nn]/ && do {$y+=($ch-$pw)};
		$sheet[$s][$r][$c]{'adj'} =~ /[Ee]/ && do {$x+=($cw-$ph)};
	    } else {
		$sheet[$s][$r][$c]{'adj'} =~ /[Nn]/ && do {$y+=($ch-$ph)};
		$sheet[$s][$r][$c]{'adj'} =~ /[Ee]/ && do {$x+=($cw-$pw)};

	    }

	    # Adjust for creep
	    while($_=chop $sheet[$s][$r][$c]{'creep'}) {
		/[Rr]/ && do {$x+=$creep;};
		/[Ll]/ && do {$x-=$creep;};
		/[Uu]/ && do {$y+=$creep;};
		/[Dd]/ && do {$y-=$creep;};
	    }

	    # Now we have the correct location
	    $spec .= "($x,$y)+";

	} # Next col
    } # Next row

    chop $spec; # Replace last plus with comma for other side
    $spec.=",";

# Same loop for back side
    for ($r=0; $r<$rows; $r++) {
	for ($loop=0; $loop<$cols; $loop++) {

	    # This is to mirror the sheet
	    $c=$cols-$loop-1;
	    
	    # Page index is page number minus 1
	    $spec.=$sheet[$s][$r][$c]{'r_pg'}-1;

# Rotation needs to be mirrored...
	    $sheet[$s][$r][$c]{'rot'} =~ /[uU]/ && do {$spec.="U";};
	    $sheet[$s][$r][$c]{'rot'} =~ /[rR]/ && do {$spec.="L";};
	    $sheet[$s][$r][$c]{'rot'} =~ /[lL]/ && do {$spec.="R";};

	    # Location of the cell
	    # Note, it's loop, not c
	    $x=($loop*$cw);
	    $y=($r*$ch);

# Adjustment depending on rotation is mirrored too
	    $sheet[$s][$r][$c]{'rot'} =~ /[uU]/ && do {$x+=$pw; $y+=$ph};
	    $sheet[$s][$r][$c]{'rot'} =~ /[rR]/ && do {$x+=$ph};
	    $sheet[$s][$r][$c]{'rot'} =~ /[lL]/ && do {$y+=$pw};


# Mirror East with West for adjustment within cell
	if ($sheet[$s][$r][$c]{'rot'} =~ /[rRlL]/) {
	$sheet[$s][$r][$c]{'adj'} =~ /[Nn]/ && do {$y+=($ch-$pw)};
	$sheet[$s][$r][$c]{'adj'} =~ /[Ww]/ && do {$x+=($cw-$ph)};
    } else {
	$sheet[$s][$r][$c]{'adj'} =~ /[Nn]/ && do {$y+=($ch-$ph)};
	$sheet[$s][$r][$c]{'adj'} =~ /[Ww]/ && do {$x+=($cw-$pw)};

    }


# And creep is mirrored too 
	    while($_=chop $sheet[$s][$r][$c]{'creep'}) {
		/[Rr]/ && do {$x-=$creep;};
		/[Ll]/ && do {$x+=$creep;};
		/[Uu]/ && do {$y+=$creep;};
		/[Dd]/ && do {$y-=$creep;};
	    }
	    $spec .= "($x,$y)+";
	} # Next col
    } # Next row

    chop $spec; # Change last plus to comma for next sheet
    $spec.=",";

} # Next sheet
chop $spec; # Remove last comma

# Add modulo and colon
$fullspec=(2*$sheets*$rows*$cols). ':'. $spec;

# And here we are, let roll

system("pstops -w$sw -h$sh \"$fullspec\" $infile $outfile");

# We got problem here. pstops will not set the correct BoundingBox
# even if we give it sheet size:-( We will have to replace it afterwards.

# We also use this part to add the name of the imposition to the file


rename $outfile, "bad.$outfile" or die "Can not rename $outfile\n";
open INFILE, "bad.$outfile";
open OUTFILE, ">", $outfile;
while(<INFILE>) {
    if (/%%BoundingBox:/) {
	print OUTFILE "%%BoundingBox: 0 0 $sw $sh\n";
    } elsif(/%!PS/) {
	print OUTFILE;
	print OUTFILE "%#Imposition: $imposition\n";
    } else {
	print OUTFILE;
    };
}

unlink "bad.$outfile";
