# -*- perl -*-

#
# $Id: GDHeavy.pm,v 1.4 2003/06/02 22:57:34 eserte Exp $
# Author: Slaven Rezic
#
# Copyright (C) 2002 Slaven Rezic. All rights reserved.
# This package is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.
#
# Mail: slaven@rezic.de
# WWW:  http://bbbike.sourceforge.net
#

package BBBikeDraw::GDHeavy;

use strict;
use vars qw($VERSION);
$VERSION = sprintf("%d.%02d", q$Revision: 1.4 $ =~ /(\d+)\.(\d+)/);

package BBBikeDraw::GD;
use Strassen::Core;
use GD;
use VectorUtil qw(get_polygon_center);

use vars qw(%color_to_index);

# REPO BEGIN
# REPO NAME pi /home/e/eserte/src/repository 
# REPO MD5 bb2103b1f2f6d4c047c4f6f5b3fa77cd
sub pi ()   { 4 * atan2(1, 1) } # 3.141592653
# REPO END

# recognizes:
#   [$r,$g,$b]
#   "#rrggbb" (as hex)
#   "rrr,ggg,bbb" (as decimal)
sub _get_gd_color {
    my $def = shift;
    if (ref $def eq 'ARRAY') {
	$def
    } elsif ($def =~ /^\#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/) {
	(hex($1), hex($2), hex($3));
    } elsif ($def =~ /^(\d+),(\d+),(\d+)$/) {
	($1, $2, $3);
    } else {
	die "Can't match color `$def'";
    }
}

sub _get_color_index {
    my $def = shift;
    $color_to_index{ join(",", _get_gd_color($def)) };
}

sub allocate_layer_colors {
    my($self, $bgcolor, @layers) = @_;
    my $im = $self->{Image};
    {
	my(@rgb) = _get_gd_color($bgcolor);
	$color_to_index{join(",",@rgb)} = $im->colorAllocate(@rgb);
    }
    for my $layer_def (@layers) {
	my @colors;
	push @colors, $layer_def->{Fill}    if $layer_def->{Fill};
	push @colors, $layer_def->{Outline} if $layer_def->{Outline};
	if ($layer_def->{TypeFill}) {
	    while(my($k,$v) = each %{ $layer_def->{TypeFill} }) {
		push @colors, $v;
	    }
	}
	if ($layer_def->{Dash}) {
	    push @colors, split(/;/, $layer_def->{Dash});
	}
	for my $color (@colors) {
	    next if $color eq 'transparent';
	    my(@rgb) = _get_gd_color($color);
	    my $rgb = join(",",@rgb);
	    if (!exists $color_to_index{$rgb}) {
		$color_to_index{$rgb} = $im->colorAllocate(@rgb);
	    }
	}
    }
}

sub draw_layers {
    my $self = shift;
    my @layers = @_;

    for my $layer_def (@layers) {
	my $type = $layer_def->{Type} || 'line';
	warn "Draw layer type $type...\n";
	my $meth = "draw_" . $type . "_layer";
	$self->$meth($layer_def);
    }
}

sub draw_line_layer {
    my($self, $layer_def) = @_;

    my $im        = $self->{Image};
    my $transpose = $self->{Transpose};

    my $str       = $layer_def->{Streets} || die "Streets object missing";
    my $fill      = exists $layer_def->{Fill} ? _get_color_index($layer_def->{Fill}) : undef;
    if ($layer_def->{Dash}) {
	my(@colors) = map {
	    if ($_ eq 'transparent') {
		gdTransparent;
	    } else {
		_get_color_index($_);
	    }
	} split /;/, $layer_def->{Dash};
	$im->setStyle(@colors);
	$fill = gdStyled;
    }
    if (!defined $fill) {
	die "Fill or Dash option missing";
    }
    my $width     = $layer_def->{Width} || 1;
    my $brush; # XXX GD bug: $brush has to be in this scope
    if ($width > 1) {
	$brush = GD::Image->new($width, $width);
	if ($layer_def->{Dash}) {
	    $brush->colorAllocate(0,0,0); # XXX?
	    $fill = gdStyledBrushed;
	} else {
	    $brush->colorAllocate(_get_gd_color($layer_def->{Fill}));
	    $fill = gdBrushed;
	}
	$im->setBrush($brush);
    }

    $str->init;
    while(1) {
	my $r = $str->next;
	my $coords = $r->[Strassen::COORDS];
	last if !@{ $coords };
	for(my $i = 0; $i < $#{$coords}; $i++) {
	    my($x1t, $y1t) = $transpose->(@{Strassen::to_koord1($coords->[$i])});
	    my($x2t, $y2t) = $transpose->(@{Strassen::to_koord1($coords->[$i+1])});
	    $im->line($x1t,$y1t,$x2t,$y2t, $fill);
	}
    }
}

sub draw_polygon_layer {
    my($self, $layer_def) = @_;

    my $str       = $layer_def->{Streets} || die "Streets object missing";
    my($fill, $meth);
    if ($layer_def->{Fill}) {
	$fill = _get_color_index($layer_def->{Fill});
	$meth = "filledPolygon";
    } elsif ($layer_def->{Outline}) {
	$fill = _get_color_index($layer_def->{Outline});
	$meth = "polygon";
    } else {
	die "Fill or Outline option missing";
    }

    my $im        = $self->{Image};
    my $transpose = $self->{Transpose};

    $str->init;
    while(1) {
	my $r = $str->next;
	my $coords = $r->[Strassen::COORDS];
	last if !@{ $coords };
	my $poly = GD::Polygon->new();
	for(my $i = 0; $i <= $#{$coords}; $i++) {
	    $poly->addPt($transpose->(@{Strassen::to_koord1($coords->[$i])}));
	}
	$im->$meth($poly, $fill);
    }
}

sub draw_arctext_layer {
    my($self, $layer_def) = @_;

    my $str       = $layer_def->{Streets} || die "Streets object missing";
    my %typefill;
    while(my($k,$v) = each %{ $layer_def->{TypeFill} }) {
	$typefill{$k} = _get_color_index($v);
    }

    my $im        = $self->{Image};
    my $transpose = $self->{Transpose};

    $str->init;
    while(1) {
	my $r = $str->next;
	my $coords = $r->[Strassen::COORDS];
	last if !@{ $coords };
	my(undef, $type, undef, undef, $text, $height, $angle, undef, $justify, $fonttype, $slant) = split /:/, $r->[Strassen::NAME];
	my($x, $y) = $transpose->(@{Strassen::to_koord1($coords->[0])});
	if ($type == 3 || $type == 16) { # Hauptstraßen, Bahnhöfe
	    $im->stringFT($typefill{$type}, $TTF_STREET, $height/4, -$angle/180*pi, $x, $y, $text);
	}
    }
}


1;

__END__
