package GDgantchart;
require Exporter;
require 'timelocal5.pl';
&timelocal_set_package('GDgantchart');
@ISA = qw(Exporter);
@EXPORT = qw(GantChart);
use GD;
#NOTE: yInc should normally be a multiple of ygrid, if not specifying low
# and high values for y.
local (%parm) = ();
local (@barcolrs);
local ($g, $v);
local ($i, $j, $k, $mapstr);
sub GantChart
{
my ($x, $y, $ix, $v, $maxxsiz, $maxysiz);
#print "
entering GDgantchart!\n";
%parm = ();
@barcolors = ();
while (@_)
{
$v = shift;
$v =~ s/^\-//;
$parm{$v} = shift;
#print "
111 parm name=$v= set to =$parm{$v}=\n";
}
goto SKIPDEBUG1;
#print "
????? *START* ????? barysiz=$parm{barysiz}=\n";
#print "
HELLO WORLD: xcnt=$#{$parm{xvals}}= ycnt=$#{$parm{tasks}}=\n";
for ($i=0;$i<$#{$parm{xvals}};$i++)
{
#print "
xxxx=${$parm{xvals}}[$i]=\n";
}
for ($i=0;$i<$#{$parm{tasks}};$i++)
{
#print "
yyyy=${$parm{tasks}}[$i]=\n";
}
SKIPDEBUG1:
local ($sfw,$sfh) = (gdSmallFont->width,gdSmallFont->height);
local ($lfw,$lfh) = (gdLargeFont->width,gdSmallFont->height);
my ($sfh2) = $sfh + 2;
my ($sfh5) = $sfh + 5;
#SET UP PARAMETER DEFAULTS.
$parm{lmgn} = 40 unless($parm{lmgn});
$parm{rmgn} = 40 unless($parm{rmgn});
$parm{bmgn} = 40 unless($parm{bmgn});
unless(defined($parm{tmgn}))
{
$parm{tmgn} = 50;
}
$parm{tmgn} += $lfh if (defined($parm{title}));
$parm{valcolor} = 'white' unless ($parm{valcolor});
$parm{axiscolor} = 'black' unless ($parm{axiscolor});
$parm{titlecolor} = $parm{axiscolor} unless ($parm{titlecolor});
$parm{valxcolor} = $parm{axiscolor} unless ($parm{valxcolor});
#$parm{barcolors} = [qw(Steelblue4 DarkGreen brown4 Yellow3 darkorchid skyblue darkorange gray khaki salmon bisque4 olivedrab)] unless(defined($parm{barcolors}));
#$parm{barcolors} = [qw(SteelBlue gray brown4 khaki DarkGreen salmon skyblue bisque3 purple yellow2 olivedrab darkorange darkcyan)] unless(defined($parm{barcolors}));
$parm{barcolors} = [qw(SteelBlue gray brown4 DarkGreen salmon skyblue bisque3 purple yellow2 olivedrab darkorange khaki)] unless(defined($parm{barcolors}));
if (defined($parm{barcolor}))
{
$parm{barcolors} = [$parm{barcolor}];
}
else
{
$parm{barcolor} = ${$parm{barcolors}}[0];
}
my ($shadowcolor) = 'black';
if (defined($parm{shadowcolor}))
{
$shadowcolor = $parm{shadowcolor};
}
else
{
if (defined($parm{bgcolor}))
{
$shadowcolor = 'gray' if ($parm{bgcolor} =~ /black/i);
}
}
$parm{headercolor} = $parm{barcolor} unless ($parm{headercolor});
$parm{gridcolor} = $parm{headercolor} unless ($parm{gridcolor});
$parm{bordercolor} = 'black' unless ($parm{bordercolor});
$parm{shadowcolor} = $shadowcolor;
#print "
ymin=$parm{ymin}; ymax=$parm{ymax}; yInc=$parm{yInc}; \n";
if ($parm{xlegendchars})
{
for $ix (0..$#{$parm{tasks}})
{
$i = substr($parm{tasks}->[$ix],0,$parm{xlegendchars});
$parm{tasks}->[$ix] = $i . '..'
unless (length($parm{tasks}->[$ix]) <= $parm{xlegendchars});
}
}
unless (defined($parm{xlegendsiz}))
{
if (defined($parm{tasks})) #IF LEGENDS WIDER THAN CHART, WIDEN CHART!
{
for $ix (0..$#{$parm{tasks}})
{
#print "??? task($ix)=${$parm{tasks}}[$ix]= len=".length(${$parm{tasks}}[$ix])."=\n";
$i = $sfw * (length(${$parm{tasks}}[$ix])+3);
#print "??? xls=$parm{xlegendsiz}= i=$i=\n";
$parm{xlegendsiz} = $i if ($parm{xlegendsiz} < $i);
}
}
}
else
{
$xlegendsiz = $parm{xlegendsiz};
}
#print "??? xlegendsiz=$parm{xlegendsiz}=\n";
unless (defined($parm{ylegendsiz}))
{
#if (defined($parm{xvals})) #IF LEGENDS WIDER THAN CHART, WIDEN CHART!
#{
# foreach $ix (@{$parm{xvals}})
# {
# $i = $sfw * (length(${$parm{xvals}}[$ix])+2);
# $parm{ylegendsiz} = $i if ($parm{ylegendsiz} < $i);
# }
#}
$parm{ylegendsiz} = $sfh5 + 5;
}
unless ($parm{barxsiz})
{
$barxsiz = 0;
foreach (@{$parm{xvals}}) #FIND WIDEST X HEADER TO COMPUTE LINE SIZE.
{
$i = $sfw * (length($_)+2);
$barxsiz = $i unless ($barxsiz > $i);
}
}
unless ($parm{xsiz})
{
$parm{barxsiz} = $barxsiz unless ($parm{barxsiz});
$maxxsiz = ($parm{barxsiz} * ($#{$parm{xvals}}+1))
+ $parm{xlegendsiz} + $parm{lmgn} + $parm{rmgn};
&fixedxsiz($parm{minxsiz})
if ($parm{minxsiz} && $maxxsiz < $parm{minxsiz});
&fixedxsiz($parm{maxxsiz})
if ($parm{maxxsiz} && $maxxsiz > $parm{maxxsiz});
$parm{maxxsiz} = $maxxsiz;
}
else #CHART'S MAXIMUM SIZE PRESET BY abUSER.
{
&fixedxsiz($parm{xsiz});
}
unless ($parm{ysiz}) #CALCULATE MAXIMUM CHART HEIGHT.
{
$parm{barysiz} = $sfh5 unless ($parm{barysiz}
&& $parm{barysiz} > $sfh5);
$maxysiz = ($parm{barysiz} * ($#{$parm{tasks}}+1)) + $parm{ylegendsiz}
+ $parm{bmgn} + $parm{tmgn};
&fixedysiz($parm{minysiz})
if ($parm{minysiz} && $maxysiz < $parm{minysiz});
&fixedysiz($parm{maxysiz})
if ($parm{maxysiz} && $maxysiz > $parm{maxysiz});
$parm{maxysiz} = $maxysiz;
}
else #CHART HEIGHT IS FIXED BY abUSER.
{
&fixedysiz($parm{ysiz});
}
unless ($parm{barpct})
{
$parm{barpct} = 25;
$parm{barpct} = 100 if ($parm{barysiz} < 10);
}
my ($chartxsizml) = $parm{barxsiz} * ($#{$parm{xvals}}+1);
$chartxsiz = $chartxsizml + $parm{xlegendsiz}; #(PIXELS)
$chartysiz = ($parm{barysiz} * ($#{$parm{tasks}}+1))
+ $parm{ylegendsiz}; #(PIXELS)
#print "
----final values: maxxsiz=$parm{maxxsiz}; maxysiz=$parm{maxysiz}; ybase=$parm{ybase}; yInc=$parm{yInc}; ygrid=$parm{ygrid}= ymax=$parm{ymax}.\n";
$g = new GD::Image($parm{maxxsiz},$parm{maxysiz});
#CONVERT COLOR NAMES TO RGB VALUES.
if (open(RGB,")
{
chomp;
($rr,$gg,$bb,$color) = split(' ');
$color = "\L$color\E";
foreach (qw(bar bg val axis grid title valx header border shadow))
{
$x = $parm{$_."color"};
${$_."colr"} = $g->colorAllocate($rr,$gg,$bb) if ($color eq "\L$x\E");
}
for($j=0;$j<=$#{$parm{barcolors}};$j++)
{
if ($color eq "\L${$parm{barcolors}}[$j]\E")
{
$i = $g->colorAllocate($rr,$gg,$bb);
$barcolrs[$j] = $i;
}
}
}
close (RGB);
my (@colorindex) = (0..$#{$parm{barcolors}});
for ($j=0;$j<$parm{shiftcolors};$j++)
{
$ix = shift(@barcolrs);
@barcolrs = (@barcolrs,$ix);
}
}
#SET UP DEFAULTS FOR ANY MISSING COLORS.
$barcolr = $g->colorAllocate(0,0,0) unless ($barcolr);
$valcolr = $g->colorAllocate(0,0,0) unless ($valcolr);
$axiscolr = $g->colorAllocate(0,0,0) unless ($axiscolr);
$gridcolr = $g->colorAllocate(0,0,0) unless ($gridcolr);
$shadowcolr = $g->colorAllocate(0,0,0) unless ($shadowcolr);
#$bgcolr = $g->colorAllocate(127,127,127) unless ($bgcolr);
if ($#barcolrs <= 0) #FILL OUT COLOR ARRAY WITH BAR-COLOR IF NOT SPECIFIED.
{
for ($j=0;$j<=$#{$parm{tasks}};$j++)
{
$barcolrs[$j] = $barcolr;
}
}
elsif ($#barcolrs < $#{$parm{tasks}}) #FILL OUT COLOR ARRAY TO MATCH Y-ARRAY.
{
for ($j=$#barcolrs+1;$j<$#{$parm{tasks}};$j++)
{
$barcolrs[$j] = $barcolrs[($j % $#barcolrs)];
}
}
if (defined($parm{bgcolor}))
{
#print "
??? bgcolor=$parm{bgcolor}= bgcolr=$bgcolr=\n";
#$g->transparent($bgcolr); #MAKE THE BACKGROUND COLOR TRANSPARENT.
$g->fill(1,1,$bgcolr);
}
for (0..($parm{border}-1))
{
$g->rectangle($_,$_,($parm{maxxsiz}-($_+1)),($parm{maxysiz}-($_+1)),$bordercolr);
}
##my $barylo = $parm{tmgn} + ($chartysiz * (($parm{ymax}-$parm{ybase}) / ($parm{ymax}-$parm{ymin})));
#SET UP IMAGE MAPPING, IF APPLICABLE.
if (defined($parm{links}) || defined($parm{mouseovers})
|| defined($parm{link}) || defined($parm{mouseover}))
{
$parm{mapname} = "BarChart.$$" unless (defined($parm{mapname}));
$mapstr = '