/usr/local/CPAN/svg-svg2zinc/SVGExtension.pm


package SVGExtension;

#       Zinc methods, usefull at display time of Zinc code generated for SVG file
# 
#	Copyright 2003
#	Centre d'Études de la Navigation Aérienne
#
#	Author: Christophe Mertz <mertz@cena.fr>
#
# $Id: SVGExtension.pm,v 1.6 2003/10/06 15:28:15 mertz Exp $
#############################################################################

use strict;
use Carp;


use vars qw( $VERSION );

($VERSION) = sprintf("%d.%02d", q$Revision: 1.6 $ =~ /(\d+)\.(\d+)/);

# To implement SVG viewport.
# This method must be called when dispalying zinc objects, because the bbox of
# Zinc objects must be known.
## BUG: Zinc method bbox return an oversized bbox (Zinc 3.2.6h).
## So this method cannot currently be fully exact.
sub Tk::Zinc::adaptViewport {
    my ($zinc, $name, $width,$height, $viewbox, $aspectRatio) = @_;
    my($x0,$y0,$x1,$y1)=$zinc->bbox($name); 
    ($x0,$y0,$x1,$y1)=($x0+2,$y0+2,$x1-2,$y1-2); # 2 is a delta induced by zinc!
    my $dx=$x1-$x0;
    my $dy=$y1-$y0;
#    print "In adaptViewport: $name w=$width h=$height dx=$dx dy=$dy x0=$x0,y0=$y0,x1=$x1,y1=$y1\n";
    if (!$aspectRatio) {
	## simple scale should be enough!
	my ($scaleX,$scaleY) = ($width/$dx, $height/$dy);
	$zinc->scale($name, $scaleX,$scaleY);
    } else {	
	my ($minx,$miny,$portWidth,$portHeight) = split /[\s,]+/ , $viewbox;
	my ($xalign,$yalign,$meet) = $aspectRatio =~ /x(.*)Y(.*)\s+(.*)/ ;
	print "In adaptViewport: $name viewbox=$viewbox xalign=$xalign yalign=$yalign meet=$meet\n";
	if ($meet eq 'meet') {
	    ## il faut réduire la taille
	    my $scale = 1;
	    my ($scaleX,$scaleY) = ($width/$dx, $height/$dy);
	    if ($scaleX < $scaleY) {
		if ($scaleX < 1) {
		    $scale = $scaleX;
		}
	    } elsif ($scaleY < 1) {
		$scale = $scaleY;
	    }
	    print "In adaptViewport: meet scale=$scale\n";
	    $zinc->scale($name, $scale,$scale);
	    
	    my ($shiftX,$shiftY)=(0,0);
	    if ($xalign eq 'Min') {
	    } elsif ($xalign eq 'Max') {
		$shiftX = $width - $dx*$scale;
	    } elsif ($xalign eq 'Mid') {
		$shiftX = ($width - $dx*$scale)/2;
	    } else {
		print "ERROR bad aspectratio value (for X): $aspectRatio\n";
	    }
	    
	    if ($yalign eq 'Min') {
	    } elsif ($yalign eq 'Max') {
		$shiftY = $height - $dy*$scale;
	    } elsif ($yalign eq 'Mid') {
		$shiftY = ($height - $dy*$scale)/2;
	    } else {
		print "ERROR: bad aspectratio value (for Y): $aspectRatio \n";
	    }
	    $zinc->translate($name, $shiftX,$shiftY);
	} elsif ($meet eq 'slice') {
	    ## il faut clipper
	    my $scale = 1;
	    if ($dx < $width)  {
		$scale = $width/$dx;
	    }
	    if ($dy < $height) {
		my $scaleY = $height/$dy;
		if ($scaleY > $scale) {$scale=$scaleY};
	    }
	    print "In adaptViewport: slice scale=$scale\n";
	    $zinc->scale($name, $scale,$scale);
		my ($shiftX,$shiftY)=(0,0);
	    
	    if ($xalign eq 'Min') {
	    } elsif ($xalign eq 'Max') {
		$shiftX = $width - $dx*$scale;
	    } elsif ($xalign eq 'Mid') {
		$shiftX = ($width - $dx*$scale)/2;
	    } else {
		print "ERROR bad aspectratio value (for X): $aspectRatio\n";
	    }
	    
	    if ($yalign eq 'Min') {
	    } elsif ($yalign eq 'Max') {
		$shiftY = $height - $dy*$scale;
	    } elsif ($yalign eq 'Mid') {
		$shiftY = ($height - $dy*$scale)/2;
	    } else {
		print "ERROR: bad aspectratio value (for Y): $aspectRatio \n";
	    }
	    $zinc->translate($name, $shiftX,$shiftY);
	    
	    my $g=$zinc->group($name);
	    my ($tag)= $zinc->gettags($name); # there should only be one!
	    $zinc->add('group', $g, -tags => [ "sub$tag" ]);
	    $zinc->chggroup($name, "sub$tag");
	    print "clipping with [0,0, $width,$height]\n";
	    $zinc->add('rectangle', "sub$tag", [0,0, $width+1,$height+1],
		       -tags => ["clipper_sub$tag"]);
	    $zinc->itemconfigure("sub$tag", -clip => "clipper_sub$tag"); 
	}
	print "\n";
    }
}


###################################################################


1;