# -*- perl -*- # # $Id: GDHeavy.pm,v 1.6 2005/02/25 01:35:43 eserte Exp $ # Author: Slaven Rezic # # Copyright (C) 2002,2004 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; # needs BBBikeDraw::GD preloaded use strict; use vars qw($VERSION); $VERSION = sprintf("%d.%02d", q$Revision: 1.6 $ =~ /(\d+)\.(\d+)/); package BBBikeDraw::GD; use Strassen::Core; use GD; use VectorUtil qw(get_polygon_center); use vars qw(%color_to_index); # 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); } } } sub draw_custom_places { my($self, $mapping_str) = @_; my(@l) = split /;/, $mapping_str; my %mapping; for (@l) { $_ = [split /,/, $_]; $mapping{$_->[0]} = { @{$_}[1..$#$_] }; } my $im = $self->{Image}; my $transpose = $self->{Transpose}; my $p = $self->_get_orte; my $cp = Strassen->new("orte_city"); $cp->init; while(1) { my $s = $cp->next_obj; last if $s->is_empty; if ($s->name eq 'Mitte') { $p->push(["Berlin", $s->coords, $s->category]); } } my %ort_font = %{ $self->get_ort_font_mapping }; $p->init; $BBBikeDraw::GD::grey_bg = $BBBikeDraw::GD::grey_bg; # peacify -w while(1) { my $s = $p->next_obj; last if $s->is_empty; my $cat = $s->category; my($x0,$y0) = @{$s->coord_as_list(0)}; my($x, $y) = &$transpose(@{$s->coord_as_list(0)}); my $ort = $s->name; # Anhängsel löschen (z.B. "b. Berlin") $ort =~ s/\|.*$//; next if !exists $mapping{$ort}; $im->arc($x, $y, 3, 3, 0, 360, $BBBikeDraw::GD::black); $self->outline_text ($ort_font{$cat} || &GD::Font::Small, $x, $y, BBBikeDraw::GD->patch_string($ort), $BBBikeDraw::GD::black, $BBBikeDraw::GD::grey_bg, -padx => 4, -anchor => $mapping{$ort}->{-anchor}, ); } } 1; __END__