GDGraph-1.44/0000755000175000001440000000000010614025002011367 5ustar benusersGDGraph-1.44/samples/0000755000175000001440000000000010614025002013033 5ustar benusersGDGraph-1.44/samples/sample15.pl0000644000175000001440000000174310347716751015051 0ustar benusersuse GD::Graph::bars; use GD::Graph::hbars; require 'save.pl'; my @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 11, 12, 15, 16, 3, 1.5, 1, 3, 4], [ 5, 12, 24, 15, 19, 8, 6, 15, 21], [ 12, 3, 1, 5, 12, 9, 16, 25, 11], ); my @names = qw/sample15 sample15-h/; for my $my_graph (GD::Graph::bars->new, GD::Graph::hbars->new) { my $name = shift @names; print STDERR "Processing $name\n"; $my_graph->set( x_label => 'X Label', y_label => 'Y label', title => 'Stacked Bars (incremental)', #y_max_value => 50, #y_tick_number => 10, #y_label_skip => 2, cumulate => 2, borderclrs => $my_graph->{dclrs}, #cycle_clrs => 2, bar_spacing => 4, #shadow_depth => 4, transparent => 0, ); $my_graph->set_legend( qw(offset increment more)); $my_graph->plot(\@data); save_chart($my_graph, $name); } GDGraph-1.44/samples/sample22.pl0000644000175000001440000000105710347716751015045 0ustar benusersuse GD::Graph::area; require 'save.pl'; @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 5, 12, 24, 33, 19, 8, 6, 15, 21], [ -1, -2, -5, -6, -3, 1.5, 1, 1.3, 2] ); my $name = 'sample22'; my $graph = GD::Graph::area->new; print STDERR "Processing $name\n"; $graph->set( two_axes => 1, zero_axis => 1, transparent => 0, ); $graph->set(rotate_chart => 1) if $name =~ /-h$/; $graph->set_legend( 'left axis', 'right axis' ); $graph->plot(\@data); save_chart($graph, $name); GDGraph-1.44/samples/sample18.pl0000644000175000001440000000601310347716751015047 0ustar benusersno strict; # TODO fix this use GD::Graph::bars; use GD::Graph::hbars; require 'save.pl'; # CONTRIB Edwin Hildebrand. # # See changes in bars.pm: Check for bar height rounding errors when # stacking bars. @dat = qw( 991006 991007 991114 991117 991118 991119 991120 991121 991122 991123 991124 991125 991126 991127 991128 991129 991130 991201 991204 991205 991206 991207 991208 ); @sub = qw(0 0 0 0 0 0 0 0 1 1 1 1 2 3 1 1 1 1 2 2 6 8 8); @def = qw(0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0); @rej = qw(0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0); @opn = qw(4 4 4 5 4 4 4 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3); @ass = qw(0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0); @wrk = qw(1 2 2 2 2 2 1 1 2 2 2 1 1 1 1 1 1 1 1 1 3 6 5); @fin = qw(0 0 0 0 0 0 1 0 0 0 0 1 1 1 2 2 2 2 2 2 2 2 2); @ver = qw(0 0 0 0 0 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1); @con = qw(0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0); @tst = qw(0 0 0 0 0 0 0 0 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1); @rev = qw(0 0 0 0 0 0 0 0 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1); @cco = qw(0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 0 0 0 0); @cls = qw(0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 1 0 0 0 0); @sld = qw(0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 3 3 3 4); # setup x data push(@data,\@dat); # push x labels into plot data push(@data,\@sub); push(@data,\@def); push(@data,\@rej); push(@data,\@opn); push(@data,\@ass); # push x values into plot data push(@data,\@wrk); # (push order must match legend label order) push(@data,\@fin); push(@data,\@ver); push(@data,\@con); push(@data,\@tst); push(@data,\@rev); push(@data,\@cco); push(@data,\@cls); push(@data,\@sld); # setup legend labels @legend = qw( Submitted Deferred Rejected Opened Assigned Work Finished Verified Configured Tested Reviewed Closed-CO Closed Sealed ); my @names = qw/sample18 sample18-h/; for my $graph (GD::Graph::bars->new(600, 400), GD::Graph::hbars->new(600, 400)) { my $name = shift @names; print STDERR "Processing $name\n"; # set graph legend $graph->set_legend(@legend); # set graph options $graph->set( 'dclrs' => [ qw(lblue lyellow blue yellow lgreen lred green red purple orange pink dyellow) ], 'title' => "States by Time", 'x_label' => "Time", 'y_label' => "# OF thingies", 'long_ticks' => 1, 'tick_length' => 0, 'x_ticks' => 0, 'x_label_position' => .5, 'y_label_position' => .5, 'cumulate' => 1, 'bgclr' => 'white', 'transparent' => 0, 'interlaced' => 1, 'y_tick_number' => 5, 'y_number_format' => '%d', #'y_max_value' => 25, #'y_min_value' => 0, 'y_plot_values' => 1, 'x_plot_values' => 1, 'zero_axis' => 1, ); $graph->set('x_labels_vertical'=> 1) unless $name =~/-h$/; $graph->plot(\@data); save_chart($graph, $name); } GDGraph-1.44/samples/sample41.pl0000644000175000001440000000144310347716751015045 0ustar benusersuse GD::Graph::linespoints; require 'save.pl'; print STDERR "Processing sample41\n"; @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [undef, 52, 53, 54, 55, 56, undef, 58, 59], [60, 61, 61, undef, 68, 66, 65, 61, undef], [70, undef, 71, undef, 78, undef, 75, 71, undef], ); $my_graph = new GD::Graph::linespoints( ); $my_graph->set( x_label => 'X Label', y_label => 'Y label', title => 'A Lines and Points Graph', y_max_value => 80, y_tick_number => 6, y_label_skip => 2, y_long_ticks => 1, x_tick_length => 2, markers => [ 1, 5 ], skip_undef => 1, transparent => 0, ) or warn $my_graph->error; $my_graph->set_legend( 'data set 1', 'data set 2', 'data set 3' ); $my_graph->plot(\@data); save_chart($my_graph, 'sample41'); GDGraph-1.44/samples/sample57.pl0000644000175000001440000000107710347716751015057 0ustar benusersuse strict; use GD::Graph::lines; require 'save.pl'; my @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 35, 32, 34, 33, 39, 38, 36, 35, 31], [ 1, 2, 5, 6, 3, 1.5, 1, 1.3, 2] ); my $name = 'sample57'; my $graph = GD::Graph::lines->new; print STDERR "Processing $name\n"; $graph->set( two_axes => 1, zero_axis => 1, title => 'Test of two_axes min/max calculation', transparent => 0, ); $graph->set_legend( 'left axis', 'right axis' ); $graph->plot(\@data); save_chart($graph, $name); GDGraph-1.44/samples/sample53.pl0000644000175000001440000000224510347716751015051 0ustar benusersuse GD::Graph::lines; use GD::Graph::colour; use GD::Graph::Data; require 'save.pl'; GD::Graph::colour::read_rgb("rgb.txt") or die "Cannot read colours from rgb.txt"; print STDERR "Processing sample53\n"; $data = ([ ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 1, 2, 5, 6, 3, 1.5, -1, -3, -4], [ -4, -3, 1, 1, -3, -1.5, -2, -1, 0], [ 9, 8, 9, 8.4, 7.1, 7.5, 8, 3, -3], [ 0.1, 0.0, -0.3, -0.4, 0.1, 0.5, 0.1, 0, 0.4], ]); $my_graph = new GD::Graph::lines(); $my_graph->set( x_label => 'X Label', y_label => 'Y label', title => 'A Multiple Line Graph', y_max_value => 10, y_min_value => -5, y_tick_number => 3, y_label_skip => 1, zero_axis_only => 0, long_ticks => 1, x_ticks => 0, dclrs => [ qw( darkorchid2 mediumvioletred deeppink darkturquoise ) ], line_types => [ 1, 2, 3, 4 ], line_type_scale => 8, legend_marker_width => 24, line_width => 3, show_values => 1, transparent => 0, ) or warn $my_graph->error; $my_graph->set_legend( 'one', 'two', undef, 'four' ); $my_graph->plot($data) or die $my_graph->error; save_chart($my_graph, 'sample53'); GDGraph-1.44/samples/sample21.pl0000644000175000001440000000127510347716751015046 0ustar benusersuse GD::Graph::area; use strict; require 'save.pl'; my @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 5, 12, 24, 33, 19,undef, 6, 15, 21], [ 1, 2, 5, 6, 3, 1.5, 1, 3, 4] ); my @names = qw/sample21/; for my $graph (GD::Graph::area->new) { my $name = shift @names; print STDERR "Processing $name\n"; $graph->set( x_label => 'X Label', y_label => 'Y label', title => 'An Area Graph', #y_max_value => 40, #y_tick_number => 8, #y_label_skip => 2, #accent_treshold => 41, transparent => 0, ); $graph->set_legend( 'one', 'two' ); $graph->plot(\@data); save_chart($graph, $name); } GDGraph-1.44/samples/sample94.pl0000644000175000001440000000125110347716751015052 0ustar benusersuse GD::Graph::pie; use strict; require 'save.pl'; # Test for very large slices that wrap around, and for text that # is larger than the pie boundaries print STDERR "Processing sample94\n"; my @data = ( ["Oversized label", "label", undef], [3, 2.5, 23] ); my $my_graph = new GD::Graph::pie( 250, 200 ); $my_graph->set( title => 'A Pie Chart', label => 'Label', axislabelclr => 'black', pie_height => 36, l_margin => 10, r_margin => 10, # approximate boundary conditions for start_angle #start_angle => -85, #start_angle => 15, transparent => 0, ); $my_graph->set_value_font(GD::Font->Giant); $my_graph->plot(\@data); save_chart($my_graph, 'sample94'); GDGraph-1.44/samples/sample55.pl0000644000175000001440000000122510347716751015050 0ustar benusersuse strict; use GD::Graph::lines; require 'save.pl'; use constant PI => 4 * atan2(1,1); print STDERR "Processing sample55\n"; my @x = map {$_ * 3 * PI/100} (0 .. 100); my @y = map sin, @x; my @z = map cos, @x; my @data = (\@x,\@y,\@z); my $my_graph = new GD::Graph::lines(); $my_graph->set( x_label => 'Angle (Radians)', y_label => 'Trig Function Value', x_tick_number => 'auto', y_tick_number => 'auto', title => 'Sine and Cosine', line_width => 1, x_label_position => 1/2, r_margin => 15, transparent => 0, ); $my_graph->set_legend('Thanks to Scott Prahl'); $my_graph->plot(\@data); save_chart($my_graph, 'sample55'); GDGraph-1.44/samples/save.pl0000644000175000001440000000044210347716751014353 0ustar benuserssub save_chart { my $chart = shift or die "Need a chart!"; my $name = shift or die "Need a name!"; local(*OUT); my $ext = $chart->export_format; open(OUT, ">$name.$ext") or die "Cannot open $name.$ext for write: $!"; binmode OUT; print OUT $chart->gd->$ext(); close OUT; } 1; GDGraph-1.44/samples/sample23.pl0000644000175000001440000000530310347716751015044 0ustar benusersuse GD::Graph::area; require 'save.pl'; # CONTRIB Edwin Hildebrand. # # See changes in bars.pm: Check for bar height rounding errors when # stacking bars. print STDERR "Processing sample23\n"; @dat = qw( 991006 991007 991114 991117 991118 991119 991120 991121 991122 991123 991124 991125 991126 991127 991128 991129 991130 991201 991204 991205 991206 991207 991208 ); @sub = qw(0 0 0 0 0 0 0 0 1 1 1 1 2 3 1 1 1 1 2 2 6 8 8); @def = qw(0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0); @rej = qw(0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0); @opn = qw(4 4 4 5 4 4 4 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3); @ass = qw(0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0); @wrk = qw(1 2 2 2 2 2 1 1 2 2 2 1 1 1 1 1 1 1 1 1 3 6 5); @fin = qw(0 0 0 0 0 0 1 0 0 0 0 1 1 1 2 2 2 2 2 2 2 2 2); @ver = qw(0 0 0 0 0 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1); @con = qw(0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0); @tst = qw(0 0 0 0 0 0 0 0 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1); @rev = qw(0 0 0 0 0 0 0 0 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1); @cco = qw(0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 0 0 0 0); @cls = qw(0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 1 0 0 0 0); @sld = qw(0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 3 3 3 4); # setup x data push(@data,\@dat); # push x labels into plot data push(@data,\@sub); push(@data,\@def); push(@data,\@rej); push(@data,\@opn); push(@data,\@ass); # push x values into plot data push(@data,\@wrk); # (push order must match legend label order) push(@data,\@fin); push(@data,\@ver); push(@data,\@con); push(@data,\@tst); push(@data,\@rev); push(@data,\@cco); push(@data,\@cls); push(@data,\@sld); # setup legend labels @legend = qw( Submitted Deferred Rejected Opened Assigned Work Finished Verified Configured Tested Reviewed Closed-CO Closed Sealed ); # get graph object $graph = GD::Graph::area->new(600, 400); # set graph legend $graph->set_legend(@legend); # set graph options $graph->set( 'dclrs' => [ qw(lblue lyellow blue yellow lgreen lred green red purple orange pink dyellow) ], 'title' => "States by Time", 'x_label' => "Time", 'y_label' => "# OF thingies", 'long_ticks' => 1, 'tick_length' => 0, 'x_ticks' => 0, 'x_label_position' => .5, 'y_label_position' => .5, 'cumulate' => 2, 'bgclr' => 'white', 'transparent' => 0, 'y_tick_number' => 5, 'y_number_format' => '%d', #'y_max_value' => 25, #'y_min_value' => 0, 'y_plot_values' => 1, 'x_plot_values' => 1, 'x_labels_vertical'=> 1, 'zero_axis' => 1, 'lg_cols' => 7, 'accent_treshold' => 100_000, ); $graph->plot(\@data); save_chart($graph, 'sample23'); GDGraph-1.44/samples/sample51.pl0000644000175000001440000000122510347716751015044 0ustar benusersuse GD::Graph::lines; require 'save.pl'; print STDERR "Processing sample51\n"; # The reverse is in here, because I thought the falling line was # depressing, but I was too lazy to retype the data set @data = ( [ qw( Jan Feb Mar Apr May Jun Jul Aug Sep ) ], [ reverse(4, 3, 5, 6, 3, 1.5, -1, -3, -4)], ); $my_graph = new GD::Graph::lines(); $my_graph->set( x_label => 'Month', y_label => 'Measure of success', title => 'A Simple Line Graph', y_max_value => 8, y_min_value => -6, y_tick_number => 14, y_label_skip => 2, box_axis => 0, line_width => 3, transparent => 0, ); $my_graph->plot(\@data); save_chart($my_graph, 'sample51'); GDGraph-1.44/samples/sample61.pl0000644000175000001440000000252310347716751015047 0ustar benusersuse GD::Graph::mixed; require 'save.pl'; print STDERR "Processing sample61 (The error message is intended)\n"; my @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 1, 2, 5, 6, 3, 1.5, -1, -3, -4], [ -4, -3, 1, 1, -3, -1.5, -2, -1, 0], [ 9, 8, 9, 8.4, 7.1, 7.5, 8, 3, -3], [ 0.1, 0.2, 0.5, 0.4, 0.3, 0.5, 0.1, 0, 0.4], [ -0.1, 2, 5, 4, -3, 2.5, 3.2, 4, -4], [ -0.1, 2, 5, 4, -3, 2.5, 3.2, 4, -4], ); my $my_graph = new GD::Graph::mixed(); $my_graph->set( types => [ qw( lines bars points area linespoints wrong_type ) ], default_type => 'points', ); $my_graph->set( x_label => 'X Label', y_label => 'Y label', title => 'A Mixed Type Graph', y_max_value => 10, y_min_value => -5, y_tick_number => 3, y_label_skip => 1, x_plot_values => 0, y_plot_values => 0, long_ticks => 1, x_ticks => 0, legend_marker_width => 24, line_width => 3, marker_size => 5, bar_spacing => 8, transparent => 0, ); $my_graph->set_legend( qw( one two three four five six ) ); $my_graph->plot(\@data) or die $my_graph->error; save_chart($my_graph, 'sample61'); GDGraph-1.44/samples/sample63.pl0000644000175000001440000000203110347716751015043 0ustar benusersuse strict; use GD::Graph::mixed; require 'save.pl'; # Also see sample17 print STDERR "Processing sample63\n"; my @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 11, 12, 15, 16, 3, 1.5, 1, 3, 4], [ 5, 12, 24, 15, 19, 8, 6, 15, 21], [ 12, 3, 1, 5, 12, 9, 16, 25, 11], [ 16, 24, 39, 31, 22, 9.5, 7, 18, 25], ); my $my_graph = new GD::Graph::mixed(); $my_graph->set( x_label => 'X Label', y_label => 'Y label', title => 'Emulation of error bars', y_min_value => 0, y_max_value => 50, y_tick_number => 10, y_label_skip => 2, cumulate => 1, types => [qw(area bars bars lines)], dclrs => [undef, qw(lgray gray red)], borderclrs => [undef, qw(black black black)], line_width => 2, bar_width => 4, transparent => 0, ) or warn $my_graph->error; $my_graph->set_legend(undef, qw(increment more)); $my_graph->plot(\@data) or die $my_graph->error; save_chart($my_graph, 'sample63'); GDGraph-1.44/samples/sample19.pl0000644000175000001440000000536210614014571015042 0ustar benusersuse strict; use GD::Graph::bars; use GD::Graph::hbars; use GD::Graph::Data; require 'save.pl'; $GD::Graph::Error::Debug = 5; my $data = GD::Graph::Data->new( [ ["2004/2/1","2004/2/2","2004/2/3","2004/2/4","2004/2/5","2004/2/6","2004/2/7", "2004/2/8", "2004/2/9"], [ 50000, 120000, 240000, 330000, 190000, 80000, 60000, 150000, 210000], [1033101,2200100,5300300,6400400,3192192,1600600, 900900,3333333,4444444], ] ) or die GD::Graph::Data->error; my $values = $data->copy(); $values->set_y(1, 7, undef) or warn $data->error; $values->set_y(2, 7, undef) or warn $data->error; my @names = qw/sample19 sample19-h/; for my $my_graph (GD::Graph::bars->new(600,400), GD::Graph::hbars->new(600,400)) { my $name = shift @names; print STDERR "Processing $name\n"; $my_graph->set( x_label => 'Date', y1_label => 'Hits', y2_label => 'Megabytes', title => 'Using two axes with different formats', #y1_max_value => 40, #y2_max_value => 8, y_tick_number => 8, y_label_skip => 2, #y_number_format => '%d', ### <-- this will override y{1,2}_number_format y1_number_format => sub { # from perlfaq5 local $_ = shift; 1 while s/^([-+]?\d+)(\d{3})/$1,$2/; $_; }, y2_number_format => sub { my $v = shift; sprintf("%.2f",$v/1024) }, long_ticks => 1, two_axes => 1, legend_placement => 'RT', x_label_position => 1/2, bgclr => 'white', fgclr => 'white', boxclr => 'dblue', accentclr => 'dblue', valuesclr => '#ffff77', dclrs => [qw(lgreen lred)], bar_spacing => 1, logo => 'logo.' . GD::Graph->export_format, logo_position => 'BR', transparent => 0, l_margin => 10, b_margin => 10, r_margin => 10, t_margin => 10, show_values => 1, values_format => "%4.1f", ) or warn $my_graph->error; if ($name =~ /-h$/) { $my_graph->set(x_labels_vertical => 0, values_vertical => 0); $my_graph->set_legend('bottom axis', 'top axis'); } else { $my_graph->set(x_labels_vertical => 1, values_vertical => 1); $my_graph->set_legend('left axis', 'right axis'); } my $font_spec = "../Dustismo_Sans"; $my_graph->set_y_label_font($font_spec, 12); $my_graph->set_x_label_font($font_spec, 12); $my_graph->set_y_axis_font($font_spec, 10); $my_graph->set_x_axis_font($font_spec, 10); $my_graph->set_title_font($font_spec, 18); $my_graph->set_legend_font($font_spec, 8); $my_graph->set_values_font($font_spec, 8); $my_graph->plot($data) or die $my_graph->error; save_chart($my_graph, $name); } GDGraph-1.44/samples/sample54.pl0000644000175000001440000000166510347716751015057 0ustar benusersuse GD::Graph::lines; require 'save.pl'; print STDERR "Processing sample54\n"; @data = read_data("sample54.dat") or die "Cannot read data from sample54.dat"; $my_graph = new GD::Graph::lines(); $my_graph->set( x_label => 'Wavelength (nm)', y_label => 'Absorbance', title => 'Numerical X axis', y_min_value => 0, y_max_value => 2, y_tick_number => 8, y_label_skip => 4, x_tick_number => 'auto', x_label_skip => 2, box_axis => 0, line_width => 2, x_label_position => 1/2, r_margin => 15, x_labels_vertical => 1, transparent => 0, ); $my_graph->set_legend('Thanks to Scott Prahl'); $my_graph->plot(\@data); save_chart($my_graph, 'sample54'); sub read_data { my $fn = shift; my @d = (); open(ZZZ, $fn) || return (); while () { chomp; my @row = split; for (my $i = 0; $i <= $#row; $i++) { undef $row[$i] if ($row[$i] eq 'undef'); unshift @{$d[$i]}, $row[$i]; } } close (ZZZ); return @d; } GDGraph-1.44/samples/sample52.pl0000644000175000001440000000151310347716751015045 0ustar benusersuse GD::Graph::lines; require 'save.pl'; print STDERR "Processing sample52\n"; @data = ( [ qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec) ], [ reverse(4, 3, 5, 6, 3, 1.5, -1, -3, -4, -6, -7, -8)], [ (4, 3, 5, 6, 3, 1.5, -1, -3, -4, -6, -7, -8)], [ (2, 2, 2, 5, 5, 4.5,1.5, 2, 3, 5, 4, 3)], ); $my_graph = new GD::Graph::lines(); $my_graph->set( x_label => 'Month', y_label => 'Measure of success', title => 'A Simple Line Graph', y_max_value => 8, y_min_value => -8, y_tick_number => 16, y_label_skip => 2, box_axis => 0, line_width => 3, zero_axis_only => 1, x_label_position => 1, y_label_position => 1, x_label_skip => 3, x_tick_offset => 2, transparent => 0, ); $my_graph->set_legend("Us", "Them", "Others"); $my_graph->plot(\@data); save_chart($my_graph, 'sample52'); GDGraph-1.44/samples/sample42.dat0000644000175000001440000000014710347716751015203 0ustar benusers1st,undef,60 2nd,52,61 3rd,53,61 4th,54,undef 5th,55,68 6th,56,66 7th,undef,65 8th,58,61 9th,59,undef GDGraph-1.44/samples/sample64.pl0000644000175000001440000000275010614014571015040 0ustar benusers#adapted from the bug report submission (RT Bug 1363) by Paul Russell use strict; use GD::Graph::mixed; require "save.pl"; ## define your data set my @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 1, 2, 5, 6, 7, 8, 9, 10, 11], [ 2, 2, 1, 1, 3, 2, 2, 4, 0], [ 9, 8, 9, 5, 7, 7, 8, 3, 3], ); print STDERR "Processing sample64\n"; my $my_graph = new GD::Graph::mixed(); $my_graph->set( types => [ qw( lines) ], default_type => 'bars', ); $my_graph->set( x_label => 'X Label', y_label => 'Y label', title => 'A Mixed Type Graph', y1_max_value => 40, y2_max_value => 8, y_min_value => 0, y_tick_number => 8, y_label_skip => 1, x_plot_values => 0, y_plot_values => 0, long_ticks => 1, x_ticks => 0, legend_marker_width => 24, line_width => 3, marker_size => 5, # bar_width => 4, # this appears to be an interesting test case--skipping for now. #bar_spacing => 1, transparent => 0, values_vertical => 1, values_format => "%4.1f", x_label_position => 1/2, cumulate => 0, overwrite => 0, ); $my_graph->set_legend( qw( incomming outgoing total ) ); $my_graph->plot(\@data) or die $my_graph->error; save_chart($my_graph, 'sample64'); GDGraph-1.44/samples/sample16.pl0000644000175000001440000000237710347716751015056 0ustar benusersuse strict; use GD::Graph::bars; use GD::Graph::hbars; require 'save.pl'; my @data = ( [ qw( 1st 2nd 3rd 4th 5th 6th 7th 8th 9th ) ], [ 5, 12,undef, 33, 19, 8, 5, 15, 21], [ -6, -5, -9, -8, -11, -9.3,undef, -9, -12] ); my $refit = 4; sub y_format { my $value = shift; my $ret; if ($value >= 0) { $ret = sprintf("\$%3d", $value * $refit); } else { $ret = sprintf("-\$%3d", abs($value) * $refit); } } my @names = qw/sample16 sample16-h/; for my $my_graph (GD::Graph::bars->new, GD::Graph::hbars->new) { my $name = shift @names; print STDERR "Processing $name\n"; $my_graph->set( x_label => 'Day', y_label => 'AUD', title => 'Credits and Debits', y_max_value => 35, y_min_value => -15, y_tick_number => 10, y_label_skip => 2, overwrite => 1, dclrs => [ qw( green lred ) ], axislabelclr => 'black', legend_placement => 'RB', zero_axis_only => 0, y_number_format => \&y_format, x_label_position => 1/2, transparent => 0, ); $my_graph->set_legend( 'credits', 'debets' ); $my_graph->plot(\@data); save_chart($my_graph, $name); } GDGraph-1.44/samples/rgb.txt0000644000175000001440000004134010347716751014375 0ustar benusers199 21 133 medium violet red 176 196 222 light steel blue 102 139 139 paleturquoise4 159 121 238 mediumpurple2 141 182 205 lightskyblue3 0 238 118 springgreen2 255 160 122 light salmon 154 205 50 yellowgreen 178 58 238 darkorchid2 69 139 116 aquamarine4 71 60 139 slateblue4 131 111 255 slateblue1 192 255 62 olivedrab1 139 105 20 goldenrod4 205 155 29 goldenrod3 142 229 238 cadetblue2 255 211 155 burlywood1 112 128 144 slategrey 255 228 225 mistyrose 50 205 50 limegreen 224 255 255 lightcyan 218 165 32 goldenrod 220 220 220 gainsboro 135 206 255 skyblue1 240 255 240 honeydew 238 238 0 yellow2 205 79 57 tomato3 135 206 235 skyblue 85 26 139 purple4 205 133 0 orange3 205 183 158 bisque3 238 213 183 bisque2 87 87 87 grey34 252 252 252 gray99 161 161 161 gray63 112 112 112 gray44 94 94 94 gray37 84 84 84 gray33 66 66 66 gray26 240 255 255 azure1 139 137 137 snow4 205 133 63 peru 219 112 147 pale violet red 139 129 76 lightgoldenrod4 60 179 113 mediumseagreen 255 240 245 lavender blush 209 95 238 mediumorchid2 176 226 255 lightskyblue1 72 61 139 darkslateblue 25 25 112 midnightblue 255 160 122 lightsalmon1 255 250 205 lemonchiffon 173 255 47 green yellow 255 160 122 lightsalmon 240 128 128 light coral 24 116 205 dodgerblue3 139 69 0 darkorange4 106 90 205 slate blue 39 64 139 royalblue4 255 69 0 orange red 50 205 50 lime green 224 255 255 light cyan 148 0 211 darkviolet 233 150 122 darksalmon 255 140 0 darkorange 95 158 160 cadet blue 255 20 147 deep pink 238 0 238 magenta2 139 71 38 sienna4 238 230 133 khaki2 191 191 191 grey75 189 189 189 grey74 186 186 186 grey73 176 176 176 grey69 173 173 173 grey68 89 89 89 grey35 33 33 33 grey13 229 229 229 gray90 207 207 207 gray81 140 140 140 gray55 130 130 130 gray51 79 79 79 gray31 238 233 233 snow2 205 145 158 pink3 18 18 18 grey7 3 3 3 gray1 139 0 0 red4 205 0 0 red3 210 180 140 tan 255 0 0 red 199 21 133 mediumvioletred 119 136 153 lightslategrey 135 206 250 lightskyblue 139 87 66 lightsalmon4 34 139 34 forestgreen 16 78 139 dodgerblue4 153 50 204 dark orchid 188 143 143 rosy brown 205 175 149 peachpuff3 124 205 124 palegreen3 238 64 0 orangered2 122 139 139 lightcyan4 139 58 58 indianred4 205 85 85 indianred3 0 0 128 navyblue 105 105 105 dim grey 255 20 147 deeppink 139 76 57 salmon4 205 112 84 salmon3 196 196 196 grey77 145 145 145 gray57 28 28 28 gray11 205 150 205 plum3 23 23 23 gray9 20 20 20 gray8 0 0 139 blue4 245 245 220 beige 250 250 210 light goldenrod yellow 139 131 134 lavenderblush4 0 206 209 dark turquoise 0 206 209 darkturquoise 47 79 79 darkslategrey 205 129 98 lightsalmon3 139 105 105 rosybrown4 255 228 225 misty rose 78 238 148 seagreen2 205 92 92 indianred 255 20 147 deeppink1 0 0 139 dark blue 230 230 250 lavender 253 245 230 oldlace 199 199 199 grey78 138 138 138 grey54 115 115 115 grey45 54 54 54 grey21 247 247 247 gray97 245 245 245 gray96 242 242 242 gray95 224 224 224 gray88 222 222 222 gray87 219 219 219 gray86 179 179 179 gray70 97 97 97 gray38 31 31 31 gray12 250 240 230 linen 72 209 204 medium turquoise 72 61 139 dark slate blue 139 137 112 lemonchiffon4 193 255 193 darkseagreen1 205 192 176 antiquewhite3 186 85 211 mediumorchid 0 255 127 springgreen 0 134 139 turquoise4 79 148 205 steelblue3 238 213 210 mistyrose2 209 238 238 lightcyan2 205 92 92 indian red 238 44 44 firebrick2 65 105 225 royalblue 95 158 160 cadetblue 108 166 205 skyblue3 205 205 0 yellow3 255 140 105 salmon1 139 90 0 orange4 255 105 180 hotpink 229 229 229 grey90 143 143 143 gray56 99 99 99 gray39 46 46 46 gray18 36 36 36 gray14 139 102 139 plum4 15 15 15 grey6 15 15 15 gray6 205 173 0 gold3 255 215 0 gold1 0 0 238 blue2 238 154 73 tan2 0 255 255 cyan 0 250 154 mediumspringgreen 188 238 104 darkolivegreen2 238 232 170 pale goldenrod 176 196 222 lightsteelblue 244 164 96 sandy brown 255 239 213 papaya whip 102 205 0 chartreuse3 139 34 82 violetred4 67 110 238 royalblue2 72 118 255 royalblue1 255 239 213 papayawhip 205 183 181 mistyrose3 224 255 255 lightcyan1 127 255 212 aquamarine 74 112 139 skyblue4 139 58 98 hotpink4 205 96 144 hotpink3 238 106 167 hotpink2 169 169 169 darkgrey 105 105 105 dimgray 255 99 71 tomato 168 168 168 grey66 166 166 166 grey65 163 163 163 grey64 84 84 84 grey33 69 69 69 grey27 194 194 194 gray76 176 176 176 gray69 173 173 173 gray68 0 0 0 grey0 240 255 255 azure 0 250 154 medium spring green 139 101 8 darkgoldenrod4 205 149 12 darkgoldenrod3 238 173 14 darkgoldenrod2 184 134 11 darkgoldenrod 139 69 19 saddle brown 238 149 114 lightsalmon2 0 104 139 deepskyblue4 0 154 205 deepskyblue3 0 178 238 deepskyblue2 0 191 255 deepskyblue 255 127 0 darkorange1 205 50 120 violetred3 238 58 140 violetred2 255 62 150 violetred1 105 89 205 slateblue3 122 103 238 slateblue2 107 142 35 olive drab 255 106 106 indianred1 255 48 48 firebrick1 83 134 139 cadetblue4 208 32 144 violetred 188 143 143 rosybrown 0 0 128 navy blue 178 34 34 firebrick 139 0 0 dark red 255 255 255 grey100 139 126 102 wheat4 201 201 201 grey79 194 194 194 grey76 156 156 156 grey61 237 237 237 gray93 214 214 214 gray84 166 166 166 gray65 92 92 92 gray36 82 82 82 gray32 33 33 33 gray13 26 26 26 gray10 193 205 205 azure3 255 250 250 snow1 255 165 79 tan1 119 136 153 light slate gray 202 255 112 darkolivegreen1 100 149 237 cornflower blue 255 235 205 blanched almond 205 193 197 lavenderblush3 238 224 229 lavenderblush2 255 240 245 lavenderblush1 85 107 47 darkolivegreen 255 240 245 lavenderblush 118 238 198 aquamarine2 208 32 144 violet red 179 238 58 olivedrab2 139 125 123 mistyrose4 255 228 225 mistyrose1 180 205 205 lightcyan3 240 128 128 lightcoral 127 255 0 chartreuse 255 218 185 peachpuff 152 251 152 palegreen 245 255 250 mintcream 126 192 238 skyblue2 255 228 181 moccasin 255 99 71 tomato1 205 105 201 orchid3 205 41 144 maroon3 250 128 114 salmon 207 207 207 grey81 158 158 158 grey62 99 99 99 grey39 97 97 97 grey38 94 94 94 grey37 235 235 235 gray92 212 212 212 gray83 168 168 168 gray66 138 138 138 gray54 127 127 127 gray50 77 77 77 gray30 48 48 48 gray19 38 38 38 gray15 131 139 139 azure4 8 8 8 grey3 205 133 63 tan3 255 192 203 pink 190 190 190 gray 0 0 255 blue 188 210 238 lightsteelblue2 202 225 255 lightsteelblue1 32 178 170 light sea green 119 136 153 lightslategray 238 233 191 lemonchiffon2 0 255 127 springgreen1 173 255 47 greenyellow 118 238 0 chartreuse2 112 128 144 slate grey 58 95 205 royalblue3 176 224 230 powderblue 238 203 173 peachpuff2 144 238 144 palegreen2 245 255 250 mint cream 106 90 205 slateblue 238 229 222 seashell2 238 18 137 deeppink2 189 183 107 darkkhaki 139 28 98 maroon4 160 82 45 sienna 181 181 181 grey71 171 171 171 grey67 46 46 46 grey18 150 150 150 gray59 110 110 110 gray43 64 64 64 gray25 255 228 196 bisque 255 0 0 red1 123 104 238 mediumslateblue 255 236 139 lightgoldenrod1 238 221 130 light goldenrod 150 205 205 paleturquoise3 96 123 139 lightskyblue4 0 255 127 spring green 255 255 224 light yellow 245 245 245 white smoke 0 0 205 medium blue 248 248 255 ghost white 54 100 139 steelblue4 205 155 155 rosybrown3 255 218 185 peachpuff1 154 255 154 palegreen1 138 43 226 blueviolet 139 134 130 seashell4 169 169 169 darkgray 205 104 57 sienna3 102 102 102 grey40 232 232 232 gray91 209 209 209 gray82 13 13 13 gray5 0 238 238 cyan2 0 255 255 cyan1 0 0 255 blue1 255 250 250 snow 238 220 130 lightgoldenrod2 132 112 255 lightslateblue 180 82 205 mediumorchid3 105 139 105 darkseagreen4 0 205 102 springgreen3 34 139 34 forest green 108 123 139 slategray4 159 182 205 slategray3 185 211 238 slategray2 65 105 225 royal blue 139 119 101 peachpuff4 84 139 84 palegreen4 152 251 152 pale green 205 55 0 orangered3 255 193 37 goldenrod1 248 248 255 ghostwhite 139 26 26 firebrick4 205 38 38 firebrick3 122 197 205 cadetblue3 112 128 144 slategray 205 197 191 seashell3 193 205 193 honeydew3 139 136 120 cornsilk4 238 232 205 cornsilk2 155 48 255 purple1 105 105 105 dimgrey 139 0 0 darkred 255 246 143 khaki1 205 205 193 ivory3 179 179 179 grey70 153 153 153 grey60 82 82 82 grey32 56 56 56 grey22 31 31 31 grey12 250 250 250 gray98 227 227 227 gray89 181 181 181 gray71 163 163 163 gray64 153 153 153 gray60 125 125 125 gray49 224 238 238 azure2 8 8 8 gray3 187 255 255 paleturquoise1 171 130 255 mediumpurple1 147 112 219 medium purple 255 250 205 lemonchiffon1 0 191 255 deep sky blue 205 179 139 navajowhite3 191 62 255 darkorchid1 255 140 0 dark orange 238 180 34 goldenrod2 189 183 107 dark khaki 238 118 33 chocolate2 238 197 145 burlywood2 240 255 240 honeydew1 0 100 0 darkgreen 205 181 205 thistle3 238 210 238 thistle2 255 225 255 thistle1 0 0 139 darkblue 216 191 216 thistle 238 48 167 maroon2 255 52 179 maroon1 135 135 135 grey53 112 112 112 grey44 64 64 64 grey25 189 189 189 gray74 115 115 115 gray45 105 105 105 gray41 89 89 89 gray35 69 69 69 gray27 59 59 59 gray23 41 41 41 gray16 139 35 35 brown4 245 222 179 wheat 255 127 80 coral 139 90 43 tan4 250 250 210 lightgoldenrodyellow 132 112 255 light slate blue 85 107 47 dark olive green 47 79 79 dark slate gray 205 104 137 palevioletred3 93 71 139 mediumpurple4 137 104 205 mediumpurple3 139 69 19 saddlebrown 176 224 230 powder blue 104 34 139 darkorchid4 154 50 205 darkorchid3 255 218 185 peach puff 105 139 34 olivedrab4 104 131 139 lightblue4 255 182 193 lightpink 211 211 211 lightgray 224 238 224 honeydew2 255 248 220 cornsilk1 253 245 230 old lace 255 130 71 sienna1 139 125 107 bisque4 218 112 214 orchid 205 198 115 khaki3 214 214 214 grey84 212 212 212 grey83 209 209 209 grey82 184 184 184 grey72 133 133 133 grey52 110 110 110 grey43 66 66 66 grey26 36 36 36 grey14 26 26 26 grey10 191 191 191 gray75 135 135 135 gray53 54 54 54 gray21 51 51 51 gray20 205 51 51 brown3 20 20 20 grey8 238 0 0 red2 0 0 128 navy 190 190 190 grey 255 215 0 gold 102 205 170 mediumaquamarine 238 221 130 lightgoldenrod 82 139 139 darkslategray4 155 205 155 darkseagreen3 180 238 180 darkseagreen2 139 131 120 antiquewhite4 250 235 215 antique white 0 139 69 springgreen4 139 139 122 lightyellow4 255 250 240 floral white 127 255 212 aquamarine1 0 197 205 turquoise3 92 172 238 steelblue2 238 180 180 rosybrown2 255 182 193 light pink 211 211 211 light gray 238 99 99 indianred2 30 144 255 dodgerblue 0 100 0 dark green 84 255 159 seagreen1 139 10 80 deeppink4 240 248 255 aliceblue 255 0 255 magenta1 255 105 180 hot pink 238 121 66 sienna2 255 131 250 orchid1 255 255 255 gray100 247 247 247 grey97 240 240 240 grey94 222 222 222 grey87 219 219 219 grey86 130 130 130 grey51 107 107 107 grey42 48 48 48 grey19 240 240 240 gray94 217 217 217 gray85 156 156 156 gray61 238 59 59 brown2 240 230 140 khaki 3 3 3 grey1 139 117 0 gold4 123 104 238 medium slate blue 60 179 113 medium sea green 47 79 79 dark slate grey 175 238 238 pale turquoise 175 238 238 paleturquoise 122 55 139 mediumorchid4 238 223 204 antiquewhite2 238 238 209 lightyellow2 144 238 144 light green 148 0 211 dark violet 233 150 122 dark salmon 127 255 0 chartreuse1 0 245 255 turquoise1 244 164 96 sandybrown 255 69 0 orangered1 255 174 185 lightpink1 178 223 238 lightblue2 191 239 255 lightblue1 211 211 211 light grey 46 139 87 seagreen4 67 205 128 seagreen3 173 216 230 lightblue 205 16 118 deeppink3 169 169 169 dark grey 0 139 139 dark cyan 222 184 135 burlywood 255 245 238 seashell 255 110 180 hotpink1 105 105 105 dim gray 0 139 139 darkcyan 139 139 0 yellow4 255 255 0 yellow 160 32 240 purple 255 165 0 orange 139 139 131 ivory4 252 252 252 grey99 227 227 227 grey89 161 161 161 grey63 148 148 148 grey58 125 125 125 grey49 79 79 79 grey31 61 61 61 grey24 51 51 51 grey20 0 139 0 green4 0 255 0 green1 186 186 186 gray73 171 171 171 gray67 205 91 69 coral3 238 106 80 coral2 238 174 238 plum2 139 99 108 pink4 255 255 240 ivory 10 10 10 gray4 5 5 5 gray2 238 201 0 gold2 102 205 170 medium aquamarine 119 136 153 light slate grey 205 190 112 lightgoldenrod3 162 205 90 darkolivegreen3 255 185 15 darkgoldenrod1 184 134 11 dark goldenrod 186 85 211 medium orchid 255 250 205 lemon chiffon 139 121 94 navajowhite4 0 191 255 deepskyblue1 255 255 224 lightyellow 255 250 240 floralwhite 30 144 255 dodger blue 0 0 205 mediumblue 144 238 144 lightgreen 139 69 19 chocolate4 205 102 29 chocolate3 139 115 85 burlywood4 64 224 208 turquoise 70 130 180 steelblue 46 139 87 sea green 124 252 0 lawngreen 131 139 131 honeydew4 169 169 169 dark gray 46 139 87 seagreen 139 71 137 orchid4 255 231 186 wheat1 238 130 238 violet 255 255 240 ivory1 224 224 224 grey88 217 217 217 grey85 145 145 145 grey57 143 143 143 grey56 140 140 140 grey55 122 122 122 grey48 120 120 120 grey47 117 117 117 grey46 77 77 77 grey30 43 43 43 grey17 120 120 120 gray47 74 74 74 gray29 238 169 184 pink2 13 13 13 grey5 10 10 10 grey4 0 255 0 green 0 0 0 gray0 165 42 42 brown 110 123 139 lightsteelblue4 110 139 61 darkolivegreen4 139 71 93 palevioletred4 135 206 250 light sky blue 121 205 205 darkslategray3 141 238 238 darkslategray2 151 255 255 darkslategray1 255 235 205 blanchedalmond 238 232 170 palegoldenrod 25 25 112 midnight blue 32 178 170 lightseagreen 205 201 165 lemonchiffon3 47 79 79 darkslategray 154 205 50 yellow green 143 188 143 darkseagreen 250 235 215 antiquewhite 238 118 0 darkorange2 69 139 0 chartreuse4 70 130 180 steel blue 255 193 193 rosybrown1 154 205 50 olivedrab3 238 162 173 lightpink2 255 69 0 orangered 139 123 139 thistle4 135 206 235 sky blue 255 248 220 cornsilk 238 130 98 salmon2 238 122 233 orchid2 238 238 224 ivory2 237 237 237 grey93 235 235 235 grey92 232 232 232 grey91 92 92 92 grey36 74 74 74 grey29 71 71 71 grey28 41 41 41 grey16 201 201 201 gray79 199 199 199 gray78 196 196 196 gray77 122 122 122 gray48 43 43 43 gray17 139 62 47 coral4 255 114 86 coral1 255 187 255 plum1 255 181 197 pink1 23 23 23 grey9 5 5 5 grey2 18 18 18 gray7 0 139 139 cyan4 0 0 205 blue3 221 160 221 plum 100 149 237 cornflowerblue 164 211 238 lightskyblue2 255 239 219 antiquewhite1 238 207 161 navajowhite2 255 222 173 navajowhite1 205 205 180 lightyellow3 139 0 139 dark magenta 255 222 173 navajowhite 205 102 0 darkorange3 245 245 245 whitesmoke 0 229 238 turquoise2 99 184 255 steelblue1 139 95 101 lightpink4 154 192 205 lightblue3 124 252 0 lawn green 255 127 36 chocolate1 240 248 255 alice blue 107 142 35 olivedrab 211 211 211 lightgrey 210 105 30 chocolate 139 0 139 magenta4 205 0 205 magenta3 255 255 0 yellow1 125 38 205 purple3 145 44 238 purple2 238 154 0 orange2 255 165 0 orange1 255 0 255 magenta 255 228 196 bisque1 238 216 174 wheat2 176 48 96 maroon 139 134 78 khaki4 245 245 245 grey96 242 242 242 grey95 204 204 204 grey80 127 127 127 grey50 105 105 105 grey41 38 38 38 grey15 28 28 28 grey11 204 204 204 gray80 148 148 148 gray58 102 102 102 gray40 87 87 87 gray34 56 56 56 gray22 255 64 64 brown1 205 201 201 snow3 72 209 204 mediumturquoise 162 181 205 lightsteelblue3 238 121 159 palevioletred2 255 130 171 palevioletred1 174 238 238 paleturquoise2 143 188 143 dark sea green 219 112 147 palevioletred 224 102 255 mediumorchid1 255 222 173 navajo white 147 112 219 mediumpurple 255 255 224 lightyellow1 28 134 238 dodgerblue2 30 144 255 dodgerblue1 139 0 139 darkmagenta 138 43 226 blue violet 102 205 170 aquamarine3 198 226 255 slategray1 112 128 144 slate gray 139 37 0 orangered4 205 140 149 lightpink3 173 216 230 light blue 153 50 204 darkorchid 152 245 255 cadetblue1 205 170 125 burlywood3 255 245 238 seashell1 205 200 177 cornsilk3 139 54 38 tomato4 238 92 66 tomato2 205 186 150 wheat3 250 250 250 grey98 150 150 150 grey59 59 59 59 grey23 0 205 0 green3 0 238 0 green2 184 184 184 gray72 158 158 158 gray62 133 133 133 gray52 117 117 117 gray46 107 107 107 gray42 71 71 71 gray28 61 61 61 gray24 255 255 255 white 0 205 205 cyan3 0 0 0 black GDGraph-1.44/samples/logo.png0000644000175000001440000000555710347716751014542 0ustar benusersPNG  IHDR@@PLTE#0g < PmJоĬnqL^`FaVbRp+OS͒tln'L̗00`iՊoѺ*6] (gԂF(嵅mjR`g6nAd$裔)0HಅH( ΰQlK\srvf+h̬$$WIhkopz,p/2Ћ}{Xx/q]X9OLolԤLܬ808MslB,OwLqOu?D r T߾̈́W0XԌ)UTL/U gY̕qRY,/B ˦l,L/boK\/Rp,,țZ/T,O ѠWnHpg Άnh7dq_lT,8o lrLROɨm尼R]5вLmr||f4в0ynҳRD ёDas]P 1aw qvUbw7m *ﯪPwnJ,pZqwݏqu5ziddUqkn6w8Z9LZ7ZnuCEtRNSS%bKGDtEXtSoftwaregif2png 0.6 (beta)iIDATxql+b'Kΐ. /u9i!wNlp64o(L>e88nXqiXu:Rː౤A`d &XW3U2guO~ݽ{Ͻ{~i}jX0xv?{{wG}ȅKdz~݅܀+_6&)ʚ~\k6&?`صvlnTz&rzŵ'|C%{v8]F 1H@@tXW\~oO?}fT)#K`n>6J,~KmT]}R2n@0f!Dzb0sjOm u3h⾾h4/ƹ/.xO $ g)?ٹs}xN@,N  ˢ Y ou[PP=&[ߟsJقA@i/4˨~L0 ܄M! оݷz:'}X44FN4ؽ_`lp=]D ,{LH`([bK#* 7Գ@aK A4*GNhd.@L@JF0&\Ui7):&}Kҟ 22/e!pt:d/WMNOSW]HRСt)ſϽNtANwRv]ofZ-D'V H#OHP;^3ukÀ-bh P:}.=rCNkљTmhɬiQ(Y Ɓɷ=uÇ*NʤRf#FITL(^CiH-yرJ94oڸpcnfDf-S i.nh^g*E&0~W1;Ba Fm}[:fHWHi ӱ_Q-Y2NgNe2B\x 7Dd4]ۨ)=Y5q-3z}f-N"<JZ(zk?}gTnԄFFF&6ܖI$3-WCR)1:poMzo>;ZRҰJgV;e||)`IQ/cGtӒH~_R <[ߏFp|޳K5I O4 AA3-&,5` Ju{+c* tUĄ)(?oڣ}|+Vc>é[ ԦZzYb+9:IfȨ}q<ؙ+?"N9t$kk킀 nZ/`Je L-d2xHOdœ->;4&6 yedjP99NBǪ}=sWQ4CRidB39=Www0 BSRKl?gR!Rxʍ!C<`dr(h$/ Sg4딆oܱ*u♿Y.ݐv,@v{ڕhPW|@n7ЮrjpZ,e]!rT_n;ot$qcN\H=G|;0?+oJx0IENDB`GDGraph-1.44/samples/sample95.pl0000644000175000001440000000504510614014571015044 0ustar benusersuse strict; use GD::Graph::bars; use GD::Graph::hbars; use GD::Graph::Data; require 'save.pl'; $GD::Graph::Error::Debug = 5; my $data = GD::Graph::Data->new( [ ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 5, 12, 24, 33, 19, 8, 6, 15, 21], [ 1, 2, 5, 6, 3, 1.5, 1, 3, 4], [ 2, 4, 4.5, 5, 2.5, 0.5, 1, 2, 3], ] ) or die GD::Graph::Data->error; my $values = $data->copy(); $values->set_y(1, 7, undef) or warn $data->error; $values->set_y(2, 7, undef) or warn $data->error; $values->set_y(3, 7, undef) or warn $data->error; my @names = qw/sample95 sample95-h/; for my $my_graph (GD::Graph::bars->new(600,400), GD::Graph::hbars->new(600,400)) { my $name = shift @names; print STDERR "Processing $name\n"; $my_graph->set( x_label => 'x label', y1_label => 'y1 label', y2_label => 'y2 label', title => 'Using two axes with three datasets', y1_max_value => 40, y2_max_value => 8, y_tick_number => 8, y_label_skip => 2, long_ticks => 1, two_axes => 1, use_axis => [1, 2, 2], legend_placement => 'RT', x_label_position => 1/2, bgclr => 'white', fgclr => 'white', boxclr => 'dblue', accentclr => 'dblue', valuesclr => '#ffff77', dclrs => [qw(lgreen lred lred)], bar_spacing => 1, logo => 'logo.' . GD::Graph->export_format, logo_position => 'BR', transparent => 0, l_margin => 10, b_margin => 10, r_margin => 10, t_margin => 10, show_values => 1, values_format => "%4.1f", ) or warn $my_graph->error; if ($name =~ /-h$/) { $my_graph->set(x_labels_vertical => 0, values_vertical => 0); $my_graph->set_legend('bottom axis', 'top axis'); } else { $my_graph->set(x_labels_vertical => 1, values_vertical => 1); $my_graph->set_legend('left axis', 'right axis'); } my $font_spec = "../Dustismo_Sans"; $my_graph->set_y_label_font($font_spec, 12); $my_graph->set_x_label_font($font_spec, 12); $my_graph->set_y_axis_font($font_spec, 10); $my_graph->set_x_axis_font($font_spec, 10); $my_graph->set_title_font($font_spec, 18); $my_graph->set_legend_font($font_spec, 8); $my_graph->set_values_font($font_spec, 8); $my_graph->plot($data) or die $my_graph->error; save_chart($my_graph, $name); } GDGraph-1.44/samples/sample71.pl0000644000175000001440000000507410347716751015054 0ustar benusersuse strict; use GD::Graph::mixed; require 'save.pl'; print STDERR "Processing sample71\n"; my @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 1, 2, 5, 6, 3, 1.5, -1, -3, -4], [ -4, -3, 1, 1, -3, -1.5, -2, -1, 0], [ 9, 8, 9, 8.4, 7.1, 7.5, 8, 3, -3], [ 0.1, 0.2, 0.5, 0.4, 0.3, 0.5, 0.1, 0, 0.4], [ -0.1, 2, 5, 4, -3, 2.5, 3.2, 4, -4], ); my ($width, $height) = (500, 400); my $my_graph = new GD::Graph::mixed($width, $height); $my_graph->set( types => [ qw( lines bars points area linespoints ) ], default_type => 'points', ); $my_graph->set( x_label => 'X Label', y_label => 'Y label', title => 'Mixed Type and TTF', y_max_value => 10, y_min_value => -5, y_tick_number => 3, y_label_skip => 1, x_plot_values => 1, y_plot_values => 1, long_ticks => 1, x_ticks => 0, x_labels_vertical => 1, legend_marker_width => 24, line_width => 3, marker_size => 5, bar_spacing => 6, legend_placement => 'RC', transparent => 0, ); $my_graph->set_title_font('../Dustismo_Sans.ttf', 18); $my_graph->set_x_label_font('../Dustismo_Sans.ttf', 10); $my_graph->set_y_label_font('../Dustismo_Sans.ttf', 10); $my_graph->set_x_axis_font('../Dustismo_Sans.ttf', 8); $my_graph->set_y_axis_font('../Dustismo_Sans.ttf', 8); $my_graph->set_legend_font('../Dustismo_Sans.ttf', 9); $my_graph->set_legend( qw( one two three four five six ) ); # Put some background text in, but only if we have TTF support if ($my_graph->can_do_ttf) { my $gd = $my_graph->gd; my $white = $gd->colorAllocate(255,255,255); my $pink = $gd->colorAllocate(255,240,240); my $gdta; $gdta = GD::Text::Align->new($gd, text => 'GD::Graph', font => '../Dustismo_Sans.ttf', ptsize => 72, colour => $pink, valign => 'center', halign => 'center', ) or warn $gdta->error; $gdta->draw($width/2, $height/2, atan2($height, $width)); } $my_graph->plot(\@data); # Use a hotspot to draw some extra text on the chart # XXX This doesn't work nicely. Need a nicer way to get the maximum. if (1) { my $gd = $my_graph->gd; my $red = $gd->colorResolve(255,0,0); my @l = $my_graph->get_hotspot(1, 3); my ($x, $y) = ( ($l[1] + $l[3])/2, ($l[2] + $l[4])/2 ); my $gdta; $gdta = GD::Text::Align->new($gd, text => 'maximum', font => ['../Dustismo_Sans.ttf', GD::Font->Small], ptsize => 12, colour => $red, valign => 'bottom', halign => 'center', ) or warn $gdta->error; $gdta->draw($x, $y + 2); } save_chart($my_graph, 'sample71'); GDGraph-1.44/samples/sample13.pl0000644000175000001440000000144110347716751015042 0ustar benusersuse strict; use GD::Graph::bars; use GD::Graph::hbars; require 'save.pl'; my @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 5, 12, 24, 33, 19, 8, 6, 15, 21], [ 1, 2, 5, 6, 3, 1.5, 1, 3, 4] ); my @names = qw/sample13 sample13-h/; for my $my_graph (GD::Graph::bars->new, GD::Graph::hbars->new) { my $name = shift @names; print STDERR "Processing $name\n"; $my_graph->set( x_label => 'X Label', y_label => 'Y label', title => 'Bars in front of each other', #y_tick_number => 8, #y_label_skip => 2, overwrite => 1, bar_spacing => 8, shadow_depth => 4, transparent => 0, ); $my_graph->plot(\@data); save_chart($my_graph, $name); } GDGraph-1.44/samples/sample14.pl0000644000175000001440000000457010347716751015051 0ustar benusersuse strict; use GD::Graph::bars; use GD::Graph::hbars; use GD::Graph::Data; require 'save.pl'; $GD::Graph::Error::Debug = 5; my $data = GD::Graph::Data->new( [ ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 5, 12, 24, 33, 19, 8, 6, 15, 21], [ 1, 2, 5, 6, 3, 1.5, 1, 3, 4], ] ) or die GD::Graph::Data->error; my $values = $data->copy(); $values->set_y(1, 7, undef) or warn $data->error; $values->set_y(2, 7, undef) or warn $data->error; my @names = qw/sample14 sample14-h/; for my $my_graph (GD::Graph::bars->new(600,400), GD::Graph::hbars->new(600,400)) { my $name = shift @names; print STDERR "Processing $name\n"; $my_graph->set( x_label => 'x label', y1_label => 'y1 label', y2_label => 'y2 label', title => 'Using two axes', y1_max_value => 40, y2_max_value => 8, y_tick_number => 8, y_label_skip => 2, long_ticks => 1, two_axes => 1, legend_placement => 'RT', x_label_position => 1/2, bgclr => 'white', fgclr => 'white', boxclr => 'dblue', accentclr => 'dblue', valuesclr => '#ffff77', dclrs => [qw(lgreen lred)], bar_spacing => 1, logo => 'logo.' . GD::Graph->export_format, logo_position => 'BR', transparent => 0, l_margin => 10, b_margin => 10, r_margin => 10, t_margin => 10, show_values => 1, values_format => "%4.1f", ) or warn $my_graph->error; if ($name =~ /-h$/) { $my_graph->set(x_labels_vertical => 0, values_vertical => 0); $my_graph->set_legend('bottom axis', 'top axis'); } else { $my_graph->set(x_labels_vertical => 1, values_vertical => 1); $my_graph->set_legend('left axis', 'right axis'); } my $font_spec = "../Dustismo_Sans"; $my_graph->set_y_label_font($font_spec, 12); $my_graph->set_x_label_font($font_spec, 12); $my_graph->set_y_axis_font($font_spec, 10); $my_graph->set_x_axis_font($font_spec, 10); $my_graph->set_title_font($font_spec, 18); $my_graph->set_legend_font($font_spec, 8); $my_graph->set_values_font($font_spec, 8); $my_graph->plot($data) or die $my_graph->error; save_chart($my_graph, $name); } GDGraph-1.44/samples/Makefile0000644000175000001440000000416610614024754014517 0ustar benusers# This Makefile requires GNU make. If you have anything else, it is very # likely that you won't be able to use this. Two pieces of advice: # # Get GNU make. It's free, and superior to many others # # Run the examples by hand, one by one, or do something like # # tcsh> foreach s (*.pl) # foreach> perl -I. -Mblib -Tw $s # foreach> end # # If you use an old version of GD that exports GIF, you will need to # have ImageMagick installed, or you need to provide another way to # convert logo.png to logo.gif. .SILENT: PERL = perl EXTRA_OPTS = OPTIONS = -I. -Mblib $(EXTRA_OPTS) -w EXT := $(shell perl $(OPTIONS) -MGD::Graph \ -e 'print scalar GD::Graph::export_format') SAMPLES := \ sample11 sample12 sample13 sample14 sample15 \ sample16 sample17 sample18 sample19 sample1A sample1B \ sample11-h sample12-h sample13-h sample14-h sample15-h \ sample16-h sample17-h sample18-h sample19-h sample1A-h sample1B-h\ sample21 sample22 sample23 \ sample31 \ sample41 sample42\ sample51 sample52 sample53 sample54 sample55 sample56 \ sample57 \ sample61 sample62 sample63 sample64 \ sample71 \ sample91 sample92 sample93 sample94 sample95 sample95-h IMAGES := $(SAMPLES:%=%.$(EXT)) all: $(IMAGES) echo "" echo These samples are both examples and test cases. Therefore echo some of them might look slightly unrealistic. info: $(PERL) $(OPTIONS) -le 'print "Perl ", $$]' $(PERL) $(OPTIONS) -MGD -le 'print "GD ", $$GD::VERSION' $(PERL) $(OPTIONS) -MGD::Text \ -le 'print "GD::Text ", $$GD::Text::VERSION' $(PERL) $(OPTIONS) -MGD::Graph \ -le 'print "GD::Graph ", $$GD::Graph::VERSION' $(PERL) $(OPTIONS) -le 'for (@INC) {print}' %.$(EXT) %-h.$(EXT): %.pl $(PERL) $(OPTIONS) $< # EXPERIMENTAL, for internal use only. Don't try to run this html: make_index.pl Makefile $(PERL) $(OPTIONS) make_index.pl $(EXT) # Requires ImageMagick to be installed logo.gif: logo.png convert logo.png logo.gif clean: rm -f $(IMAGES) logo.gif # Other dependencies sample14.$(EXT): logo.$(EXT) sample42.$(EXT): sample42.dat sample54.$(EXT): sample54.dat sample56.$(EXT): sample54.dat sample53.$(EXT): rgb.txt GDGraph-1.44/samples/sample31.pl0000644000175000001440000000127610347716751015050 0ustar benusersuse GD::Graph::points; require 'save.pl'; print STDERR "Processing sample31\n"; @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 5, 12, 24, 33, 19, 8, 6, 15, 21], [ 1, 2, 5, 6, 3, 1.5, undef, 3, 4], ); $my_graph = new GD::Graph::points(); $my_graph->set( x_label => 'X Label', y_label => 'Y label', title => 'A Points Graph', y_max_value => 40, y_tick_number => 8, y_label_skip => 2, legend_placement => 'RC', long_ticks => 1, marker_size => 6, markers => [ 9, 10, 1, 7, 5 ], transparent => 0, ); $my_graph->set_legend( qw( one two ) ); $my_graph->plot(\@data); save_chart($my_graph, 'sample31'); GDGraph-1.44/samples/sample62.pl0000644000175000001440000000150210347716751015044 0ustar benusersuse GD::Graph::mixed; require 'save.pl'; print STDERR "Processing sample62\n"; @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 9, 8, 9, 8.4, 7.1, 7.5, 8, 3, 3], [ .4, .3, 1, 1, .3, 1.5, 2, 1, 0], ); $my_graph = new GD::Graph::mixed(); $my_graph->set( x_label => 'X Label', y1_label => 'Y1 label', y2_label => 'Y2 label', title => 'A Mixed Type Graph with Two Axes', two_axes => 1, y1_max_value => 10, y2_max_value => 2.5, y_min_value => 0, y_tick_number => 5, long_ticks => 1, x_ticks => 0, legend_marker_width => 24, line_width => 5, bar_spacing => 4, types => [ qw( bars lines ) ], transparent => 0, ); $my_graph->set_legend( qw( one two three four five six ) ); $my_graph->plot(\@data); save_chart($my_graph, 'sample62'); GDGraph-1.44/samples/sample91.pl0000644000175000001440000000077410347716751015060 0ustar benusersuse GD::Graph::pie; require 'save.pl'; print STDERR "Processing sample91\n"; @data = ( ["1st","2nd","3rd","4th","5th","6th"], [ 4, 2, 3, 4, 3, 3.5] ); $my_graph = new GD::Graph::pie( 250, 200 ); #$my_graph = new GD::Graph::pie( ); $my_graph->set( title => 'A Pie Chart', label => 'Label', axislabelclr => 'black', pie_height => 36, l_margin => 15, r_margin => 15, start_angle => 235, transparent => 0, ); $my_graph->plot(\@data); save_chart($my_graph, 'sample91'); GDGraph-1.44/samples/sample92.pl0000644000175000001440000000114410347716751015051 0ustar benusersuse GD::Graph::pie; require 'save.pl'; print STDERR "Processing sample92\n"; @data = ( ["1st","2nd","3rd","4th","5th","6th"], [ 4, 2, 3, 4, 3, 3.5] ); $my_graph = new GD::Graph::pie( 250, 200 ); $my_graph->set( title => 'A Pie Chart', label => 'Label', axislabelclr => 'white', dclrs => [ 'lblue' ], accentclr => 'lgray', transparent => 0, ); $my_graph->set_title_font('../cetus.ttf', 18); $my_graph->set_label_font('../cetus.ttf', 12); $my_graph->set_value_font('../cetus.ttf', 10); $my_graph->plot(\@data); save_chart($my_graph, 'sample92'); GDGraph-1.44/samples/sample1A.pl0000644000175000001440000000212110614014571015040 0ustar benusers#!/usr/local/bin/perl use strict; use GD::Graph::bars; use GD::Graph::hbars; require 'save.pl'; my @data = ( ["1st","2nd","3rd","4th","5th","6th","7th"], [ 5, 12, 24, 33, 19, 18, 6], [ 5, 11, 13, 28, 23, 13, 1], [ 2, 8, 10, 20, 18, 21, 3], [ 10, 20, 19, 36, 23, 19, 11], ); my @names = qw/sample1A sample1A-h/; my @dim = (600,400); for my $my_graph (GD::Graph::bars->new(@dim),GD::Graph::hbars->new(@dim)) { my $name = shift @names; print STDERR "Processing $name\n"; $my_graph->set( x_label => 'X Label', y_label => 'Y label', title => 'Four data sets (with grouping space)', y_max_value => 40, y_tick_number => 8, y_label_skip => 2, bar_spacing => 2, shadow_depth => 3, bargroup_spacing => 4, accent_treshold => 200, transparent => 0, ); $my_graph->set_legend(qw(Harry Ron Neville Hermione)); $my_graph->plot(\@data); save_chart($my_graph, $name); } GDGraph-1.44/samples/sample1B.pl0000644000175000001440000000167210614014571015053 0ustar benusers#!/usr/bin/perl # This code demonstrates the problem I am having with labels inside # of a stacked bar chart use strict; use GD::Graph::hbars; require "save.pl"; my @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 1, 2, 5, 6, 3, 1.5, 1, 3, 4], [ 1, 1.5, 3, 2, 3, 1.5, 3, 4, 4 ] ); my @dim = (600,400); my @names = qw/sample1B sample1B-h/; for my $graph (GD::Graph::bars->new(@dim),GD::Graph::hbars->new(@dim)) { my $name = shift @names; print STDERR "Processing $name\n"; $graph->set_legend('Pass', 'Fail'); $graph->set( x_label => 'X Label', y_label => 'Y label', title => 'Cumulated bar graph with labels', y_max_value => 10, y_tick_number => 10, y_label_skip => 2, bar_spacing => 8, cumulate => 'true', dclrs => [ qw( green lred ) ], show_values => 1, values_space => 4, ) or warn $graph->error; my $format = $graph->export_format; $graph->plot(\@data)->$format(); save_chart($graph,$name); } GDGraph-1.44/samples/sample12.pl0000644000175000001440000000157310347716751015047 0ustar benusersuse strict; use GD::Graph::bars; use GD::Graph::hbars; require 'save.pl'; my @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 5, 12, 24, 33, 19, 8, 6, 15, 21], [ 1, 2, 5, 6, 3, 1.5, 1, 3, 4], ); my @names = qw/sample12 sample12-h/; for my $my_graph (GD::Graph::bars->new, GD::Graph::hbars->new) { my $name = shift @names; print STDERR "Processing $name\n"; $my_graph->set( x_label => 'X Label', y_label => 'Y label', title => 'Two data sets', long_ticks => 1, y_max_value => 40, y_tick_number => 8, y_label_skip => 2, bar_spacing => 3, shadow_depth => 4, accent_treshold => 200, transparent => 0, ); $my_graph->set_legend('Data set 1', 'Data set 2'); $my_graph->plot(\@data); save_chart($my_graph, $name); } GDGraph-1.44/samples/sample56.pl0000644000175000001440000000211110347716751015044 0ustar benusersuse GD::Graph::lines; require 'save.pl'; print STDERR "Processing sample56 (experimental)\n"; @data = read_data("sample54.dat") or die "Cannot read data from sample54.dat"; $my_graph = new GD::Graph::lines(); $my_graph->set( x_label => 'Wavelength (nm)', y_label => 'Absorbance', title => 'Numerical X axis', y_min_value => 0, y_max_value => 2, y_tick_number => 8, y_label_skip => 4, x_tick_number => 14, x_min_value => 100, x_max_value => 800, x_ticks => 1, x_tick_length => -4, x_long_ticks => 1, x_label_skip => 2, x_tick_offset => 2, no_axes => 1, line_width => 2, x_label_position => 1/2, r_margin => 15, transparent => 0, ); $my_graph->set_legend('Thanks to Scott Prahl and Gary Deschaines'); $my_graph->plot(\@data); save_chart($my_graph, 'sample56'); sub read_data { my $fn = shift; local(*ZZZ); my @d = (); open(ZZZ, $fn) || return (); while () { chomp; my @row = split; for (my $i = 0; $i <= $#row; $i++) { undef $row[$i] if ($row[$i] eq 'undef'); unshift @{$d[$i]}, $row[$i]; } } close (ZZZ); return @d; } GDGraph-1.44/samples/sample93.pl0000644000175000001440000000074710347716751015062 0ustar benusersuse GD::Graph::pie; require 'save.pl'; print STDERR "Processing sample93\n"; @data = ( [ qw( 1st 2nd 3rd 4th 5th 6th 7th ) ], [ sort { $b <=> $a} (5.6, 2.1, 3.03, 4.05, 1.34, 0.2, 2.56) ] ); $my_graph = new GD::Graph::pie( 200, 200 ); $my_graph->set( start_angle => 90, '3d' => 0, label => 'Foo Bar', # The following should prevent the 7th slice from getting a label suppress_angle => 5, transparent => 0, ); $my_graph->plot(\@data); save_chart($my_graph, 'sample93'); GDGraph-1.44/samples/sample11.pl0000644000175000001440000000163610347716751015046 0ustar benusersuse strict; use GD::Graph::bars; use GD::Graph::hbars; use GD::Graph::Data; require 'save.pl'; my $data = GD::Graph::Data->new([ ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 1, 2, 5, 6, 3, 1.5, 1, 3, 4], ]) or die GD::Graph::Data->error; my @names = qw/sample11 sample11-h/; for my $my_graph (GD::Graph::bars->new, GD::Graph::hbars->new) { my $name = shift @names; print STDERR "Processing $name\n"; $my_graph->set( x_label => 'X Label', y_label => 'Y label', title => 'A Simple Bar Chart', #y_max_value => 8, #y_tick_number => 8, #y_label_skip => 2, #x_labels_vertical => 1, # shadows bar_spacing => 8, shadow_depth => 4, shadowclr => 'dred', transparent => 0, ) or warn $my_graph->error; $my_graph->plot($data) or die $my_graph->error; save_chart($my_graph, $name); } GDGraph-1.44/samples/sample54.dat0000644000175000001440000007535410347716751015222 0ustar benusers700.000 0.003485 699.750 -0.001097 699.500 -0.002087 699.250 0.001198 699.000 0.000286 698.750 -0.000158 698.500 0.000168 698.250 -0.000262 698.000 0.001695 697.750 0.001520 697.500 0.000413 697.250 0.001776 697.000 -0.000226 696.750 -0.001634 696.500 0.001075 696.250 0.002390 696.000 -0.000109 695.750 0.000572 695.500 0.000110 695.250 0.000005 695.000 -0.000334 694.750 -0.000543 694.500 0.000820 694.250 0.000451 694.000 0.001651 693.750 -0.000832 693.500 0.000726 693.250 0.000399 693.000 -0.001413 692.750 -0.000926 692.500 0.001384 692.250 0.000304 692.000 0.000731 691.750 0.000284 691.500 -0.001864 691.250 0.002392 691.000 -0.002022 690.750 -0.001963 690.500 0.000652 690.250 0.001707 690.000 0.001195 689.750 0.001182 689.500 0.001832 689.250 -0.001381 689.000 0.001112 688.750 0.000403 688.500 0.000576 688.250 -0.001397 688.000 0.001534 687.750 -0.000616 687.500 0.000276 687.250 -0.000747 687.000 -0.000232 686.750 -0.000382 686.500 0.000031 686.250 -0.001819 686.000 0.001683 685.750 0.000853 685.500 0.000385 685.250 0.001108 685.000 -0.001241 684.750 0.001103 684.500 0.001127 684.250 -0.000541 684.000 0.000518 683.750 0.000284 683.500 -0.000656 683.250 0.000395 683.000 0.000378 682.750 0.001463 682.500 0.001554 682.250 0.000277 682.000 0.001752 681.750 0.001333 681.500 0.002022 681.250 0.001392 681.000 0.000737 680.750 0.000205 680.500 0.001799 680.250 -0.001171 680.000 -0.000689 679.750 0.001249 679.500 0.002911 679.250 0.000199 679.000 -0.000050 678.750 -0.000738 678.500 0.000714 678.250 -0.002703 678.000 0.001025 677.750 0.000583 677.500 0.002166 677.250 0.001560 677.000 0.005364 676.750 0.001962 676.500 0.000031 676.250 0.001134 676.000 0.001617 675.750 -0.000237 675.500 -0.001913 675.250 0.000409 675.000 -0.000626 674.750 -0.000785 674.500 0.000176 674.250 0.000385 674.000 0.001106 673.750 0.000414 673.500 0.000475 673.250 0.002717 673.000 0.001492 672.750 0.002600 672.500 0.000252 672.250 0.002480 672.000 0.000457 671.750 0.000962 671.500 0.002991 671.250 0.001473 671.000 0.003620 670.750 0.001495 670.500 0.002955 670.250 0.006124 670.000 0.002939 669.750 0.000903 669.500 0.000541 669.250 -0.000725 669.000 0.001060 668.750 0.000069 668.500 0.002306 668.250 0.002930 668.000 0.001625 667.750 -0.001658 667.500 0.001622 667.250 0.002226 667.000 0.001875 666.750 0.001441 666.500 0.001486 666.250 0.001678 666.000 -0.002652 665.750 0.001211 665.500 0.001754 665.250 0.002511 665.000 -0.000742 664.750 0.003748 664.500 0.000592 664.250 0.003531 664.000 0.001268 663.750 0.002753 663.500 0.001279 663.250 0.002106 663.000 -0.000628 662.750 0.003597 662.500 0.000905 662.250 -0.001147 662.000 0.000835 661.750 0.001582 661.500 0.000192 661.250 0.002283 661.000 0.000832 660.750 0.000271 660.500 -0.000217 660.250 0.000852 660.000 0.001018 659.750 -0.000924 659.500 0.002043 659.250 0.001838 659.000 -0.000131 658.750 0.002503 658.500 0.002001 658.250 0.001777 658.000 -0.000453 657.750 0.001435 657.500 -0.000089 657.250 0.003333 657.000 0.000484 656.750 -0.001547 656.500 0.001847 656.250 0.003163 656.000 0.001798 655.750 -0.001625 655.500 0.001741 655.250 -0.000855 655.000 0.002662 654.750 0.002060 654.500 -0.000580 654.250 -0.000509 654.000 -0.001555 653.750 0.000236 653.500 0.002695 653.250 0.000810 653.000 0.000186 652.750 -0.000797 652.500 -0.001033 652.250 0.000642 652.000 0.000284 651.750 -0.000660 651.500 0.000113 651.250 0.001203 651.000 -0.000545 650.750 0.002602 650.500 -0.000550 650.250 -0.000873 650.000 0.002922 649.750 0.002667 649.500 -0.001198 649.250 -0.001668 649.000 -0.000872 648.750 0.000872 648.500 -0.000782 648.250 0.001165 648.000 0.001180 647.750 0.002938 647.500 -0.000021 647.250 0.001230 647.000 0.003165 646.750 -0.001589 646.500 -0.001688 646.250 -0.001920 646.000 -0.000839 645.750 -0.000133 645.500 0.003075 645.250 0.000394 645.000 -0.000885 644.750 -0.000866 644.500 0.001828 644.250 0.001108 644.000 -0.000129 643.750 0.000601 643.500 -0.000420 643.250 -0.000986 643.000 -0.000769 642.750 0.001334 642.500 0.000676 642.250 0.001345 642.000 -0.001207 641.750 -0.000712 641.500 0.001083 641.250 0.002568 641.000 -0.000668 640.750 -0.001999 640.500 0.000531 640.250 0.001468 640.000 0.000154 639.750 0.001899 639.500 0.000923 639.250 0.000379 639.000 0.001225 638.750 0.002069 638.500 0.000196 638.250 -0.000645 638.000 -0.000330 637.750 0.001110 637.500 0.000983 637.250 0.000027 637.000 -0.000023 636.750 -0.000348 636.500 -0.000624 636.250 0.001612 636.000 0.000451 635.750 -0.000827 635.500 0.002637 635.250 0.002549 635.000 0.001107 634.750 0.000468 634.500 0.000526 634.250 0.000395 634.000 0.000030 633.750 0.003069 633.500 0.000996 633.250 0.002051 633.000 0.001829 632.750 0.002402 632.500 0.000911 632.250 0.001727 632.000 -0.001005 631.750 0.001516 631.500 0.002026 631.250 0.001725 631.000 0.000992 630.750 -0.000457 630.500 -0.000459 630.250 0.001449 630.000 0.000957 629.750 0.001148 629.500 -0.001836 629.250 -0.002367 629.000 0.001593 628.750 0.000480 628.500 0.000451 628.250 -0.000803 628.000 0.000530 627.750 0.000069 627.500 0.001225 627.250 -0.000237 627.000 0.002603 626.750 -0.000488 626.500 -0.002227 626.250 0.001372 626.000 0.000540 625.750 0.001948 625.500 0.002627 625.250 -0.001437 625.000 0.000955 624.750 -0.000582 624.500 0.002640 624.250 -0.001048 624.000 0.002180 623.750 -0.003305 623.500 0.002353 623.250 -0.000908 623.000 0.001728 622.750 0.000160 622.500 0.001645 622.250 -0.000651 622.000 0.001856 621.750 0.001581 621.500 0.000985 621.250 0.000942 621.000 0.002110 620.750 0.000117 620.500 -0.001055 620.250 0.003015 620.000 -0.000091 619.750 0.000835 619.500 0.001019 619.250 0.002355 619.000 -0.000704 618.750 -0.000790 618.500 0.000019 618.250 -0.000134 618.000 -0.000123 617.750 0.000831 617.500 0.001568 617.250 -0.000491 617.000 0.002866 616.750 0.000143 616.500 0.000490 616.250 0.001049 616.000 0.002870 615.750 0.001223 615.500 0.000982 615.250 -0.000359 615.000 0.002900 614.750 0.000677 614.500 0.000658 614.250 0.002700 614.000 0.000002 613.750 0.000213 613.500 0.001694 613.250 -0.000312 613.000 0.000419 612.750 0.000414 612.500 0.001325 612.250 0.000094 612.000 0.001089 611.750 -0.000198 611.500 0.001635 611.250 0.000737 611.000 -0.000046 610.750 0.000068 610.500 0.001006 610.250 0.000079 610.000 0.001836 609.750 0.002766 609.500 0.001276 609.250 0.000247 609.000 0.000628 608.750 0.002193 608.500 0.002646 608.250 0.002348 608.000 0.000857 607.750 -0.000423 607.500 -0.000218 607.250 0.000280 607.000 0.001252 606.750 0.000404 606.500 0.002017 606.250 -0.000554 606.000 0.001009 605.750 0.001266 605.500 0.000968 605.250 0.000284 605.000 0.001797 604.750 0.000838 604.500 0.002422 604.250 -0.000424 604.000 -0.000080 603.750 0.000215 603.500 -0.001128 603.250 0.001883 603.000 0.000773 602.750 -0.000565 602.500 0.002195 602.250 0.000088 602.000 0.001426 601.750 0.003078 601.500 0.002494 601.250 0.000300 601.000 0.000579 600.750 0.000186 600.500 -0.000276 600.250 0.001364 600.000 0.001982 599.750 0.002404 599.500 0.001908 599.250 0.000279 599.000 -0.001049 598.750 0.002265 598.500 -0.001644 598.250 0.000101 598.000 0.001239 597.750 0.000955 597.500 0.002879 597.250 0.000817 597.000 0.001023 596.750 0.001283 596.500 0.001764 596.250 -0.000999 596.000 0.000187 595.750 0.001942 595.500 -0.000854 595.250 -0.002409 595.000 0.000357 594.750 -0.000563 594.500 0.000600 594.250 0.003749 594.000 0.000623 593.750 0.001857 593.500 0.000868 593.250 -0.000006 593.000 -0.000283 592.750 0.001902 592.500 0.002514 592.250 0.001302 592.000 0.002633 591.750 0.000916 591.500 0.002026 591.250 -0.000080 591.000 0.001555 590.750 0.000751 590.500 0.001497 590.250 0.001723 590.000 0.001914 589.750 0.000415 589.500 -0.001266 589.250 0.001488 589.000 -0.001072 588.750 0.001006 588.500 0.001584 588.250 0.000532 588.000 -0.001322 587.750 -0.000756 587.500 0.000532 587.250 -0.000355 587.000 0.001842 586.750 0.000552 586.500 0.001010 586.250 0.002049 586.000 0.000164 585.750 -0.000412 585.500 0.001661 585.250 -0.000271 585.000 -0.000731 584.750 0.000704 584.500 0.000736 584.250 0.000654 584.000 0.000001 583.750 -0.002251 583.500 0.000575 583.250 -0.000178 583.000 0.000916 582.750 0.001753 582.500 -0.000349 582.250 -0.000609 582.000 0.000580 581.750 -0.000375 581.500 0.000991 581.250 -0.000937 581.000 0.000842 580.750 0.000026 580.500 -0.000214 580.250 -0.000118 580.000 0.000073 579.750 0.000877 579.500 0.002605 579.250 0.000737 579.000 0.000471 578.750 -0.000426 578.500 0.001335 578.250 -0.000555 578.000 0.002658 577.750 0.001066 577.500 0.001994 577.250 0.000393 577.000 0.000466 576.750 0.000646 576.500 0.001826 576.250 0.001087 576.000 0.000825 575.750 -0.002147 575.500 0.000255 575.250 0.000812 575.000 0.001162 574.750 0.000711 574.500 0.000311 574.250 0.001773 574.000 0.002306 573.750 0.001012 573.500 0.000637 573.250 0.001111 573.000 0.000362 572.750 0.001144 572.500 0.000562 572.250 0.001344 572.000 0.001589 571.750 0.000117 571.500 -0.000055 571.250 -0.000233 571.000 0.000308 570.750 0.000407 570.500 0.000665 570.250 -0.000233 570.000 0.001547 569.750 -0.001147 569.500 0.000613 569.250 0.000644 569.000 0.001209 568.750 0.002192 568.500 0.000225 568.250 0.001281 568.000 0.000971 567.750 0.000647 567.500 0.002784 567.250 0.002174 567.000 0.000563 566.750 -0.000070 566.500 0.001362 566.250 -0.000124 566.000 0.000341 565.750 0.003329 565.500 0.001766 565.250 0.000939 565.000 0.000516 564.750 0.002648 564.500 0.002011 564.250 0.001208 564.000 0.000322 563.750 -0.000868 563.500 0.001683 563.250 0.000417 563.000 0.003694 562.750 0.001758 562.500 0.002178 562.250 0.002440 562.000 -0.000152 561.750 0.001334 561.500 0.002478 561.250 0.001767 561.000 0.001378 560.750 0.002441 560.500 0.001331 560.250 0.002275 560.000 0.001786 559.750 0.000310 559.500 0.001405 559.250 0.000688 559.000 0.000435 558.750 0.001321 558.500 0.000936 558.250 0.001423 558.000 0.000207 557.750 0.001619 557.500 0.000612 557.250 0.002336 557.000 -0.000278 556.750 0.000278 556.500 0.000520 556.250 0.003567 556.000 0.002057 555.750 0.001919 555.500 0.000676 555.250 0.002609 555.000 0.001933 554.750 0.000364 554.500 0.000712 554.250 0.001593 554.000 0.000677 553.750 0.003557 553.500 0.001873 553.250 0.003056 553.000 0.002430 552.750 0.001535 552.500 0.002336 552.250 0.002086 552.000 0.000928 551.750 0.001911 551.500 0.002301 551.250 0.002146 551.000 0.001152 550.750 0.002746 550.500 0.002402 550.250 0.002560 550.000 0.002081 549.750 0.001410 549.500 0.001859 549.250 0.000054 549.000 0.000729 548.750 0.001124 548.500 0.002000 548.250 0.002374 548.000 0.003516 547.750 0.001118 547.500 0.004229 547.250 0.003176 547.000 0.001539 546.750 0.002328 546.500 0.002866 546.250 0.002322 546.000 0.001054 545.750 0.002090 545.500 0.002408 545.250 0.002877 545.000 0.001585 544.750 0.002585 544.500 0.002317 544.250 0.002914 544.000 0.002064 543.750 0.002194 543.500 0.003035 543.250 0.003390 543.000 0.001940 542.750 0.003991 542.500 0.001357 542.250 0.002414 542.000 0.000320 541.750 0.002636 541.500 0.000484 541.250 0.002455 541.000 0.001985 540.750 0.002848 540.500 0.003139 540.250 0.002187 540.000 0.002249 539.750 0.002824 539.500 0.001102 539.250 0.002202 539.000 0.002262 538.750 0.002717 538.500 0.003449 538.250 0.004284 538.000 0.002760 537.750 0.001382 537.500 0.002016 537.250 0.003520 537.000 0.004057 536.750 0.001832 536.500 0.000519 536.250 0.001278 536.000 0.004109 535.750 0.003109 535.500 0.002729 535.250 0.003620 535.000 0.003616 534.750 0.005985 534.500 0.003052 534.250 0.002422 534.000 0.002318 533.750 0.003863 533.500 0.002440 533.250 0.002440 533.000 0.003424 532.750 0.003696 532.500 0.002383 532.250 0.005181 532.000 0.004266 531.750 0.003357 531.500 0.002836 531.250 0.002791 531.000 0.004392 530.750 0.004000 530.500 0.005537 530.250 0.003467 530.000 0.004364 529.750 0.006034 529.500 0.005192 529.250 0.004109 529.000 0.005158 528.750 0.003946 528.500 0.003974 528.250 0.006072 528.000 0.007039 527.750 0.005294 527.500 0.004768 527.250 0.005977 527.000 0.006458 526.750 0.004524 526.500 0.005562 526.250 0.004991 526.000 0.007509 525.750 0.006177 525.500 0.004608 525.250 0.005739 525.000 0.007256 524.750 0.006819 524.500 0.007188 524.250 0.006378 524.000 0.007247 523.750 0.007964 523.500 0.007976 523.250 0.008371 523.000 0.008495 522.750 0.007874 522.500 0.009637 522.250 0.008548 522.000 0.007169 521.750 0.008511 521.500 0.009225 521.250 0.009122 521.000 0.010348 520.750 0.009869 520.500 0.012080 520.250 0.011043 520.000 0.011500 519.750 0.011698 519.500 0.012692 519.250 0.012226 519.000 0.013552 518.750 0.012339 518.500 0.014122 518.250 0.013902 518.000 0.013401 517.750 0.014588 517.500 0.016467 517.250 0.016510 517.000 0.016411 516.750 0.017746 516.500 0.017125 516.250 0.018484 516.000 0.019682 515.750 0.020348 515.500 0.019410 515.250 0.020820 515.000 0.021084 514.750 0.023799 514.500 0.024193 514.250 0.024466 514.000 0.026420 513.750 0.024900 513.500 0.028586 513.250 0.028666 513.000 0.028609 512.750 0.030678 512.500 0.031081 512.250 0.031811 512.000 0.032660 511.750 0.033620 511.500 0.037438 511.250 0.034871 511.000 0.037713 510.750 0.038781 510.500 0.040564 510.250 0.044399 510.000 0.043881 509.750 0.046421 509.500 0.046741 509.250 0.046794 509.000 0.049522 508.750 0.052733 508.500 0.054422 508.250 0.053607 508.000 0.057517 507.750 0.060001 507.500 0.058060 507.250 0.062783 507.000 0.062952 506.750 0.067736 506.500 0.068677 506.250 0.068596 506.000 0.072423 505.750 0.074690 505.500 0.078619 505.250 0.079714 505.000 0.084549 504.750 0.085463 504.500 0.089676 504.250 0.092779 504.000 0.094395 503.750 0.097944 503.500 0.102598 503.250 0.106443 503.000 0.106442 502.750 0.112589 502.500 0.115285 502.250 0.117788 502.000 0.123433 501.750 0.126776 501.500 0.130905 501.250 0.136913 501.000 0.142013 500.750 0.144770 500.500 0.150715 500.250 0.153160 500.000 0.161046 499.750 0.165289 499.500 0.171208 499.250 0.175056 499.000 0.182432 498.750 0.186069 498.500 0.193270 498.250 0.198940 498.000 0.205717 497.750 0.208447 497.500 0.219067 497.250 0.223011 497.000 0.230423 496.750 0.237589 496.500 0.247289 496.250 0.254037 496.000 0.260339 495.750 0.266421 495.500 0.276830 495.250 0.281242 495.000 0.290877 494.750 0.301098 494.500 0.307344 494.250 0.317485 494.000 0.325439 493.750 0.335905 493.500 0.344531 493.250 0.354326 493.000 0.362063 492.750 0.372033 492.500 0.381660 492.250 0.390094 492.000 0.399778 491.750 0.404125 491.500 0.411818 491.250 0.420785 491.000 0.432287 490.750 0.442628 490.500 0.453151 490.250 0.464478 490.000 0.473760 489.750 0.485156 489.500 0.495804 489.250 0.506534 489.000 0.519081 488.750 0.530027 488.500 0.541662 488.250 0.555836 488.000 0.567276 487.750 0.579372 487.500 0.588890 487.250 0.602199 487.000 0.615152 486.750 0.627062 486.500 0.639785 486.250 0.654855 486.000 0.667859 485.750 0.678458 485.500 0.689456 485.250 0.707747 485.000 0.720609 484.750 0.729401 484.500 0.747311 484.250 0.761109 484.000 0.771278 483.750 0.788845 483.500 0.803751 483.250 0.816788 483.000 0.829087 482.750 0.842090 482.500 0.857695 482.250 0.873934 482.000 0.887415 481.750 0.902979 481.500 0.914144 481.250 0.932168 481.000 0.944113 480.750 0.960203 480.500 0.973121 480.250 0.987002 480.000 1.001077 479.750 1.017602 479.500 1.034350 479.250 1.046191 479.000 1.059908 478.750 1.079969 478.500 1.097367 478.250 1.109840 478.000 1.126115 477.750 1.140256 477.500 1.151599 477.250 1.170288 477.000 1.187523 476.750 1.200290 476.500 1.216126 476.250 1.233279 476.000 1.249161 475.750 1.265606 475.500 1.280025 475.250 1.290943 475.000 1.309434 474.750 1.326134 474.500 1.340813 474.250 1.349204 474.000 1.367864 473.750 1.377791 473.500 1.393125 473.250 1.409705 473.000 1.418322 472.750 1.431218 472.500 1.443075 472.250 1.454210 472.000 1.467261 471.750 1.485638 471.500 1.489768 471.250 1.496841 471.000 1.510198 470.750 1.522041 470.500 1.531030 470.250 1.545328 470.000 1.560172 469.750 1.570888 469.500 1.580139 469.250 1.593152 469.000 1.594805 468.750 1.605464 468.500 1.616219 468.250 1.621754 468.000 1.632535 467.750 1.644631 467.500 1.650524 467.250 1.656282 467.000 1.667263 466.750 1.673635 466.500 1.686621 466.250 1.693873 466.000 1.696128 465.750 1.704764 465.500 1.711756 465.250 1.714948 465.000 1.728853 464.750 1.729348 464.500 1.743019 464.250 1.746787 464.000 1.752885 463.750 1.760666 463.500 1.760704 463.250 1.768180 463.000 1.766523 462.750 1.778626 462.500 1.778225 462.250 1.783692 462.000 1.792741 461.750 1.797693 461.500 1.795760 461.250 1.804503 461.000 1.810953 460.750 1.813487 460.500 1.816123 460.250 1.819425 460.000 1.819624 459.750 1.816466 459.500 1.823444 459.250 1.836482 459.000 1.830087 458.750 1.834800 458.500 1.841166 458.250 1.840140 458.000 1.839459 457.750 1.836853 457.500 1.837930 457.250 1.840912 457.000 1.847599 456.750 1.847373 456.500 1.846104 456.250 1.851409 456.000 1.852811 455.750 1.850807 455.500 1.854914 455.250 1.856802 455.000 1.852359 454.750 1.853096 454.500 1.853795 454.250 1.854348 454.000 1.855929 453.750 1.856634 453.500 1.855813 453.250 1.848005 453.000 1.857326 452.750 1.851605 452.500 1.850387 452.250 1.853856 452.000 1.854881 451.750 1.847421 451.500 1.847991 451.250 1.857937 451.000 1.854583 450.750 1.858615 450.500 1.845350 450.250 1.858381 450.000 1.854062 449.750 1.851552 449.500 1.843309 449.250 1.846660 449.000 1.844071 448.750 1.839074 448.500 1.830719 448.250 1.836334 448.000 1.835399 447.750 1.834972 447.500 1.834846 447.250 1.830959 447.000 1.814837 446.750 1.825482 446.500 1.817394 446.250 1.827438 446.000 1.822202 445.750 1.819161 445.500 1.808851 445.250 1.801431 445.000 1.805995 444.750 1.810186 444.500 1.814813 444.250 1.802981 444.000 1.809521 443.750 1.807120 443.500 1.800821 443.250 1.790042 443.000 1.794777 442.750 1.783619 442.500 1.786601 442.250 1.779207 442.000 1.790295 441.750 1.787355 441.500 1.775297 441.250 1.771944 441.000 1.768527 440.750 1.766404 440.500 1.765948 440.250 1.763506 440.000 1.760175 439.750 1.753914 439.500 1.748948 439.250 1.751297 439.000 1.744780 438.750 1.738644 438.500 1.742462 438.250 1.733294 438.000 1.731909 437.750 1.724946 437.500 1.713200 437.250 1.712755 437.000 1.722690 436.750 1.696102 436.500 1.697120 436.250 1.704847 436.000 1.691638 435.750 1.690900 435.500 1.695534 435.250 1.683187 435.000 1.682039 434.750 1.667432 434.500 1.674124 434.250 1.666470 434.000 1.667341 433.750 1.649206 433.500 1.654528 433.250 1.648213 433.000 1.636745 432.750 1.640029 432.500 1.637619 432.250 1.622890 432.000 1.623684 431.750 1.619482 431.500 1.608657 431.250 1.612524 431.000 1.604380 430.750 1.592960 430.500 1.593769 430.250 1.588738 430.000 1.580874 429.750 1.583372 429.500 1.564663 429.250 1.563121 429.000 1.563412 428.750 1.549781 428.500 1.554880 428.250 1.542450 428.000 1.542101 427.750 1.526977 427.500 1.529820 427.250 1.525953 427.000 1.517332 426.750 1.513895 426.500 1.508433 426.250 1.498621 426.000 1.489842 425.750 1.488509 425.500 1.484847 425.250 1.478670 425.000 1.469083 424.750 1.459923 424.500 1.452635 424.250 1.446755 424.000 1.437943 423.750 1.435912 423.500 1.427282 423.250 1.416570 423.000 1.419523 422.750 1.407179 422.500 1.399733 422.250 1.391979 422.000 1.389844 421.750 1.384139 421.500 1.381486 421.250 1.361263 421.000 1.359125 420.750 1.347285 420.500 1.340171 420.250 1.339171 420.000 1.327270 419.750 1.318870 419.500 1.314066 419.250 1.305208 419.000 1.299636 418.750 1.290758 418.500 1.282128 418.250 1.269650 418.000 1.268674 417.750 1.259497 417.500 1.254514 417.250 1.246204 417.000 1.236159 416.750 1.230592 416.500 1.219814 416.250 1.208552 416.000 1.206094 415.750 1.201313 415.500 1.196249 415.250 1.185113 415.000 1.178991 414.750 1.176668 414.500 1.166433 414.250 1.154901 414.000 1.151682 413.750 1.140955 413.500 1.130924 413.250 1.129338 413.000 1.121470 412.750 1.109495 412.500 1.112846 412.250 1.098981 412.000 1.101536 411.750 1.094811 411.500 1.088235 411.250 1.077106 411.000 1.070724 410.750 1.065664 410.500 1.054043 410.250 1.044583 410.000 1.041445 409.750 1.035140 409.500 1.032585 409.250 1.023565 409.000 1.015033 408.750 1.008563 408.500 1.001095 408.250 0.997377 408.000 0.985273 407.750 0.984415 407.500 0.970997 407.250 0.967440 407.000 0.961576 406.750 0.950522 406.500 0.951770 406.250 0.941268 406.000 0.940969 405.750 0.927263 405.500 0.919785 405.250 0.913934 405.000 0.903149 404.750 0.899691 404.500 0.894056 404.250 0.891572 404.000 0.882521 403.750 0.875929 403.500 0.864006 403.250 0.864889 403.000 0.859166 402.750 0.850735 402.500 0.843364 402.250 0.838488 402.000 0.831549 401.750 0.827026 401.500 0.815881 401.250 0.812708 401.000 0.808612 400.750 0.801094 400.500 0.794788 400.250 0.788117 400.000 0.784465 399.750 0.779231 399.500 0.773893 399.250 0.768103 399.000 0.758542 398.750 0.750166 398.500 0.746501 398.250 0.744711 398.000 0.732846 397.750 0.729293 397.500 0.726528 397.250 0.712691 397.000 0.710217 396.750 0.705656 396.500 0.699080 396.250 0.693714 396.000 0.685906 395.750 0.676197 395.500 0.670175 395.250 0.669454 395.000 0.662164 394.750 0.654837 394.500 0.650481 394.250 0.644421 394.000 0.640018 393.750 0.631024 393.500 0.627066 393.250 0.620201 393.000 0.618361 392.750 0.610644 392.500 0.606236 392.250 0.596042 392.000 0.591400 391.750 0.584576 391.500 0.586497 391.250 0.579418 391.000 0.570761 390.750 0.571627 390.500 0.565790 390.250 0.561336 390.000 0.551768 389.750 0.547165 389.500 0.543238 389.250 0.536130 389.000 0.532471 388.750 0.530376 388.500 0.527796 388.250 0.518375 388.000 0.514024 387.750 0.511162 387.500 0.506842 387.250 0.504771 387.000 0.499727 386.750 0.492431 386.500 0.493567 386.250 0.484988 386.000 0.481181 385.750 0.477143 385.500 0.473275 385.250 0.470359 385.000 0.465429 384.750 0.460725 384.500 0.457158 384.250 0.456887 384.000 0.450583 383.750 0.443172 383.500 0.440244 383.250 0.439282 383.000 0.433423 382.750 0.436229 382.500 0.424293 382.250 0.423676 382.000 0.418072 381.750 0.416187 381.500 0.410521 381.250 0.410703 381.000 0.406220 380.750 0.405959 380.500 0.397956 380.250 0.394971 380.000 0.390174 379.750 0.388047 379.500 0.384419 379.250 0.380012 379.000 0.383473 378.750 0.374935 378.500 0.369261 378.250 0.365915 378.000 0.364646 377.750 0.362120 377.500 0.357627 377.250 0.355601 377.000 0.351923 376.750 0.349981 376.500 0.343197 376.250 0.343363 376.000 0.336080 375.750 0.338200 375.500 0.331339 375.250 0.331295 375.000 0.327159 374.750 0.324800 374.500 0.316912 374.250 0.321584 374.000 0.317157 373.750 0.314394 373.500 0.311933 373.250 0.307991 373.000 0.305850 372.750 0.300357 372.500 0.302398 372.250 0.300119 372.000 0.301788 371.750 0.294374 371.500 0.289817 371.250 0.289715 371.000 0.283722 370.750 0.284413 370.500 0.280980 370.250 0.282786 370.000 0.276642 369.750 0.277362 369.500 0.274303 369.250 0.269527 369.000 0.271239 368.750 0.263047 368.500 0.261197 368.250 0.261002 368.000 0.260707 367.750 0.256858 367.500 0.252833 367.250 0.251443 367.000 0.249702 366.750 0.251339 366.500 0.246414 366.250 0.241847 366.000 0.244070 365.750 0.239116 365.500 0.236174 365.250 0.236369 365.000 0.235509 364.750 0.228521 364.500 0.231901 364.250 0.226640 364.000 0.225582 363.750 0.225079 363.500 0.227058 363.250 0.221091 363.000 0.225328 362.750 0.217849 362.500 0.218292 362.250 0.214232 362.000 0.215715 361.750 0.210092 361.500 0.209317 361.250 0.210199 361.000 0.207231 360.750 0.205099 360.500 0.205093 360.250 0.202446 360.000 0.200532 359.750 0.203341 359.500 0.199270 359.250 0.196662 359.000 0.195995 358.750 0.191428 358.500 0.195964 358.250 0.197531 358.000 0.189168 357.750 0.191085 357.500 0.192020 357.250 0.188696 357.000 0.182438 356.750 0.184706 356.500 0.176496 356.250 0.183932 356.000 0.175004 355.750 0.178355 355.500 0.179858 355.250 0.179899 355.000 0.177043 354.750 0.175541 354.500 0.173554 354.250 0.167817 354.000 0.173603 353.750 0.176040 353.500 0.174166 353.250 0.170477 353.000 0.167256 352.750 0.164269 352.500 0.171244 352.250 0.167618 352.000 0.163031 351.750 0.163608 351.500 0.165996 351.250 0.159724 351.000 0.162176 350.750 0.160044 350.500 0.153497 350.250 0.154399 350.000 0.156709 349.750 0.159592 349.500 0.158326 349.250 0.162303 349.000 0.154231 348.750 0.143696 348.500 0.158352 348.250 0.157700 348.000 0.148508 347.750 0.156349 347.500 0.148151 347.250 0.153139 347.000 0.147673 346.750 0.148098 346.500 0.153938 346.250 0.152076 346.000 0.152298 345.750 0.142747 345.500 0.145213 345.250 0.153900 345.000 0.146978 344.750 0.147138 344.500 0.150859 344.250 0.143783 344.000 0.151068 343.750 0.148105 343.500 0.141355 343.250 0.140875 343.000 0.143040 342.750 0.146450 342.500 0.147139 342.250 0.141078 342.000 0.141793 341.750 0.153308 341.500 0.148057 341.250 0.147297 341.000 0.147653 340.750 0.150010 340.500 0.142927 340.250 0.146266 340.000 0.148453 339.750 0.156465 339.500 0.148291 339.250 0.146827 339.000 0.146956 338.750 0.148063 338.500 0.143521 338.250 0.148606 338.000 0.144162 337.750 0.153081 337.500 0.149483 337.250 0.150997 337.000 0.150044 336.750 0.153076 336.500 0.162385 336.250 0.155170 336.000 0.154031 335.750 0.146523 335.500 0.159546 335.250 0.164967 335.000 0.154491 334.750 0.149409 334.500 0.152782 334.250 0.155691 334.000 0.146996 333.750 0.157165 333.500 0.158794 333.250 0.158724 333.000 0.162895 332.750 0.161968 332.500 0.159997 332.250 0.157223 332.000 0.162192 331.750 0.160337 331.500 0.154666 331.250 0.166325 331.000 0.163170 330.750 0.160672 330.500 0.167714 330.250 0.167915 330.000 0.163880 329.750 0.164373 329.500 0.166254 329.250 0.169905 329.000 0.166488 328.750 0.171528 328.500 0.174559 328.250 0.165377 328.000 0.169938 327.750 0.175941 327.500 0.179443 327.250 0.172176 327.000 0.170810 326.750 0.179400 326.500 0.177425 326.250 0.173978 326.000 0.175459 325.750 0.175955 325.500 0.187965 325.250 0.183506 325.000 0.179989 324.750 0.184163 324.500 0.179882 324.250 0.185322 324.000 0.192224 323.750 0.190439 323.500 0.185054 323.250 0.187270 323.000 0.191856 322.750 0.192442 322.500 0.187779 322.250 0.189883 322.000 0.198279 321.750 0.190099 321.500 0.196479 321.250 0.196946 321.000 0.198823 320.750 0.202542 320.500 0.194340 320.250 0.196445 320.000 0.203024 319.750 0.199329 319.500 0.202523 319.250 0.201017 319.000 0.198086 318.750 0.199690 318.500 0.203814 318.250 0.206346 318.000 0.208664 317.750 0.209464 317.500 0.205052 317.250 0.212960 317.000 0.208087 316.750 0.214934 316.500 0.210078 316.250 0.208640 316.000 0.212058 315.750 0.209844 315.500 0.211461 315.250 0.213439 315.000 0.218150 314.750 0.214387 314.500 0.217037 314.250 0.215708 314.000 0.220565 313.750 0.221578 313.500 0.214118 313.250 0.223177 313.000 0.220233 312.750 0.222263 312.500 0.225229 312.250 0.221214 312.000 0.224047 311.750 0.226373 311.500 0.225933 311.250 0.223556 311.000 0.221582 310.750 0.220336 310.500 0.229840 310.250 0.233339 310.000 0.230065 309.750 0.230394 309.500 0.230573 309.250 0.232903 309.000 0.233199 308.750 0.239265 308.500 0.231477 308.250 0.232984 308.000 0.227587 307.750 0.230493 307.500 0.233081 307.250 0.239346 307.000 0.238054 306.750 0.236219 306.500 0.236882 306.250 0.229527 306.000 0.236100 305.750 0.241625 305.500 0.245136 305.250 0.237689 305.000 0.239350 304.750 0.243502 304.500 0.244706 304.250 0.244038 304.000 0.249938 303.750 0.246604 303.500 0.244041 303.250 0.241025 303.000 0.248219 302.750 0.238866 302.500 0.247556 302.250 0.244228 302.000 0.245991 301.750 0.251647 301.500 0.252827 301.250 0.243687 301.000 0.249091 300.750 0.256465 300.500 0.247661 300.250 0.251606 300.000 0.248964 299.750 0.252268 299.500 0.250951 299.250 0.249106 299.000 0.255694 298.750 0.257666 298.500 0.255988 298.250 0.257628 298.000 0.256609 297.750 0.253869 297.500 0.250451 297.250 0.258887 297.000 0.263199 296.750 0.257040 296.500 0.253775 296.250 0.258138 296.000 0.258213 295.750 0.261633 295.500 0.262931 295.250 0.260412 295.000 0.263835 294.750 0.267593 294.500 0.260730 294.250 0.257485 294.000 0.261625 293.750 0.261443 293.500 0.263428 293.250 0.258649 293.000 0.265758 292.750 0.271056 292.500 0.264563 292.250 0.268447 292.000 0.266045 291.750 0.263747 291.500 0.267238 291.250 0.268309 291.000 0.274134 290.750 0.272555 290.500 0.272974 290.250 0.269241 290.000 0.265992 289.750 0.274277 289.500 0.273740 289.250 0.272384 289.000 0.271253 288.750 0.274891 288.500 0.279346 288.250 0.277111 288.000 0.273747 287.750 0.277344 287.500 0.278157 287.250 0.278262 287.000 0.278972 286.750 0.280832 286.500 0.277159 286.250 0.286144 286.000 0.278156 285.750 0.277891 285.500 0.280443 285.250 0.277367 285.000 0.280821 284.750 0.277663 284.500 0.280531 284.250 0.281540 284.000 0.289916 283.750 0.279915 283.500 0.277901 283.250 0.289338 283.000 0.287156 282.750 0.284366 282.500 0.283675 282.250 0.292629 282.000 0.282890 281.750 0.284116 281.500 0.280611 281.250 0.287628 281.000 0.283177 280.750 0.287964 280.500 0.287014 280.250 0.285804 280.000 0.291663 279.750 0.284617 279.500 0.288047 279.250 0.285506 279.000 0.292081 278.750 0.289202 278.500 0.290395 278.250 0.281847 278.000 0.291420 277.750 0.289075 277.500 0.290129 277.250 0.287856 277.000 0.286223 276.750 0.291591 276.500 0.291828 276.250 0.285657 276.000 0.291369 275.750 0.282416 275.500 0.292265 275.250 0.291572 275.000 0.294789 274.750 0.289152 274.500 0.286162 274.250 0.293733 274.000 0.284931 273.750 0.288638 273.500 0.290369 273.250 0.288736 273.000 0.288824 272.750 0.293727 272.500 0.288399 272.250 0.287643 272.000 0.290198 271.750 0.288596 271.500 0.286238 271.250 0.288016 271.000 0.289589 270.750 0.287425 270.500 0.284982 270.250 0.293242 270.000 0.291171 269.750 0.291055 269.500 0.287614 269.250 0.285780 269.000 0.287755 268.750 0.289843 268.500 0.287788 268.250 0.289634 268.000 0.286127 267.750 0.285383 267.500 0.288344 267.250 0.288631 267.000 0.289175 266.750 0.285403 266.500 0.286425 266.250 0.288959 266.000 0.293827 265.750 0.287069 265.500 0.287558 265.250 0.293491 265.000 0.290901 264.750 0.290559 264.500 0.290980 264.250 0.297674 264.000 0.292210 263.750 0.289555 263.500 0.288041 263.250 0.294963 263.000 0.291411 262.750 0.293384 262.500 0.296503 262.250 0.299751 262.000 0.294547 261.750 0.293179 261.500 0.295129 261.250 0.298605 261.000 0.296387 260.750 0.303467 260.500 0.297811 260.250 0.300513 260.000 0.300330 259.750 0.301772 259.500 0.299348 259.250 0.303467 259.000 0.302518 258.750 0.308689 258.500 0.308930 258.250 0.314558 258.000 0.311470 257.750 0.307254 257.500 0.311549 257.250 0.321780 257.000 0.326667 256.750 0.330390 256.500 0.325364 256.250 0.329821 256.000 0.335945 255.750 0.333252 255.500 0.336778 255.250 0.339673 255.000 0.343333 254.750 0.338764 254.500 0.349499 254.250 0.349318 254.000 0.353904 253.750 0.356977 253.500 0.361135 253.250 0.364462 253.000 0.373863 252.750 0.372712 252.500 0.372288 252.250 0.377149 252.000 0.379380 251.750 0.379883 251.500 0.391014 251.250 0.397669 251.000 0.399963 250.750 0.413173 250.500 0.411242 250.250 0.415035 250.000 0.413945 249.750 0.424185 249.500 0.434087 249.250 0.447793 249.000 0.434247 248.750 0.446772 248.500 0.451104 248.250 0.446940 248.000 0.457072 247.750 0.464649 247.500 0.463968 247.250 0.471274 247.000 0.478035 246.750 0.472998 246.500 0.488234 246.250 0.492785 246.000 0.489170 245.750 0.497396 245.500 0.514458 245.250 0.514914 245.000 0.516976 244.750 0.533890 244.500 0.522568 244.250 0.539249 244.000 0.559919 243.750 0.544205 243.500 0.560541 243.250 0.562978 243.000 0.577710 242.750 0.578995 242.500 0.594804 242.250 0.593923 242.000 0.592221 241.750 0.599145 241.500 0.628855 241.250 0.599058 241.000 0.600732 240.750 0.601622 240.500 0.571203 240.250 0.627491 240.000 0.542981 239.750 0.581265 GDGraph-1.44/samples/sample42.pl0000644000175000001440000000157110347716751015050 0ustar benusersuse GD::Graph::linespoints; require 'save.pl'; print STDERR "Processing sample42\n"; @data = read_data_from_csv("sample42.dat") or die "Cannot read data from sample42.dat"; $my_graph = new GD::Graph::linespoints( ); $my_graph->set( x_label => 'X Label', y_label => 'Y label', title => 'A Lines and Points Graph, reading a CSV file', y_max_value => 80, y_tick_number => 6, y_label_skip => 2, markers => [ 1, 5 ], transparent => 0, ); $my_graph->set_legend( 'data set 1', 'data set 2' ); $my_graph->plot(\@data); save_chart($my_graph, 'sample42'); sub read_data_from_csv { my $fn = shift; my @d = (); open(ZZZ, $fn) || return (); while () { chomp; # you might want Text::CSV here my @row = split /,/; for (my $i = 0; $i <= $#row; $i++) { undef $row[$i] if ($row[$i] eq 'undef'); push @{$d[$i]}, $row[$i]; } } close (ZZZ); return @d; } GDGraph-1.44/samples/sample17.pl0000644000175000001440000000204110347716751015043 0ustar benusersuse strict; use GD::Graph::bars; use GD::Graph::hbars; require 'save.pl'; # Also see sample63 my @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 11, 12, 15, 16, 3, 1.5, 1, 3, 4], [ 5, 12, 24, 15, 19, 8, 6, 15, 21], [ 12, 3, 1, 5, 12, 9, 16, 25, 11], ); my @names = qw/sample17 sample17-h/; for my $my_graph (GD::Graph::bars->new, GD::Graph::hbars->new) { my $name = shift @names; print STDERR "Processing $name\n"; $my_graph->set( x_label => 'X Label', y_label => 'Y label', title => 'Stacked Bars (incremental)', #y_max_value => 50, #y_tick_number => 10, #y_label_skip => 2, cumulate => 1, dclrs => [ undef, qw(dgreen green) ], borderclrs => [ undef, qw(black black) ], bar_spacing => 4, transparent => 0, ); $my_graph->set_legend(undef, qw(low high)); $my_graph->plot(\@data) or die $my_graph->error; save_chart($my_graph, $name); } GDGraph-1.44/t/0000755000175000001440000000000010614025002011632 5ustar benusersGDGraph-1.44/t/images/0000755000175000001440000000000010614025002013077 5ustar benusersGDGraph-1.44/t/images/logo.xbm0000644000175000001440000000631410614014571014564 0ustar benusers#define logo_width 64 #define logo_height 64 static char logo_bits[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFE, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0x07, 0x1F, 0xFE, 0xFF, 0xFF, 0xFF, 0xF1, 0xFF, 0x03, 0x1E, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0xF1, 0x81, 0x06, 0xF7, 0xFF, 0xFF, 0xFF, 0x01, 0x70, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0x00, 0x18, 0x20, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0x00, 0x40, 0x40, 0x00, 0xFC, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x18, 0x00, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0x10, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x83, 0x04, 0x00, 0x04, 0x40, 0xF8, 0xFF, 0xFF, 0x01, 0x40, 0x08, 0x00, 0x80, 0xF8, 0xFF, 0xFF, 0x00, 0x10, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x7F, 0x40, 0x02, 0x01, 0x03, 0xE0, 0xFF, 0xFF, 0x3F, 0x02, 0x40, 0xE8, 0x03, 0xE8, 0xFF, 0xFF, 0x1F, 0x10, 0x08, 0xE0, 0x05, 0xE0, 0xFF, 0xFF, 0x4F, 0x08, 0x12, 0x42, 0x02, 0xC8, 0xFF, 0xFF, 0x07, 0x42, 0x80, 0x10, 0x01, 0xC5, 0xFF, 0xFF, 0x23, 0x48, 0x20, 0x00, 0x40, 0xD4, 0xFF, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x18, 0x83, 0xFF, 0xFF, 0x40, 0x00, 0x00, 0x5B, 0xC4, 0xAA, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0xA4, 0x13, 0x88, 0xFF, 0x3F, 0x04, 0x01, 0x00, 0x40, 0x89, 0x83, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0xA0, 0x35, 0xC8, 0xFF, 0x7F, 0x91, 0x00, 0x00, 0x80, 0xA0, 0xF0, 0xFF, 0x7F, 0x04, 0x00, 0x00, 0x00, 0x8D, 0xFC, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x80, 0xA2, 0xFF, 0xFF, 0xFF, 0x40, 0x01, 0xE0, 0x40, 0xE4, 0xFF, 0xFF, 0x3F, 0x80, 0x56, 0x39, 0x20, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0xA8, 0x17, 0x90, 0x0E, 0xE7, 0xFF, 0x0F, 0x00, 0x5A, 0x2A, 0x20, 0x03, 0xC3, 0xFF, 0x0F, 0x00, 0x80, 0x15, 0xC0, 0x01, 0xE0, 0xFF, 0x1F, 0x10, 0x60, 0x2B, 0x80, 0x01, 0xF8, 0xFF, 0x1F, 0x08, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x3F, 0x00, 0xC0, 0x03, 0x00, 0x00, 0xFC, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0x01, 0x00, 0xC0, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x01, 0x00, 0xC0, 0xFF, 0xFF, 0x21, 0x01, 0xFE, 0x25, 0xE1, 0xC1, 0xFF, 0xFF, 0x03, 0x08, 0xFC, 0x91, 0xF0, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0xF8, 0x07, 0xF8, 0xFF, 0xFF, 0xFF, 0x1F, 0x02, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x10, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xE5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x38, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x78, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }; GDGraph-1.44/t/images/logo_gif_noext0000644000175000001440000000515510614014571016043 0ustar benusersGIF89a@@#0/B ?D 6] 8o RD K\LZnHaVpZ`ipg aw qwTL/R]5]X9Ad$Rp,x/`g6nh7bw7qu5^`FOwLboKddUmjRas]qvU}{Xrvf||fUhgyqT,z,< U niWWonqY,n'n6B,T,l,p+oZ/p/mJq_bRtlrLqOqk  $7)/,(0$2͒˦߾оѺ*   (8910*0000  /,+)(84HZSLRP\ThudlnwzrpԤLFHOWPXJLOQLPkmlonmlmORLOIZlqgwsrΆՊݏЋ̬Ѡв̕ёԌΰвҳ嵼!,@@ H*\ȰÇ#JHŋ3jȱjXy4P]b4 8:qhnѴDy,)ڞ:I6n2m!QE 5OS,*55kfZz)O6qQ+U*4TAߍDqu-Dr1d8E$2&=`9̠Z`( 1d20C!t4F{gƠfR.mlr 2p2/4F'" B1mt $)m &Xx'od8C'xG>B"|}M6 L@& &hr )hW0!|."1IFdeL̓KjI&BhC,4Ђ0AAB<(et OWFfLF"S (`tvpAG[*pѭTF&l8a<JpB #`ۗtp]9Dq̀3ĠdLiuaFTnajpX_m:9H*Ьxtf0C2a>H '>$xD/&" ŠL:x3A3 b=Au~uF4Ȅ#0 OpȐ'A3!pNEp#fSJP P#L Fx#8 ' 1$xTdpN< L@(8@1ۀ!&ABD&0$$P6 WB Po4<fOԂ2#/A v3+h4P`p5 ?(jaQ& ֙D`(( b CYe|D, R 3A Bh!3_8D <V1QhnЄLđ 06$ L C&6 LRP*rAG8"QC-@g$#Laf @oT81<et_rRk.c:p, R}AWR%\ظ[,[.?,Cج*UnB/UkV;#d7aT(>TyGϤ٠vXյ!MbYm&T7D `01pۈ=7f9R [*xJH3e[(pu`ڒ6Fz?X[K띞62h`*"OkEO1PIt^l (}.o9|/FyX~^pؔu+{*J4]V )6ƑjY$DEf7-XI;cn,[5D e\0z0Z"@+PYaJf! "f"س|QcvM`q p9.N1on5v.iI\mEE7b;-@}U9PwJ|FmIuZiz̥ڷ"+YsJ_j_J^Rn[mNv[*]zj{ 8&ŗ?ˡm>5X+XjWUU(tVەҪ$Vv0s7TO|ʾO7Atoz[G%^\)iT) OjN8;ؚ^k \q>Xo,F םd1Dxs1_x(<fe[(瞋ǽG=s]V 0_Vv!#<m &x!וͫQu: k@v)9TԼ;*/%W\6T5!b v4=j:LWMس8 vX4s7 NGD12RGYᯔ^e׶~o3l^wk-T9[qM5!#ϑӒzL_Qoyߐ5mB`EU1]SpDnIFטUf)&cBhMYR$̧/'^9ʩZUjOo,,ZfRjUԼiz[l6>w ^?x'rנnM7jִC>Wy RΥزTV#:Ho<M_&vjmQ|JQ9Aky’*[~cV%% (:E +,K 8,RPe?~N񼘼_ar<+vY+XZM2Q?N3ɭ*nvN"MM~}0j!&!>CQ-}JұK:K+n+*rbT'Ǒj52䠑)s b7BIJl'W-x5ί[-rPayٜ<ҭVh 7, x|F |m vtԳoso#&2-gf ~d.Yc+ڍr SD\* \Xy+>=R}3tz=&q5,TjUA厛822)ZXXYa8 H2Oޫ?デ:WsrKpڹa[XDQ6D #Zj5yZR"dKKƭi~k_4]*`l-r0-a _( ^]uv&bk '?9^X!UQpPU_?miÒFG/ ,&y}-\UZ ,0C <{XFX?83Kgգ#Uaq2 d+ʡa9ĭ͖K ׳,Hkh_z=Dz^GDGraph-1.44/t/images/logo.gif0000644000175000001440000000515510614014571014545 0ustar benusersGIF89a@@#0/B ?D 6] 8o RD K\LZnHaVpZ`ipg aw qwTL/R]5]X9Ad$Rp,x/`g6nh7bw7qu5^`FOwLboKddUmjRas]qvU}{Xrvf||fUhgyqT,z,< U niWWonqY,n'n6B,T,l,p+oZ/p/mJq_bRtlrLqOqk  $7)/,(0$2͒˦߾оѺ*   (8910*0000  /,+)(84HZSLRP\ThudlnwzrpԤLFHOWPXJLOQLPkmlonmlmORLOIZlqgwsrΆՊݏЋ̬Ѡв̕ёԌΰвҳ嵼!,@@ H*\ȰÇ#JHŋ3jȱjXy4P]b4 8:qhnѴDy,)ڞ:I6n2m!QE 5OS,*55kfZz)O6qQ+U*4TAߍDqu-Dr1d8E$2&=`9̠Z`( 1d20C!t4F{gƠfR.mlr 2p2/4F'" B1mt $)m &Xx'od8C'xG>B"|}M6 L@& &hr )hW0!|."1IFdeL̓KjI&BhC,4Ђ0AAB<(et OWFfLF"S (`tvpAG[*pѭTF&l8a<JpB #`ۗtp]9Dq̀3ĠdLiuaFTnajpX_m:9H*Ьxtf0C2a>H '>$xD/&" ŠL:x3A3 b=Au~uF4Ȅ#0 OpȐ'A3!pNEp#fSJP P#L Fx#8 ' 1$xTdpN< L@(8@1ۀ!&ABD&0$$P6 WB Po4<fOԂ2#/A v3+h4P`p5 ?(jaQ& ֙D`(( b CYe|D, R 3A Bh!3_8D <V1QhnЄLđ 06$ L C&6 LRP*rAG8"QC-@g$#Laf @oT81<et_rRk.c:p, R}AWR%\ظ[,[.?,Cج*UnB/UkV;#d7aT(>TyGϤ٠vXյ!MbYm&T7D `01pۈ=7f9R [*xJH3e[(pu`ڒ6Fz?X[K띞62h`*"OkEO1PIt^l (}.o9|/FyX~^pؔu+{*J4]V )6ƑjY$DEf7-XI;cn,[5D e\0z0Z"@+PYaJf! "f"س|QcvM`q p9.N1on5v.iI\mEE7b;-@}U9PwJ|FmIuZiz̥ڷ"+YsJ_j_J^Rn[mNv[*]zj{ 8&ŗ?ˡm>5X+XjWUU(tVەҪ$Vv0s7TO|ʾO7Atoz[G%^\)iT) OjN8;ؚ^k \q>Xo,F םd1Dxs1_x(<fe[(瞋ǽG=s]V 0_Vv!#<m &x!וͫQu: k@v)9TԼ;*/%W\6T5!b v4=j:LWMس8 vX4s7 NGD12RGYᯔ^e׶~o3l^wk-T9[qM5!#ϑӒzL_Qoyߐ5mB`EU1]SpDnIFטUf)&cBhMYR$̧/'^9ʩZUjOo,,ZfRjUԼiz[l6>w ^?x'rנnM7jִC>Wy RΥزTV#:Ho<M_&vjmQ|JQ9Aky’*[~cV%% (:E +,K 8,RPe?~N񼘼_ar<+vY+XZM2Q?N3ɭ*nvN"MM~}0j!&!>CQ-}JұK:K+n+*rbT'Ǒj52䠑)s b7BIJl'W-x5ί[-rPayٜ<ҭVh 7, x|F |m vtԳoso#&2-gf ~d.Yc+ڍr SD\* \Xy+>=R}3tz=&q5,TjUA厛822)ZXXYa8 H2Oޫ?デ:WsrKpڹa[XDQ6D #Zj5yZR"dKKƭi~k_4]*`l-r0-a _( ^]uv&bk '?9^X!UQpPU_?miÒFG/ ,&y}-\UZ ,0C <{XFX?83Kgգ#Uaq2 d+ʡa9ĭ͖K ׳,Hkh_z=Dz^GDGraph-1.44/t/images/logo_ping_noext0000644000175000001440000000555710614014571016241 0ustar benusersPNG  IHDR@@PLTE#0g < PmJоĬnqL^`FaVbRp+OS͒tln'L̗00`iՊoѺ*6] (gԂF(嵅mjR`g6nAd$裔)0HಅH( ΰQlK\srvf+h̬$$WIhkopz,p/2Ћ}{Xx/q]X9OLolԤLܬ808MslB,OwLqOu?D r T߾̈́W0XԌ)UTL/U gY̕qRY,/B ˦l,L/boK\/Rp,,țZ/T,O ѠWnHpg Άnh7dq_lT,8o lrLROɨm尼R]5вLmr||f4в0ynҳRD ёDas]P 1aw qvUbw7m *ﯪPwnJ,pZqwݏqu5ziddUqkn6w8Z9LZ7ZnuCEtRNSS%bKGDtEXtSoftwaregif2png 0.6 (beta)iIDATxql+b'Kΐ. /u9i!wNlp64o(L>e88nXqiXu:Rː౤A`d &XW3U2guO~ݽ{Ͻ{~i}jX0xv?{{wG}ȅKdz~݅܀+_6&)ʚ~\k6&?`صvlnTz&rzŵ'|C%{v8]F 1H@@tXW\~oO?}fT)#K`n>6J,~KmT]}R2n@0f!Dzb0sjOm u3h⾾h4/ƹ/.xO $ g)?ٹs}xN@,N  ˢ Y ou[PP=&[ߟsJقA@i/4˨~L0 ܄M! оݷz:'}X44FN4ؽ_`lp=]D ,{LH`([bK#* 7Գ@aK A4*GNhd.@L@JF0&\Ui7):&}Kҟ 22/e!pt:d/WMNOSW]HRСt)ſϽNtANwRv]ofZ-D'V H#OHP;^3ukÀ-bh P:}.=rCNkљTmhɬiQ(Y Ɓɷ=uÇ*NʤRf#FITL(^CiH-yرJ94oڸpcnfDf-S i.nh^g*E&0~W1;Ba Fm}[:fHWHi ӱ_Q-Y2NgNe2B\x 7Dd4]ۨ)=Y5q-3z}f-N"<JZ(zk?}gTnԄFFF&6ܖI$3-WCR)1:poMzo>;ZRҰJgV;e||)`IQ/cGtӒH~_R <[ߏFp|޳K5I O4 AA3-&,5` Ju{+c* tUĄ)(?oڣ}|+Vc>é[ ԦZzYb+9:IfȨ}q<ؙ+?"N9t$kk킀 nZ/`Je L-d2xHOdœ->;4&6 yedjP99NBǪ}=sWQ4CRidB39=Www0 BSRKl?gR!Rxʍ!C<`dr(h$/ Sg4딆oܱ*u♿Y.ݐv,@v{ڕhPW|@n7ЮrjpZ,e]!rT_n;ot$qcN\H=G|;0?+oJx0IENDB`GDGraph-1.44/t/images/logo.xpm0000644000175000001440000002762610614014571014613 0ustar benusers/* XPM */ static char *logo[] = { /* columns rows colors chars-per-pixel */ "64 64 227 2", " c #233004", ". c #2F420A", "X c #3F440A", "o c #365D09", "O c #386F0C", "+ c #524409", "@ c #4B5C07", "# c #4C5A15", "$ c #6E4808", "% c #615605", "& c #705A08", "* c #606908", "= c #70670D", "- c #617709", "; c #717707", ": c #544C2F", "> c #525D35", ", c #5D5839", "< c #416424", "1 c #52702C", "2 c #7F782F", "3 c #606736", "4 c #6E6837", "5 c #627737", "6 c #717535", "7 c #5E6046", "8 c #4F774C", "9 c #626F4B", "0 c #646455", "q c #6D6A52", "w c #61735D", "e c #717655", "r c #7D7B58", "t c #727666", "y c #7C7C66", "u c #805505", "i c #886806", "p c #986706", "a c #847907", "s c #9B7F06", "d c #B17107", "f c #84542C", "g c #A27A2C", "h c #3C890C", "j c #558A0D", "k c #6E8D07", "l c #698A1B", "z c #57A10F", "x c #57BC11", "c c #6FA506", "v c #6EA618", "b c #71B915", "n c #59892C", "m c #6E8F27", "M c #6E8A36", "N c #42A02C", "B c #54A42C", "V c #6CA72C", "C c #70B92B", "Z c #6FC518", "A c #5AC02F", "S c #70C62F", "D c #6D884A", "F c #71855F", "G c #62BE52", "H c #74BC6C", "J c #72C14C", "K c #71CC4F", "L c #71D16B", "P c #808000", "I c #858B06", "U c #9C9405", "Y c #9A9419", "T c #B58105", "R c #B59305", "E c #B69A18", "W c #84A406", "Q c #9BA808", "! c #82BC08", "~ c #97B90B", "^ c #80A819", "/ c #80BD19", "( c #B5A90A", ") c #A9BB07", "_ c #BEBA08", "` c #868E24", "' c #848937", "] c #A39429", "[ c #83AA2F", "{ c #9FA92C", "} c #80BE28", "| c #97BA30", " . c #B7B724", ".. c #A7BA32", "X. c #CD9206", "o. c #CBA607", "O. c #DFBE07", "+. c #D0BE08", "@. c #E1A605", "#. c #D1BA2A", "$. c #98C80C", "%. c #86CD15", "&. c #99D611", "*. c #A8CA0A", "=. c #BCC806", "-. c #A8D90B", ";. c #B9DA05", ":. c #BADE17", ">. c #85CE28", ",. c #81C038", "<. c #85CF39", "1. c #97C931", "2. c #98D730", "3. c #A7C92A", "4. c #BBC830", "5. c #A8DB30", "6. c #BBD930", "7. c #BDE530", "8. c #D1CF0B", "9. c #DECF09", "0. c #D6DE07", "q. c #EFC208", "w. c #EFCF09", "e. c #D8E219", "r. c #E7E107", "t. c yellow", "y. c #E8E419", "u. c #D1D22F", "i. c #DFD12C", "p. c #E6DF2B", "a. c #F6D129", "s. c #D7E228", "d. c #D7E638", "f. c #EAED34", "g. c #808948", "h. c #80875A", "j. c #959A53", "k. c #85A64C", "l. c #9AA952", "z. c #96BA50", "x. c #B4A45C", "c. c #A7B954", "v. c #838968", "b. c #979975", "n. c #AC9464", "m. c #87A16C", "M. c #9AB96E", "N. c #9AA777", "B. c #A6A77A", "V. c #A9B772", "C. c #B8B870", "Z. c #D4A44C", "A. c #82C146", "S. c #85CF48", "D. c #98D94F", "F. c #84C157", "G. c #97C950", "H. c #85D158", "J. c #A5CB4A", "K. c #BAC44C", "L. c #A8DB4F", "P. c #BED751", "I. c #BAE64C", "U. c #AAE450", "Y. c #88C16B", "T. c #97C86D", "R. c #88D46C", "E. c #96DA6F", "W. c #BCC66E", "Q. c #A8DD6D", "!. c #BCD86C", "~. c #BDE76D", "^. c #D5D74F", "/. c #E5DA52", "(. c #D1EA4C", "). c #E0EA4F", "_. c #F1EE49", "`. c #EEEE5A", "'. c #D6D56C", "]. c #E7D771", "[. c #D6EC67", "{. c #D8EC77", "}. c #E8E973", "|. c #EBF572", " X c #808080", ".X c #9AA696", "XX c #AFB088", "oX c #A0BB8F", "OX c #AFB29A", "+X c #B5BE92", "@X c #B6BFAA", "#X c #98CE86", "$X c #8AD58A", "%X c #98DD8F", "&X c #B5D08B", "*X c #A4CCAC", "=X c #B9D1A0", "-X c #BAD0B2", ";X c #B7E4A4", ":X c #C7CC95", ">X c #D9D191", ",X c #ECD48C", ".>.<.S.| i ` gXgX0XJ.) U 1XgXgXgXtXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX~.;.s.5X3X3X}.d.e.[._.gXgXgXaX8XG./ } J.G.F.I l {.Q.Q.=._ +.8.>X>Xd.d.d.gXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXrXI.e.(.eX5X[.0.0.p.|.gXgXaX:X1.S %./ b / C / b W ;.*.=.;.8.+.+.9.w.+.s.{.gXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX0X2X~.I.s.s.i.i.4XfXfX8XW.A.~ } ,.[ b C C C A C b _ o.o.O.O.@.O.).3XgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXaXI.5.Q.5.8.9._ 6.L.5.| %.} } / S [ } C S Z } <.Z / / o.O.O.O.O.s.gXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXaXV.c.%.6.2...) $./ } C / C ~ } C | C / b / } Z S / x Z %.<.+.w.w.9.9.gXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXqXH.Y.3.~ / / / / C / C / b / } b / } } / ! ! } S S <.S S S S A.Y . .#.a.6XgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXaXoX,.,.[ ^ } [ V / C S ,.,.S S A.>.,.[ / ,.,./ ! S <.K H.$X$XE.E.S.k.r e +X}.w.f.gXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXaXF.} C / } C / } b / S ,./ S >.b >./ / 3. .O.X.Y ! Z 2.S.L Q.D.Q.D.K | =X>XgXaX).).gXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXpXA.C C [ C V ,.^ C / } } C } / S / } %.{ o.w.q.@.X.I Z R.R.R.%X%X$XH.S.c.gXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgX7X,./ C / v / b } ! v b / C C } ,.! Z } / o.q.E f + s b ,.R.R.%X%X%XR.,.V.gXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgX+Xk./ V C v A / A ,.C C } A [ S ^ ,.b ! } W X.+ . a } <.K R.E.E.E.J m N.gXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgX@X,./ } / / b b C / b b ,.C b / } v } v ! W c X.+ . I P S <.K S.S.1.~ l D m.gXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgX:X$.! ^ / ^ } C C } } A.S A.A.J V b } v C V } V I E d g.g d c S.K $XK >.v 6 v.q v.8XgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgX=X>.$./ C V c ^ C | A / S.S A.G ,.F.V / v v G.K #Xn k & = + h <.H.H.Q.1.l.7 r y 9 v.XXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgX:X,.$.! / ^ b ^ } / S } S S.S ,.G F.A.[ ! ^ c J.1.S.<.B B N A H.D.J.3.{ D F r t y e t m.gXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXsXXX} %./ b / b b W } %.%./ A.G ,.C C ,.A.} ! c ! &.U.D.E.Y.F.D.G.1.] k 1 r y t e q Xy y t =XgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXM.1.%./ %.b b A } >./ } S.<.S S H.J F.S.J } A %.j - ; = # a k I j.= # 8 7 v.t q t , t r q h.b.gXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXL.%.$.! ^ ! ! ! ! ! %.} %.S &.S S <.<.S ,.,.,.} / W c = & $ u $ + @ o 5 q e q y e e 0 q q r t C.gXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgX~.2.$.$.! } b ! Z ! ! Z ! %.<.2.2.<.2.S.<.>.S.>.! $.$.=.R d s p u u @ e q q t e y e t e e r h.r tXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgX0X&.3.b [ W b c Z ! ! &.$.Z 2.&.2.7.%.&.<.S.<.$.&.;.;.+.O.O.+.R d % 4 v.q t e 0 y q 7 t , v.b.8XgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXQ./ W c c c ! ! ! ! &.&.-.&.&.-.;.;.-.5.&.-.-.;.;.=.+.t.}.w.@.s 6 t q e e t q y e F e b.+XgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXM./ ! c k W ! $.! $.-.;.*.*.&.=.;.-.;.-.;.-.-.) _ +.w.t.a.@.X.2 q q q q e t r e h.b.pXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXuXV &.-.W U W W ~ ! *.$.-.~ $.=.;.;.8.) _ ~ Q U = s r.|.a.X.s 9 r e , h.0 v.v.+XgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXE.*.-.;.R R s I W U U ) Q I ~ _ _ ) U I ; % o 1 K.e./.@.T g.q e r e q h.+XgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXW.Q.G.$.;.;.;.o.s s s i i s s s a a i a & + o # 7 j.d.d.@.U D 0 q 9 g.N.8XgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXI.D.<.H.D.$.;.*.;.=.T d p i & * & % @ X X X < > > 9 W.(.(.R g.3 7 v.' 8XgXgXgXsX].y.p.gXgXgX6X6XgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgX2X7.H.S.S.S.<.2.&.*.=.( X.d a 3 t 7 > 7 7 7 7 7 , 7 n.(.[.:.=.2 9 3 v.wXgXgXaX,Xy.9.9.p.gXgX].r.r.|.gXgXgXgXgXgXgXgXgXgX", "gXgXgXgXqX:.5.<.S.J >.S.,.1.&.=._ o.T 6 4 e q q 7 > 7 0 , 9 '.I.U.5.U.5./ j.gXgXgX9X#.q.9.O.'.}.d.e.r.s.`.gXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXV.&.>.} J ,.<.G G.S -.*.=.o.U 9 y 3 7 e : e > 3 D ~.U.U.2.H.D.<.D.[.gXgX,XO.q.9.9.O.9.w.s.rXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXyXA.%.>.K } J F.F.H.A.2.;.;.( R W..XB.b.v.e , 9 3 z.2.5.U.D.E.Q.E.D.5.{.+.O.0.0.i.O.O.O.rXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgX@X1.%./ b J A.<.F.A.Y.3.&.-.=. .gXgXgXgXaXqXqX7X:X;XQ.1.2.<.D.H.D.D.2.&.*.;.5.7.:.8.8.O.gXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXOX>.&.Z / %.A } S K A.} -.-.*.#.gXgXgXgXgXgXgXgXgXgXoX/ &.<.2.D.D.2.D.5.U.Q.5.1.:.:.:.d.).|.6XgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgX@Xz.&.b / ,.A.,.F.J F.G.3.:.;.u.gXgXgXgXgXgXgXgXgXuX8 l v C 3.$.>.<.H.Y.[ k.&XL.5.~.[.(.2X).gXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgX-XM.3./ } C F.S J J F.H.1.:.:.d.gXgXgXgXgXgXgXgX.Xq w w 8 5 V k.M V D B.gXgXgXgXeXeX{.5X{.gXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXdXN.,.[ / Z / A A.A.K S.2.:.:.s.gXgXgXgXgXgXgX@Xv.y y 0 h.w e v.e 7XgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXdX*XF.V b / ,.G S.G F.H D.5.7.`.gXgXgXgXgXgXgXgXwX-X+XOXXXOX:XaXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgX7XE.H [ b ,.G S.F.A.H.L.5.7.gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXiXG.H.V l c ,.J ,.S.S.5.~ tXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgX@Xm.R.k.l j v ,.H.D.G.P R a.p._.rXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXiX&XT.,.z h b V - ; U 8.a._.6XgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX-X!.%.h o O W _ s.gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX7X~.&.c W ;.;.8.rXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXqX&.;.+.+.=.0.y.5XgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX~.d.;.8.4.d.e.e./.5XgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX6.u.|.gXgXgX^.7.:.6XgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX{.6.`.gXgXgXgX2X2XgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXtXe88nXqiXu:Rː౤A`d &XW3U2guO~ݽ{Ͻ{~i}jX0xv?{{wG}ȅKdz~݅܀+_6&)ʚ~\k6&?`صvlnTz&rzŵ'|C%{v8]F 1H@@tXW\~oO?}fT)#K`n>6J,~KmT]}R2n@0f!Dzb0sjOm u3h⾾h4/ƹ/.xO $ g)?ٹs}xN@,N  ˢ Y ou[PP=&[ߟsJقA@i/4˨~L0 ܄M! оݷz:'}X44FN4ؽ_`lp=]D ,{LH`([bK#* 7Գ@aK A4*GNhd.@L@JF0&\Ui7):&}Kҟ 22/e!pt:d/WMNOSW]HRСt)ſϽNtANwRv]ofZ-D'V H#OHP;^3ukÀ-bh P:}.=rCNkљTmhɬiQ(Y Ɓɷ=uÇ*NʤRf#FITL(^CiH-yرJ94oڸpcnfDf-S i.nh^g*E&0~W1;Ba Fm}[:fHWHi ӱ_Q-Y2NgNe2B\x 7Dd4]ۨ)=Y5q-3z}f-N"<JZ(zk?}gTnԄFFF&6ܖI$3-WCR)1:poMzo>;ZRҰJgV;e||)`IQ/cGtӒH~_R <[ߏFp|޳K5I O4 AA3-&,5` Ju{+c* tUĄ)(?oڣ}|+Vc>é[ ԦZzYb+9:IfȨ}q<ؙ+?"N9t$kk킀 nZ/`Je L-d2xHOdœ->;4&6 yedjP99NBǪ}=sWQ4CRidB39=Www0 BSRKl?gR!Rxʍ!C<`dr(h$/ Sg4딆oܱ*u♿Y.ݐv,@v{ڕhPW|@n7ЮrjpZ,e]!rT_n;ot$qcN\H=G|;0?+oJx0IENDB`GDGraph-1.44/t/images/logo_xpm_noext0000644000175000001440000002762610614014571016111 0ustar benusers/* XPM */ static char *logo[] = { /* columns rows colors chars-per-pixel */ "64 64 227 2", " c #233004", ". c #2F420A", "X c #3F440A", "o c #365D09", "O c #386F0C", "+ c #524409", "@ c #4B5C07", "# c #4C5A15", "$ c #6E4808", "% c #615605", "& c #705A08", "* c #606908", "= c #70670D", "- c #617709", "; c #717707", ": c #544C2F", "> c #525D35", ", c #5D5839", "< c #416424", "1 c #52702C", "2 c #7F782F", "3 c #606736", "4 c #6E6837", "5 c #627737", "6 c #717535", "7 c #5E6046", "8 c #4F774C", "9 c #626F4B", "0 c #646455", "q c #6D6A52", "w c #61735D", "e c #717655", "r c #7D7B58", "t c #727666", "y c #7C7C66", "u c #805505", "i c #886806", "p c #986706", "a c #847907", "s c #9B7F06", "d c #B17107", "f c #84542C", "g c #A27A2C", "h c #3C890C", "j c #558A0D", "k c #6E8D07", "l c #698A1B", "z c #57A10F", "x c #57BC11", "c c #6FA506", "v c #6EA618", "b c #71B915", "n c #59892C", "m c #6E8F27", "M c #6E8A36", "N c #42A02C", "B c #54A42C", "V c #6CA72C", "C c #70B92B", "Z c #6FC518", "A c #5AC02F", "S c #70C62F", "D c #6D884A", "F c #71855F", "G c #62BE52", "H c #74BC6C", "J c #72C14C", "K c #71CC4F", "L c #71D16B", "P c #808000", "I c #858B06", "U c #9C9405", "Y c #9A9419", "T c #B58105", "R c #B59305", "E c #B69A18", "W c #84A406", "Q c #9BA808", "! c #82BC08", "~ c #97B90B", "^ c #80A819", "/ c #80BD19", "( c #B5A90A", ") c #A9BB07", "_ c #BEBA08", "` c #868E24", "' c #848937", "] c #A39429", "[ c #83AA2F", "{ c #9FA92C", "} c #80BE28", "| c #97BA30", " . c #B7B724", ".. c #A7BA32", "X. c #CD9206", "o. c #CBA607", "O. c #DFBE07", "+. c #D0BE08", "@. c #E1A605", "#. c #D1BA2A", "$. c #98C80C", "%. c #86CD15", "&. c #99D611", "*. c #A8CA0A", "=. c #BCC806", "-. c #A8D90B", ";. c #B9DA05", ":. c #BADE17", ">. c #85CE28", ",. c #81C038", "<. c #85CF39", "1. c #97C931", "2. c #98D730", "3. c #A7C92A", "4. c #BBC830", "5. c #A8DB30", "6. c #BBD930", "7. c #BDE530", "8. c #D1CF0B", "9. c #DECF09", "0. c #D6DE07", "q. c #EFC208", "w. c #EFCF09", "e. c #D8E219", "r. c #E7E107", "t. c yellow", "y. c #E8E419", "u. c #D1D22F", "i. c #DFD12C", "p. c #E6DF2B", "a. c #F6D129", "s. c #D7E228", "d. c #D7E638", "f. c #EAED34", "g. c #808948", "h. c #80875A", "j. c #959A53", "k. c #85A64C", "l. c #9AA952", "z. c #96BA50", "x. c #B4A45C", "c. c #A7B954", "v. c #838968", "b. c #979975", "n. c #AC9464", "m. c #87A16C", "M. c #9AB96E", "N. c #9AA777", "B. c #A6A77A", "V. c #A9B772", "C. c #B8B870", "Z. c #D4A44C", "A. c #82C146", "S. c #85CF48", "D. c #98D94F", "F. c #84C157", "G. c #97C950", "H. c #85D158", "J. c #A5CB4A", "K. c #BAC44C", "L. c #A8DB4F", "P. c #BED751", "I. c #BAE64C", "U. c #AAE450", "Y. c #88C16B", "T. c #97C86D", "R. c #88D46C", "E. c #96DA6F", "W. c #BCC66E", "Q. c #A8DD6D", "!. c #BCD86C", "~. c #BDE76D", "^. c #D5D74F", "/. c #E5DA52", "(. c #D1EA4C", "). c #E0EA4F", "_. c #F1EE49", "`. c #EEEE5A", "'. c #D6D56C", "]. c #E7D771", "[. c #D6EC67", "{. c #D8EC77", "}. c #E8E973", "|. c #EBF572", " X c #808080", ".X c #9AA696", "XX c #AFB088", "oX c #A0BB8F", "OX c #AFB29A", "+X c #B5BE92", "@X c #B6BFAA", "#X c #98CE86", "$X c #8AD58A", "%X c #98DD8F", "&X c #B5D08B", "*X c #A4CCAC", "=X c #B9D1A0", "-X c #BAD0B2", ";X c #B7E4A4", ":X c #C7CC95", ">X c #D9D191", ",X c #ECD48C", ".>.<.S.| i ` gXgX0XJ.) U 1XgXgXgXtXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX~.;.s.5X3X3X}.d.e.[._.gXgXgXaX8XG./ } J.G.F.I l {.Q.Q.=._ +.8.>X>Xd.d.d.gXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXrXI.e.(.eX5X[.0.0.p.|.gXgXaX:X1.S %./ b / C / b W ;.*.=.;.8.+.+.9.w.+.s.{.gXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX0X2X~.I.s.s.i.i.4XfXfX8XW.A.~ } ,.[ b C C C A C b _ o.o.O.O.@.O.).3XgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXaXI.5.Q.5.8.9._ 6.L.5.| %.} } / S [ } C S Z } <.Z / / o.O.O.O.O.s.gXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXaXV.c.%.6.2...) $./ } C / C ~ } C | C / b / } Z S / x Z %.<.+.w.w.9.9.gXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXqXH.Y.3.~ / / / / C / C / b / } b / } } / ! ! } S S <.S S S S A.Y . .#.a.6XgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXaXoX,.,.[ ^ } [ V / C S ,.,.S S A.>.,.[ / ,.,./ ! S <.K H.$X$XE.E.S.k.r e +X}.w.f.gXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXaXF.} C / } C / } b / S ,./ S >.b >./ / 3. .O.X.Y ! Z 2.S.L Q.D.Q.D.K | =X>XgXaX).).gXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXpXA.C C [ C V ,.^ C / } } C } / S / } %.{ o.w.q.@.X.I Z R.R.R.%X%X$XH.S.c.gXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgX7X,./ C / v / b } ! v b / C C } ,.! Z } / o.q.E f + s b ,.R.R.%X%X%XR.,.V.gXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgX+Xk./ V C v A / A ,.C C } A [ S ^ ,.b ! } W X.+ . a } <.K R.E.E.E.J m N.gXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgX@X,./ } / / b b C / b b ,.C b / } v } v ! W c X.+ . I P S <.K S.S.1.~ l D m.gXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgX:X$.! ^ / ^ } C C } } A.S A.A.J V b } v C V } V I E d g.g d c S.K $XK >.v 6 v.q v.8XgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgX=X>.$./ C V c ^ C | A / S.S A.G ,.F.V / v v G.K #Xn k & = + h <.H.H.Q.1.l.7 r y 9 v.XXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgX:X,.$.! / ^ b ^ } / S } S S.S ,.G F.A.[ ! ^ c J.1.S.<.B B N A H.D.J.3.{ D F r t y e t m.gXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXsXXX} %./ b / b b W } %.%./ A.G ,.C C ,.A.} ! c ! &.U.D.E.Y.F.D.G.1.] k 1 r y t e q Xy y t =XgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXM.1.%./ %.b b A } >./ } S.<.S S H.J F.S.J } A %.j - ; = # a k I j.= # 8 7 v.t q t , t r q h.b.gXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXL.%.$.! ^ ! ! ! ! ! %.} %.S &.S S <.<.S ,.,.,.} / W c = & $ u $ + @ o 5 q e q y e e 0 q q r t C.gXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgX~.2.$.$.! } b ! Z ! ! Z ! %.<.2.2.<.2.S.<.>.S.>.! $.$.=.R d s p u u @ e q q t e y e t e e r h.r tXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgX0X&.3.b [ W b c Z ! ! &.$.Z 2.&.2.7.%.&.<.S.<.$.&.;.;.+.O.O.+.R d % 4 v.q t e 0 y q 7 t , v.b.8XgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXQ./ W c c c ! ! ! ! &.&.-.&.&.-.;.;.-.5.&.-.-.;.;.=.+.t.}.w.@.s 6 t q e e t q y e F e b.+XgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXM./ ! c k W ! $.! $.-.;.*.*.&.=.;.-.;.-.;.-.-.) _ +.w.t.a.@.X.2 q q q q e t r e h.b.pXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXuXV &.-.W U W W ~ ! *.$.-.~ $.=.;.;.8.) _ ~ Q U = s r.|.a.X.s 9 r e , h.0 v.v.+XgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXE.*.-.;.R R s I W U U ) Q I ~ _ _ ) U I ; % o 1 K.e./.@.T g.q e r e q h.+XgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXW.Q.G.$.;.;.;.o.s s s i i s s s a a i a & + o # 7 j.d.d.@.U D 0 q 9 g.N.8XgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXI.D.<.H.D.$.;.*.;.=.T d p i & * & % @ X X X < > > 9 W.(.(.R g.3 7 v.' 8XgXgXgXsX].y.p.gXgXgX6X6XgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgX2X7.H.S.S.S.<.2.&.*.=.( X.d a 3 t 7 > 7 7 7 7 7 , 7 n.(.[.:.=.2 9 3 v.wXgXgXaX,Xy.9.9.p.gXgX].r.r.|.gXgXgXgXgXgXgXgXgXgX", "gXgXgXgXqX:.5.<.S.J >.S.,.1.&.=._ o.T 6 4 e q q 7 > 7 0 , 9 '.I.U.5.U.5./ j.gXgXgX9X#.q.9.O.'.}.d.e.r.s.`.gXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXV.&.>.} J ,.<.G G.S -.*.=.o.U 9 y 3 7 e : e > 3 D ~.U.U.2.H.D.<.D.[.gXgX,XO.q.9.9.O.9.w.s.rXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXyXA.%.>.K } J F.F.H.A.2.;.;.( R W..XB.b.v.e , 9 3 z.2.5.U.D.E.Q.E.D.5.{.+.O.0.0.i.O.O.O.rXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgX@X1.%./ b J A.<.F.A.Y.3.&.-.=. .gXgXgXgXaXqXqX7X:X;XQ.1.2.<.D.H.D.D.2.&.*.;.5.7.:.8.8.O.gXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXOX>.&.Z / %.A } S K A.} -.-.*.#.gXgXgXgXgXgXgXgXgXgXoX/ &.<.2.D.D.2.D.5.U.Q.5.1.:.:.:.d.).|.6XgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgX@Xz.&.b / ,.A.,.F.J F.G.3.:.;.u.gXgXgXgXgXgXgXgXgXuX8 l v C 3.$.>.<.H.Y.[ k.&XL.5.~.[.(.2X).gXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgX-XM.3./ } C F.S J J F.H.1.:.:.d.gXgXgXgXgXgXgXgX.Xq w w 8 5 V k.M V D B.gXgXgXgXeXeX{.5X{.gXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXdXN.,.[ / Z / A A.A.K S.2.:.:.s.gXgXgXgXgXgXgX@Xv.y y 0 h.w e v.e 7XgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXdX*XF.V b / ,.G S.G F.H D.5.7.`.gXgXgXgXgXgXgXgXwX-X+XOXXXOX:XaXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgX7XE.H [ b ,.G S.F.A.H.L.5.7.gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXiXG.H.V l c ,.J ,.S.S.5.~ tXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgX@Xm.R.k.l j v ,.H.D.G.P R a.p._.rXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXiX&XT.,.z h b V - ; U 8.a._.6XgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX-X!.%.h o O W _ s.gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX7X~.&.c W ;.;.8.rXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXqX&.;.+.+.=.0.y.5XgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX~.d.;.8.4.d.e.e./.5XgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX6.u.|.gXgXgX^.7.:.6XgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX{.6.`.gXgXgXgX2X2XgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgX", "gXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXtXe88nXqiXu:Rː౤A`d &XW3U2guO~ݽ{Ͻ{~i}jX0xv?{{wG}ȅKdz~݅܀+_6&)ʚ~\k6&?`صvlnTz&rzŵ'|C%{v8]F 1H@@tXW\~oO?}fT)#K`n>6J,~KmT]}R2n@0f!Dzb0sjOm u3h⾾h4/ƹ/.xO $ g)?ٹs}xN@,N  ˢ Y ou[PP=&[ߟsJقA@i/4˨~L0 ܄M! оݷz:'}X44FN4ؽ_`lp=]D ,{LH`([bK#* 7Գ@aK A4*GNhd.@L@JF0&\Ui7):&}Kҟ 22/e!pt:d/WMNOSW]HRСt)ſϽNtANwRv]ofZ-D'V H#OHP;^3ukÀ-bh P:}.=rCNkљTmhɬiQ(Y Ɓɷ=uÇ*NʤRf#FITL(^CiH-yرJ94oڸpcnfDf-S i.nh^g*E&0~W1;Ba Fm}[:fHWHi ӱ_Q-Y2NgNe2B\x 7Dd4]ۨ)=Y5q-3z}f-N"<JZ(zk?}gTnԄFFF&6ܖI$3-WCR)1:poMzo>;ZRҰJgV;e||)`IQ/cGtӒH~_R <[ߏFp|޳K5I O4 AA3-&,5` Ju{+c* tUĄ)(?oڣ}|+Vc>é[ ԦZzYb+9:IfȨ}q<ؙ+?"N9t$kk킀 nZ/`Je L-d2xHOdœ->;4&6 yedjP99NBǪ}=sWQ4CRidB39=Www0 BSRKl?gR!Rxʍ!C<`dr(h$/ Sg4딆oܱ*u♿Y.ݐv,@v{ڕhPW|@n7ЮrjpZ,e]!rT_n;ot$qcN\H=G|;0?+oJx0IENDB`GDGraph-1.44/t/images/logo_jpeg_noext0000644000175000001440000000734310614014571016224 0ustar benusersJFIFHHCC@@" ) "$%1 (!"$1#% ?ǣ/G}4!uB!!#JG`bb0I 1$s#]b߯פ)CȘrulcHAg =J=KK:Ǯ^~]HFPa (IK$2 " |5]Ji]2`ZxdEW1П 0[`(f'ќJ]YFue.AGvNKC'-5R8 XukI[A qյH!UӷdSH/bpc8 "?1_TkZKHZ3wXZy.(d?(cIԓ 8)9Vm{_Nҵ#Vd˥8*`$#a/PR"l)#>et_rRk.c:p, R}AWR%\ظ[,[.?,Cج*UnB/UkV;#d7aT(>TyGϤ٠vXյ!MbYm&T7D `01pۈ=7f9R [*xJH3e[(pu`ڒ6Fz?X[K띞62h`*"OkEO1PIt^l (}.o9|/FyX~^pؔu+{*J4]V )6ƑjY$DEf7-XI;cn,[5D e\0z0Z"@+PYaJf! "f"س|QcvM`q p9.N1on5v.iI\mEE7b;-@}U9PwJ|FmIuZiz̥ڷ"+YsJ_j_J^Rn[mNv[*]zj{ 8&ŗ?ˡm>5X+XjWUU(tVەҪ$Vv0s7TO|ʾO7Atoz[G%^\)iT) OjN8;ؚ^k \q>Xo,F םd1Dxs1_x(<fe[(瞋ǽG=s]V 0_Vv!#<m &x!וͫQu: k@v)9TԼ;*/%W\6T5!b v4=j:LWMس8 vX4s7 NGD12RGYᯔ^e׶~o3l^wk-T9[qM5!#ϑӒzL_Qoyߐ5mB`EU1]SpDnIFטUf)&cBhMYR$̧/'^9ʩZUjOo,,ZfRjUԼiz[l6>w ^?x'rנnM7jִC>Wy RΥزTV#:Ho<M_&vjmQ|JQ9Aky’*[~cV%% (:E +,K 8,RPe?~N񼘼_ar<+vY+XZM2Q?N3ɭ*nvN"MM~}0j!&!>CQ-}JұK:K+n+*rbT'Ǒj52䠑)s b7BIJl'W-x5ί[-rPayٜ<ҭVh 7, x|F |m vtԳoso#&2-gf ~d.Yc+ڍr SD\* \Xy+>=R}3tz=&q5,TjUA厛822)ZXXYa8 H2Oޫ?デ:WsrKpڹa[XDQ6D #Zj5yZR"dKKƭi~k_4]*`l-r0-a _( ^]uv&bk '?9^X!UQpPU_?miÒFG/ ,&y}-\UZ ,0C <{XFX?83Kgգ#Uaq2 d+ʡa9ĭ͖K ׳,Hkh_z=Dz^GDGraph-1.44/t/images/logo_xbm_noext0000644000175000001440000000631410614014571016062 0ustar benusers#define logo_width 64 #define logo_height 64 static char logo_bits[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFE, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0x07, 0x1F, 0xFE, 0xFF, 0xFF, 0xFF, 0xF1, 0xFF, 0x03, 0x1E, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0xF1, 0x81, 0x06, 0xF7, 0xFF, 0xFF, 0xFF, 0x01, 0x70, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0x00, 0x18, 0x20, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0x00, 0x40, 0x40, 0x00, 0xFC, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x18, 0x00, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0x10, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x83, 0x04, 0x00, 0x04, 0x40, 0xF8, 0xFF, 0xFF, 0x01, 0x40, 0x08, 0x00, 0x80, 0xF8, 0xFF, 0xFF, 0x00, 0x10, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x7F, 0x40, 0x02, 0x01, 0x03, 0xE0, 0xFF, 0xFF, 0x3F, 0x02, 0x40, 0xE8, 0x03, 0xE8, 0xFF, 0xFF, 0x1F, 0x10, 0x08, 0xE0, 0x05, 0xE0, 0xFF, 0xFF, 0x4F, 0x08, 0x12, 0x42, 0x02, 0xC8, 0xFF, 0xFF, 0x07, 0x42, 0x80, 0x10, 0x01, 0xC5, 0xFF, 0xFF, 0x23, 0x48, 0x20, 0x00, 0x40, 0xD4, 0xFF, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x18, 0x83, 0xFF, 0xFF, 0x40, 0x00, 0x00, 0x5B, 0xC4, 0xAA, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0xA4, 0x13, 0x88, 0xFF, 0x3F, 0x04, 0x01, 0x00, 0x40, 0x89, 0x83, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0xA0, 0x35, 0xC8, 0xFF, 0x7F, 0x91, 0x00, 0x00, 0x80, 0xA0, 0xF0, 0xFF, 0x7F, 0x04, 0x00, 0x00, 0x00, 0x8D, 0xFC, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x80, 0xA2, 0xFF, 0xFF, 0xFF, 0x40, 0x01, 0xE0, 0x40, 0xE4, 0xFF, 0xFF, 0x3F, 0x80, 0x56, 0x39, 0x20, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0xA8, 0x17, 0x90, 0x0E, 0xE7, 0xFF, 0x0F, 0x00, 0x5A, 0x2A, 0x20, 0x03, 0xC3, 0xFF, 0x0F, 0x00, 0x80, 0x15, 0xC0, 0x01, 0xE0, 0xFF, 0x1F, 0x10, 0x60, 0x2B, 0x80, 0x01, 0xF8, 0xFF, 0x1F, 0x08, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x3F, 0x00, 0xC0, 0x03, 0x00, 0x00, 0xFC, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0x01, 0x00, 0xC0, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x01, 0x00, 0xC0, 0xFF, 0xFF, 0x21, 0x01, 0xFE, 0x25, 0xE1, 0xC1, 0xFF, 0xFF, 0x03, 0x08, 0xFC, 0x91, 0xF0, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0xF8, 0x07, 0xF8, 0xFF, 0xFF, 0xFF, 0x1F, 0x02, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x10, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xE5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x38, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x78, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }; GDGraph-1.44/t/data.tab0000644000175000001440000000016510347716770013263 0ustar benusers# X Y1 Y2 Y3 Y4 Y5 A 1 2 3 4 5 B 2 3 4 5 C 1 2 3 D 1 4 # num_sets should return 5 # num_points should return 4 GDGraph-1.44/t/axestype.t0000644000175000001440000000274710347716770013721 0ustar benusers# $Id: axestype.t,v 1.1 2005/12/14 04:22:16 ben Exp $ # # Test stuff related to axestype charts # use Test; use strict; BEGIN { plan tests => 13 } # Use "mixed" as the generic chart type to test use GD::Graph::mixed; ok(1); print "# Check for division by 0 errors when all data points are 0\n"; { my $g = GD::Graph::mixed->new(); if (ok(defined $g)) { ok($g->isa("GD::Graph::axestype")); my $gd = eval { $g->plot([[qw/A B C D E/], [0, 0, 0, 0, 0]]) }; if (ok(defined $gd)) { ok($gd->isa("GD::Image")); } else { skip($@, 0); } } else { skip("GD::Graph::mixed->new() failed", 0) for 1..3; } } print "# Check for division by 0 errors on zero two_axes charts\n"; { my $g = GD::Graph::lines->new(); $g->set(two_axes => 1); if (ok(defined $g)) { ok($g->isa("GD::Graph::axestype")); my $gd = eval { $g->plot([[qw/A B/], [0, 0], [0, 0]]) }; if (ok(defined $gd)) { ok($gd->isa("GD::Image")); } else { skip($@, 0); } } else { skip("GD::Graph::lines->new() failed", 0) for 1..3; } } print "# Check for division by 0 errors on non-zero two_axes charts\n"; { my $g = GD::Graph::lines->new(); $g->set(two_axes => 1); if (ok(defined $g)) { ok($g->isa("GD::Graph::axestype")); my $gd = eval { $g->plot([[qw/A B/], [1, 1], [1, 1]]) }; if (ok(defined $gd)) { ok($gd->isa("GD::Image")); } else { skip($@, 0); } } else { skip("GD::Graph::lines->new() failed", 0) for 1..3; } } GDGraph-1.44/t/error.t0000644000175000001440000000212710347716770013200 0ustar benusers# $Id: error.t,v 1.1 2005/12/14 04:22:16 ben Exp $ use Test; use strict; BEGIN { plan tests => 16 } use GD::Graph::Error; ok(1); # Can't/Shouldn't instantiate a GD::Graph::Error object. Will use # GD::Graph::Data instead use GD::Graph::Data; ok(1); print "# Check inheritance\n"; my $error = GD::Graph::Data->new(); ok($error); ok($error->isa("GD::Graph::Error")); ok($error->isa("GD::Graph::Data")); print "# Check error and warning level\n"; ok(! $error->has_error); ok(! $error->has_warning); print "# Set some warnings and errors\n"; $error->_set_error([2, "One warning"], [0, "Two warning"], [1, "Three warning"]); ok($error->has_warning, 3); ok($error->has_error, 0); print "# Set more errors\n"; $error->_set_error([9, "One error"]); ok($error->has_warning, 3); ok($error->has_error, 1); print "# Clear errors\n"; $error->clear_errors; ok(! $error->has_warning); ok(! $error->has_error); print "# Set critical error\n"; eval { $error->_set_error([11, "Critical error"]) }; ok($@, qr/^Critical error/); ok(! $error->has_warning); ok($error->has_error, 1); GDGraph-1.44/t/use.t0000644000175000001440000000060510347716770012642 0ustar benusers# $Id: use.t,v 1.1 2005/12/14 04:22:16 ben Exp $ use Test; use strict; BEGIN { plan tests => 10 } use GD::Graph; ok(1); use GD::Graph::axestype; ok(1); use GD::Graph::area; ok(1); use GD::Graph::bars; ok(1); use GD::Graph::hbars; ok(1); use GD::Graph::lines; ok(1); use GD::Graph::points; ok(1); use GD::Graph::linespoints; ok(1); use GD::Graph::mixed; ok(1); use GD::Graph::pie; ok(1); GDGraph-1.44/t/colour.t0000644000175000001440000000154310347716770013353 0ustar benusers# $Id: colour.t,v 1.1 2005/12/14 04:22:16 ben Exp $ use Test; use strict; BEGIN { plan tests => 9 } use GD::Graph::colour qw(:colours :lists :convert); ok(1); my $colour = '#7fef10'; print "# Convert a colour between hex and rgb list\n"; my @rgb = hex2rgb($colour); ok("@rgb", "127 239 16"); ok($colour, rgb2hex(@rgb)); # Get the number of colours currently defined my $nc = scalar (@_ = colour_list()); print "# add a colour explicitly\n"; my $rc = add_colour(foo => [12, 13, 14]); ok($rc, "foo"); ok($nc + 1, $nc = scalar (@_ = colour_list())); @rgb = _rgb("foo"); ok("@rgb", "12 13 14"); print "# The next should add a colour, since it hasn't been defined yet\n"; @rgb = _rgb("#7f1020"); ok("@rgb", "127 16 32"); ok($nc + 1, $nc = scalar (@_ = colour_list())); print "# Check that colour_list() limits correctly\n"; ok(13, scalar (@_ = colour_list(13))); GDGraph-1.44/t/data.csv0000644000175000001440000000016510347716770013310 0ustar benusers# X, Y1, Y2, Y3, Y4, Y5 A,1,2,3,4,5 B,2,3,4,5 C,1,2,3 D,1,,4 # num_sets should return 5 # num_points should return 4 GDGraph-1.44/t/data.t0000644000175000001440000000625510347716770012766 0ustar benusers# $Id: data.t,v 1.1 2005/12/14 04:22:16 ben Exp $ use Test; use strict; BEGIN { plan tests => 37 } use GD::Graph::Data; ok(1); use Data::Dumper; ok(1); my @data = ( [qw( Jan Feb Mar )], [11, 12], [21], [31, 32, 33, 34], ); print "# Test setting up of object\n"; my $data = GD::Graph::Data->new(); ok($data); ok($data->isa("GD::Graph::Data")); $GD::Graph::Error::Debug = 4; print "# Test that empty object is empty\n"; my @l = $data->get_min_max_x; ok(@l, 0); my $err_ar_ref = $data->clear_errors; ok(@{$err_ar_ref}, 1); print "# Fill with data\n"; my $rc = $data->copy_from(\@data); ok($rc); #@l = $data->get_min_max_x; #ok(@l, 2); #ok("@l", "Jan Jan"); # Nonsensical test for non-numeric data print "# Check number of data sets\n"; my $nd = $data->num_sets; ok($nd, 3); print "# Get min and max\n"; @l = $data->get_min_max_y(1); ok(@l, 2); ok("@l", "11 12"); @l = $data->get_min_max_y($nd); ok(@l, 2); ok("@l", "31 34"); print "# Check number of points, and y value\n"; my $np = $data->num_points; my $y = $data->get_y($nd, $np-1); ok($np, 3); ok($y, 33); print "# Add a point and check dimensions\n"; $data->add_point(qw(X3 13 23 35)); $nd = $data->num_sets; $np = $data->num_points; $y = $data->get_y($nd, $np-1); ok($nd, 3); ok($np, 4); ok($y, 35); @l = $data->y_values(3) ; ok(@l, 4); ok("@l", "31 32 33 35"); print "# Check cumulate\n"; $data->cumulate(preserve_undef => 0) ; @l = $data->y_values(3); ok(@l, 4); ok("@l", "63 44 33 71"); print "# Check reverse\n"; $data->reverse; @l = $data->y_values(1) ; ok(@l, 4); ok("@l", "63 44 33 71"); print "# Check min and max\n"; @l = $data->get_min_max_y_all; ok(@l, 2); ok("@l", "0 71"); print "# Check copy()\n"; my $data2 = $data->copy; ok($data2); ok($data2->isa("GD::Graph::Data")); ok(Dumper($data2), Dumper($data)); my $file; print "# Read tab-separated file\n"; $file = -f 'data.tab' ? 'data.tab' : -f 't/data.tab' ? 't/data.tab': undef; $data = GD::Graph::Data->new(); $rc = $data->read(file => $file); ok(ref $rc, "GD::Graph::Data", "Couldn't read input data.tab input file"); if (!defined $rc) { skip("data.tab not read", 0) for 1..2; } else { ok($data->num_sets(), 5); ok(scalar $data->num_points(), 4); } print "# Read comma-separated file\n"; $file = -f 'data.csv' ? 'data.csv' : -f 't/data.csv' ? 't/data.csv': undef; $data = GD::Graph::Data->new(); $rc = $data->read(file => $file, delimiter => qr/,/); ok(ref $rc, "GD::Graph::Data", "Couldn't read input data.csv input file"); if (!defined $rc) { skip("data.csv not read", 0) for 1..2; } else { ok($data->num_sets(), 5); ok(scalar $data->num_points(), 4); } print "# Read from DATA\n"; # Skip first line of DATA ; $data = GD::Graph::Data->new(); $rc = $data->read(file => \*DATA, delimiter => qr/,/); # TODO This test cannot fail, because I don't check whether DATA is an # open file handle in read(). ok(ref $rc, "GD::Graph::Data", "Couldn't read from DATA file handle"); if (!defined $rc) { skip("DATA not read", 0) for 1..2; } else { ok($data->num_sets(), 3); ok(scalar $data->num_points(), 3); } __DATA__ We will skip this line # And from here on, things should be normal for input files A,1,2,3 B,1,2,3 C,1,2,3 GDGraph-1.44/t/bugfixes.t0000644000175000001440000000502510614022737013651 0ustar benusers#!perl use Test::More tests => 33; use strict; use File::Basename; use_ok('GD::Graph'); my $graph = GD::Graph->new(200,200); ok($graph,"Got an object from new()"); isa_ok($graph,"GD::Graph"); #bug 20802 my @candidates = ( [ qw(gif logo.gif logo_gif_noext) ], [ qw(jpeg logo.jpeg logo_jpeg_noext logo.jpg) ], [ qw(png logo.png logo_ping_noext logo_alt.PNG) ], [ qw(xbm logo.xbm logo_xbm_noext) ], [ qw(xpm logo.xpm logo_xpm_noext) ], ); my $icon_dir = dirname(__FILE__) . "/images"; foreach my $group (@candidates) { # no skipping for now my ($type,$withext, $noext,$other) = @$group; my $tests = $other ? 6 : 4; unless (my $method = GD::Image->can("newFrom\u$type")) { my $count = defined $other ? 6 : 4; pass("Skipping: GD appears not to support importing \U$type\E files") for 1..$tests; next; } else { my $quirky_test = eval { GD::Image->$method ; $@ }; if ($quirky_test && $quirky_test =~ /libgd was not built with/) { pass("Skipping: GD *really* doesn't support importing \U$type\E files") for 1..$tests; next; } } $graph->set(logo=> "$icon_dir/$withext"); ok(my $logo = $graph->_read_logo_file, "_read_logo_file succeeds for $type with file extension"); isa_ok($logo,"GD::Image"); $graph->set(logo=>"$icon_dir/$noext"); ok($logo = $graph->_read_logo_file, "_read_logo_file succeeds for $type without file extension"); isa_ok($logo,"GD::Image"); next unless defined $other; $graph->set(logo=>"$icon_dir/$other"); ok($logo = $graph->_read_logo_file, "_read_logo_file succeeds for $type with alternate extension"); isa_ok($logo,"GD::Image"); } my @buggy_sets = ( [ (1)x5 ], [ (0)x5 ], [ (-1)x5 ], ); use_ok('GD::Graph::bars'); # and now we attempt to reproduce more annoying bugs... # this is at axestype.pm line 1902 my $foo = GD::Graph::bars->new(100,100); $foo->set(y_min_value=>1,y_max_value=>1); ok ( eval { $foo->plot([ [ map "label$_", 1..3], [(1)x3]]) }, "freakish divide-by-zero trick"); ok(!$@, "No fatalities on the above"); # other possibilities for the same bug: setup_x_step_size_v (line 597), _h (628) # create_y_labels? (if "tick_number" is set to 0) $foo = GD::Graph::bars->new(100,100); $foo->set_legend(qw(Longlegenditemasdfasdf the heck)); my $stat = eval { $foo->plot([ ['A'..'F'], [(0)x7] , [(0)x7] , [(0)x7] ]); }; ok(!$@, "Survived 20792"); ok($stat, "and got a result"); #25975 is a duplicate of #5282 require GD::Graph::lines; $foo = GD::Graph::lines->new(1200,300); eval { $SIG{ALRM} = sub { die "alarmed" } ; alarm 1; $foo->plot([ [1..4],[(-1)x4]]); }; ok(!$@, "No timeout"); GDGraph-1.44/MANIFEST0000644000175000001440000000267710614023121012534 0ustar benusersCHANGES Dustismo.LICENSE Dustismo_Sans.ttf Graph.pm Graph/area.pm Graph/axestype.pm Graph/bars.pm Graph/colour.pm Graph/Data.pm Graph/Error.pm Graph/FAQ.pod Graph/hbars.pm Graph/lines.pm Graph/linespoints.pm Graph/mixed.pm Graph/pie.pm Graph/points.pm Graph/utils.pm Makefile.PL MANIFEST META.yml Module meta-data (added by MakeMaker) README samples/Makefile samples/logo.png samples/rgb.txt samples/sample11.pl samples/sample12.pl samples/sample13.pl samples/sample14.pl samples/sample15.pl samples/sample16.pl samples/sample17.pl samples/sample18.pl samples/sample19.pl samples/sample1A.pl samples/sample1B.pl samples/sample21.pl samples/sample22.pl samples/sample23.pl samples/sample31.pl samples/sample41.pl samples/sample42.dat samples/sample42.pl samples/sample51.pl samples/sample52.pl samples/sample53.pl samples/sample54.dat samples/sample54.pl samples/sample55.pl samples/sample56.pl samples/sample57.pl samples/sample61.pl samples/sample62.pl samples/sample63.pl samples/sample64.pl samples/sample71.pl samples/sample91.pl samples/sample92.pl samples/sample93.pl samples/sample94.pl samples/sample95.pl samples/save.pl t/axestype.t t/bugfixes.t t/colour.t t/data.csv t/data.t t/data.tab t/error.t t/images/logo.gif t/images/logo.jpeg t/images/logo.jpg t/images/logo.png t/images/logo.xbm t/images/logo.xpm t/images/logo_alt.PNG t/images/logo_gif_noext t/images/logo_jpeg_noext t/images/logo_ping_noext t/images/logo_xbm_noext t/images/logo_xpm_noext t/use.t GDGraph-1.44/Dustismo_Sans.ttf0000644000175000001440000017310010347716572014731 0ustar benusers LTSHyOS/2UNVVDMXkIr`cmapxzcvt tm@fpgmɌqvgasp glyf<9hdmx>b"heado,6hhea Bzd$hmtx{SHkernGloca8fmaxp^ nameD}post &prepr @?_<9jEWkk2Wuu[e@[fJADBE@ Kqc ">T"dX 1,9e L \ s#w    >  "   X 0   V . v   F Copyright (c) Dustin Norlander, 2002. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or any later DustismoRegularDustinNorlander: Dustismo: 2002DustismoVersion 1.4; 2002DustismoDustismo is a trademark of Dustin Norlander.Copyright (c) Dustin Norlander, 2002. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or any later DustismoRegularDustinNorlander: Dustismo: 2002DustismoVersion 1.06 2003DustismoDustismo is a trademark of Dustin Norlander.Dustin Norlander, . This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version of the License, or any laterDustin Norlanderhttp://www.dustismo.comCopyright (C) 2002 Dustin Norlander This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or any later version.http://www.gnu.org/licenses/gpl.txtCopyright (c) Dustin Norlander, 2002. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or any later DustismoRegularDustinNorlander: Dustismo: 2002DustismoVersion 1.06 2003DustismoDustismo is a trademark of Dustin Norlander.Dustin Norlander, . This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version of the License, or any laterDustin Norlanderhttp://www.dustismo.comCopyright (C) 2002 Dustin Norlander This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or any later version.http://www.gnu.org/licenses/gpl.txt "  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ƂʈǫJ@ ~!7~     " & 0 : D !""" "9     & 0 9 D !"""7r~pc0hޒHZ\bh 4bcdefghjikmlnoqprsutvwxzy{}|~ #$    %&'()*`aKLMN\[GHIJOPQRSTUVWXYZCD]bc?@ABEF^_;<=> !"qonrstH@~!7~     " & 0 : D !""" "9     & 0 9 D !"""7r~pc0hޒFXZ`f2bcdefghjikmlnoqprsutvwxzy{}|~ #$    %&'()*`aKLMN\[GHIJOPQRSTUVWXYZCD]bc?@ABEF^_;<=> !"qonrstu ++ E}iD@ EhDEhDEhDEhDEhDEhDEhDEhDEhDEhDEhDEhDEhDEhDEhDF+F+EhDEhD@,vE %E#ah#h`D- ,KPXYD_^- , EiD`- , *!- , F%FRX#Y Id F had%F hadRX#eY/ SXi TX!@Yi TX!@eYY:-, F%FRX#Y F jad%F jadRX#Y/-,K &PXQXD@DY!! EPXD!YY-, EiD` E}iD`-,*-,K &SX@Y &SX#!#Y &SX#!#Y &SX#!@#Y &SX%EPX#!#!%E#!#!Y!YD-,KSXED!!Y-sKKWZbZb*qKwlil!k!(:hsJ8 @)hEHHY;5D( F"$ 1(\CLHn%~9`JP9IJJJs9Jd1=JsHHl9$Hs9IHe5$~A9!5i91H]X=0Ha*arH<3Ye4!L/J/ LHcV J]Je4YJLYH9dC9!<=P!DGq c,p9p9B9JH^9pAWzWzWzWzWzWz3R0R0R0R0`iOJW4W4W4W4W4CCCC.!b[G=5p%..9v:7 !._:k%{s26D~9p9^92ADH0.8<b$b0 B!!A!HH4h5<1p9Jp9JJV1V VV^9^9^9pApApAJL,OT=@h- =DTRYMa,(e<@1D/Q B!>L<D~9*aydaU`JrH`JrH`JrHP93YHIHYHIHYHIHe4l9$d~ACe59e59e59~AC~AC~AC~9*a~9*aP93P93H]Jdd@!d1~-J1D1D5<P!~9*aP93P93IJPJe4Je4Je4Je4Je4s9L/s9L/s9L/~AC~ACl9e4l9e4H]J$ddd1/s9L/Jx/1/=LHJJJH]JW$dI0uQ\AAC~9*adBl9e4~AC9#/`JR8x                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         V@ @ Fv/7?Y0134632#"&x)**).))))iKQ +/ /ܸܸи///EX/>YEX/>Y01#3#3΂7!D@ @!            Fv/7?YEX/>Y +( +( +иик)9 и!и(+012654&#"32##5"&'33"&54767532#&^e\gU]`53\%2WQN/GK9YEX/>YEX///>YEX/>YEX / >Y01 #2#"&546"32654&2#"&546"32654&irnnqo6NN66OO{poomZ" N87RTKKmnopK66JJ66KėnomnO8JL65K:q*#,{ +& +&A&&&&&&&]A &&&&6&F&V&qAe&u&qEX / >Y +016&6'3'.547'.7632267z u2g=o6/I%LOssGD?'_sd lAW27fpOIE%_k+GEMJrmC(4%7o\j sK$ + +/EX/>Y01#3JqK + +A]A &6FVqAeuqEX/>YEX / >Y017&Je``ef#m*]]*m#f8oI | + +AjzqA]A )9IYqEX / >YEX/>Y0156'5e``e#m*33*m#@1Q + / /// + 9ик  9  901''7#53'773ag``gakgllgk<  +//0172'67.6,CVyC9@A,w:/DqmHS + +01!!H H# + +AjzqA]A )9IYqEX / >YA]A '7GWqAfvq0174632#"&H@./>@-.@m/@A..?@*KQ@@Fv/7?YEX/>Y AiyqA]A (8HXqA]A '7GWqAfvq01#"&=46324&#"3265jjjji^ݘޙhd^d5U Q + + и EX/>YEX/>Yܸ и 01526733!5358EZFXb/4łvD + + и и /EX/>YEX/>YAiyqA]A (8HXq01)56$65&!"#4$32!~s[egHyH`IvA;(})} +$ +Aj$z$qA$$$$$$$]A $$)$9$I$Y$q$9/AjzqA]A )9IYqܸ+EX/>YEX/>YEX/>YEX/>YEX/>Y + 9'Ai'y'qA''''''']A ''('8'H'X'q01'67632#"&5332654>56&#" m$1_mx=}[jiHK#5ƥk*Á|HܧNrrqMf< q" w + +и иEX/>YEX/>YEX/>YEX / >Yܸи01% 3##!5<^$dd_;łq;Fq# +//и/ܸ ܸи/ AjzqA]A )9IYqEX/>YEX/>Y + ܺ 99A]A '7GWqAfvq01"#!!632#"'532654'&[khpŖ5il`|[1ޑ^}׎PG"I + +AjzqA]A )9IYq EX/>YEX/>Y +9ܸA]A '7GWqAfvq01632#".!"";2654& nn.8nѽns|u$q^@%@Fv/7?YEX/>Y  + %AiyqA]A (8HXqA]A '7GWqAfvq  9* 9014&#"326&#"3265&#"$'47&54632Ғ[[[[X ЋޑދWWjrrIoiioj`si̔is(o + +A]A &6FVqAeuqEX/>YEX/>Y +9ܸAiyqA]A (8HXq01#"$54$32!52%2654&+"z3Țz,nѽwasy|u\7  + +AjzqA]A )9IYq ииEX/>Y +014632#"&4632#"&\A,-A@..??..@A-.?U-@A,.BBJ.BB..?@CA<  + +AjzqA]A )9IYqи//EX/>Y014632#"&2'67.6]B,,CB-.@o,CVyC9@U-@A,.BBA,w:/DqmL'k@-@Fv/7?/.ć........10IhIha@RX878Y 5'q%osHB + + +01!!!!H}}ĂnI +/EX/>Y015 n%q%K#// +0/1/0и/*ܸи/1ܸ Aj z qA ]A  ) 9 I Y q*и/*и/ и/*!и!/$и$/EX/>YEX-/->YAiyqA]A (8HXq01#7676767654'&#"#46324632#"&t7(N)M5:4a6ʍ8"=657 )**),]C/-&=w71z%@ĉzB)[0Uw))))` AP +&5 +&F +F@ +@5@9Aj z qA ]A  ) 9 I Y q и /5@95@9 5@9A&&&&&&&]A &&&&6&F&V&qAe&u&qAFFFFFFF]A FF&F6FFFVFqAeFuFq@R*/ +*:" +:J +JB +B9Jи/и/ B901;27654#"'&'#"&54763273&! 327#"'&'&547632#"32654'&@!2H}ULyS-'ڣӬTfǶAߡZc⮟bkT4D5*@TyЩvh8/DڠأkżxvXZflsPQB@9K @B @        Fv/7?YEX$/$>Y + $ܸ ܺ 901!27654'&#!27654'&#'2#!e_TU^+ZTUZSLyQTO3SHQSDJz MIdaKNiookz^V&K9c#۸ + +EX/>YEX/>YAiyqA]A (8HXqA]A '7GWqAfvq014632#&'&#"327673#"&59jjL1GdșdG1LjjSnnV_iNnۣnNi_VnnJK a +//и/ܸܸܸи/EX / >YEX/>Yܸ 017!2654&#!%2#!(Ę(zs7$V+߂]X`kڙKJaK U + +EX/>YEX / >Y +ܸ 01!!!!!akKTKJaK M + +EX/>YEX/>Y +01!!!#akKXeK9c): +*/+/)ܸܸ* и /)и/и ܸ и /EX/>YEX/>YEX/>Y% +%9AiyqA]A (8HXqA]A '7GWqAfvq01!5#"&54632#4&#"3265!6&7!};KqjjᘘjjᘂșșhG%7nYnnۣ۩ A JK W +EX/>YEX/>YEX/>YEX / >Y +01!3#!#:ƂK<K1K l@0 @       Fv/7?YEX/>YA]A '7GWqAfvq01!#"'&=33265#F$3w{%MlKJLl~rv~-5EXkX=K @B @     Fv/7?YEX/>Y01!!T*K7KHK @> @     Fv/7?YEX/>YA]A '7GWqAfvq Ai y qA ]A   ( 8 H X q0132654&#"#"&54632șșDjjᘘjjۣyۣnnYnnHK  +//и/ܸܸ иAjzqA]A )9IYqEX/>YEX/>Y +  01#!2#32654'&#̄؛JXKx|D9c8, +9/:/9,и,/:ܺ,9ܸ,ܸи7EX2/2>YEX/>YEX'/'>Y292 Ai y qA ]A   ( 8 H X q'A]A '7GWqAfvq01654'&#"327'%#.'#"&'&547632 @ 9ddddddzXL 2[1%)pjjLLpqjjLL#F#]{ymnnmnmE6]47nY77nHK߸ +// и / ܸиܸAjzqA]A )9IYq 99EX / >YEX / >YEX/>Y + ܺ 901!2654&##!2#؛nl)y~8Kx|rn!5d7Z +8/9/8и/ܸи9 ܸ!Aj!z!qA!!!!!!!]A !!)!9!I!Y!q(и 2и!3EX-/->YEX/>Y-AiyqA]A (8HXqA]A '7GWqAfvq01"#".'332>'4.$.54>36#4.Q[11YDR_aM2[NNa74`AMckH-Z!gcQ^e;9eaGZ@$&AXD6UCidMLa9:fM3lB&KE + +EX/>YEX/>Yܸи01#!5!.i7ɂAK +//и/ܸ ܸܸ и /EX/>YEX/>YEX/>YA]A '7GWqAfvq0132653#"'&'&5ʒ̂Ɩzs6%Kۥ_ٚ]X`kQ!Kl@/@Fv/7?m^W1K o@. @    Fv/7?Y017!!Hba?K +/EX/>Y01 3? aLy +M/N/7ܸܸMHиH/A]A &6FVqAeuq и+и+/H,и,/EX1/1>YEX=/=>YEXC/C>YA]A '7GWqAfvqC191&Ai&y&qA&&&&&&&]A &&(&8&H&X&q:01%2>76=>=4.#"'>32.''".54>@^A'!0L^aY /"3M\$itt\93N[(1^RA~NqKBwM3O?XLsF/Cl$ %,/29 @ 6' &D7IhB#@\9 A -'-,=kU$MF=HK } +//и/ܸи/ܸ Aj z qA ]A  ) 9 I Y qк9EX/>YEX / >YEX/>Y AiyqA]A (8HXqA]A '7GWqAfvq9901"32654&'2#"'#36#ǐ2܀{Q⑓㏒ĮK3: +  + A ]A   & 6 F V qAe u qEX/>YEX/>Y9 Ai y qA ]A   ( 8 H X qA]A '7GWqAfvq9012#&'&#"327673#"54Ǎ5! gˑf !2ә9@p⒓p ;50.Ky +//ܸܸи и / 9A]A &6FVqAeuqи/EX/>YEX/>YEX / >Y 9 9AiyqA]A (8HXq A]A '7GWqAfvq0123#5#"54"32654&{2ǐߓ<-0ᒏߓ4۸ +EX/>YEX / >Y + A]A '7GWqAfvqAiyqA]A (8HXq013267#"5432"!.юh+5  o)#ϊـ[/.hj!Ks + +и  EX/>YEX/>YEX / >YEX/>Yܸ и 01"3###535463YcNNcDb;b}/v & +'/(/ܸܸи/'и/ A ]A   & 6 F V qAe u qи/ и/$к%9EX/>YEX / >YEX/>Y! +! A]A '7GWqAfvqAiyqA]A (8HXq 9% 901%2654&#""543253#"&'7326= w z|lߓ⑓߂,ɳ֦{ǔ[JKԸ +//и/ܸܸ ܸEX/>YEX/>YEX/>YEX/>Y9 Ai y qA ]A   ( 8 H X q013632#4&#"#J~վ炙Kޘ"/>Mf + +и/и/EX/>YEX/>YEX/>Y014>32#".!##  ..  r , , C; qYKZ + +и/!EX/>YEX/>YEX/>Y014>32#".#5!#52765#  ..  pWVZ12| , , L~WX21DHK @@ @     Fv/7?YEX/>Y013#VKJs +  +  + + к99!EX/>YEX/>YEX/>YEX/>YEX / >YEX/>YAiyqA]A (8HXq к9901"#6&#"#3632632#4&xyfvzZM7𹤂_Qҡ"ޡҡ"j"ޡJԸ +//и/ܸܸ ܸEX/>YEX/>YEX/>YEX/>Y9 Ai y qA ]A   ( 8 H X q013632#4&#"#Jsꄲ޽"4  +//и/A]A &6FVqAeuqܸ Aj z qA ]A  ) 9 I Y qEX / >YEX/>Y AiyqA]A (8HXqA]A '7GWqAfvq01"32654&'2#"54ˑΑQ⒓0.Jq  +//ܸAjzqA]A )9IYqи/ܸ и /к9EX/>YEX/>YEX/>YEX / >YA]A '7GWqAfvqAiyqA]A (8HXq9901%2654&#""'#3632'̐Ɛl㏒⑓߂LLq +//и/ ܸ ܸ к  9 и/A]A &6FVqAeuqEX / >YEX/>YEX / >YEX/>Y 9 9A]A '7GWqAfvqAiyqA]A (8HXq01"543253#'2654&#"*ܐĒ-0Į=ĂߓᒏH + + EX/>YEX / >YEX / >Y 9 9AiyqA]A (8HXq016;&#"#3̀g^DŽ,̑"9C>764&'.'.67>.'.&'.',4+aa\'9X+0a0.G<2(4?.N<(~)2,ff`%0I,0c/Exa5~?.N<(0$ #x9 ;FT)/*:L2!1# 't: bD)/*:L2#r + +и /EX/>YEX/>YEX / >Yܸ ܸи013#;#"&5#52=328,b,:aSblC̸ +//ܸܸи/ ܸEX/>YEX/>YEX/>YEX/>Y9 A ]A   ' 7 G W qAf v q01!#5#"&5332653m悛 ؚ!l@/@Fv/7?YEX/>YEX/>YEX/>YEX / >YEX / >Y99901!33 3# ]}H= @O @            Fv/7?YEX/>Y0173 3'{(g$6NM|!Dp o@. @    Fv/7?YEX/>Y 9016567.4'GiMs6(::(6sMiHSI++++ISHq}K?@@Fv/7?YEX/>Y 901'>67.&'7iMs6(::(6sMiHSJI՜++IJSH,1 +//EX/>YEX / >Y012767#"&"'>@w)&%{>Nn"0{%iVP/[T3g@9{&$9j&$(9c&&""Ja&(!kH&19v&2Ar&8zK&DHzK&DCYzJ&Dz &Dz&Dzx&D.-3&F@0K&HA0K&HCS0K&H0&HwQ&fS&Cf`K&i&/rJ&Q4K&RA4K&RC!4K&R4 &R4&RCK&XCK&XCQCN&XC&Xx.@DK - +/EX/>YEX/>Y012#"&546"32654&7ponm6ON78RTKnomnK58JK76J!>" + +" +"A]A &6FVqAeuqܸ и"иии"/EX/>Y 9 90167#5&'&54676753&'yHKLIwRvmrpIUlMQSw{SPkw}9% cթ![09̸ +1 +1и/ и1,и13и3/%/EX / >YEX/>Y  + -и/и 5A5555555]A 55'575G5W5qAf5v5q01%&#"32!#"'#"'&54763265#5347632&#"3#327677D0!3vYix6YX4/16[92V6=*27ii V{X!<bb($56'+)NIg5.~HM(O! G?uK<Hh +I/J/Iи/ܸи/Jܸ и /&Aj&z&qA&&&&&&&]A &&)&9&I&Y&qи/9+к/92и8и&9и9/&;и=и=/&C/EX5/5>YAiyqA]A (8HXq5959/5901"#"&53327654'%&54767'&54632#67632767&#"[O#c${$(H~ $NR%HH<2V|HK%H$)%A*IS*7{I f7Y=&,,$E277{dC8`8o|~y#:% 5b  +/ /014632#"&5XYWXXz{WWxy%)r + +  +  ܸ EX/>YEX / >YEX/>Yܸ и 01476763!####.%F +0+{d~\+;?.vD (1K + + + +A]A &6FVqAeuqAjzqA]A )9IYq& 9)и3EX/>Y +A]A '7GWqAfvq01 ! "3254#%6#/32654&'rwJLFBa_IilODux}EE^hd^ɆwMOr .vD%3 ++# ++ +1 +A]A &6FVqAeuq #9#9A+++++++]A ++&+6+F+V+qAe+u+qAj1z1qA1111111]A 11)191I1Y1q5EX / >Y& + + + .A.......]A ..'.7.G.W.qAf.v.q01"3267#"'&5432. ! "3254j*ƃ Ĺ+urwJLFB䷍n`y~y]q`ux}EE9q-K@U@        Fv/7??))99)*>?))99tK@M@      Fv/7?YEX*/*>YEX/>YEX / >Yܺ 9* ܺ901%;2654'%"&#%+"'#7&5476;27BLXMVUYJrgEZa4F:4#-+v՜n:|ؙ==+C,!E! @;@          Fv/7/YEX/>Y 9 901%#"' '633273#&YY O1b2GzOOz .ZTr?rV:EZm +EX&/&>YEX,/,>YEX / >YEX?/?>YQ +0 +,AiyqA]A (8HXqQ9и/ии"и"/* &9?7A7777777]A 77'777G7W7qAf7v7qDиD/FиQMиM/QOиO/FZ01"!.+"'&'&547676;2767.#!"#463!2632!32767#"'&#"276=#"'#"3l'&ok\`0D?fCJNmL5H_DDbzY$#.hf\`,307iIE,cH^#gFBBEh;eg'b25[;EgSL%DXdC|bPYEX/>YEX/>YEX/>YA]A '7GWqAfvqAiyqA]A (8HXq01%32654/"&'273#"'#7&54+Km{jG@]k HkP<̐bc̑fP,,q%%b%K / +0/1/0.и./и/./ܸи/1ܸ%Aj%z%qA%%%%%%%]A %%)%9%I%Y%qи//и//!и!/EX/>YEX/>Y!A!!!!!!!]A !!'!7!G!W!qAf!v!q014632#"&#"&53327654'&'&'&/3)**) 756="8̍ʅ6a4:5M)N(7))))U0[)Bz¢@%z17w=&-/C]sG @ +  + и/ и//EX / >Y014632#"&#s)**)))))2: M@ @    Fv/7/YEX/>YEX!/!>Y A]A '7GWqAfvqи0174632#"&%4632#"&%4632#"&D@..AB-.@@./?A-.@A./?A--Bm/@A.-@@-/@A..?@-.AA..?@9&$CHm9&$9&2AK0 +1/2/1!и!/ܸ2ܸܸ и /и,EX'/'>YEX/>Y +./ +. +'ܸܺ9,/.901#";2654&!!!!5+"'&5476;25!!& Ӑ XBZ`d ōZa d`ZBlը+RxuQ/2+C,2/QmxD.5t +" +A]A &6FVqAeuqEX%/%>YEX)/)>YEX/>YEX/>Y/ +/%AiyqA]A (8HXqA]A '7GWqAfvqк%9'%9401"32654&'&327#"'!"&'&543 632%!&'&#" ]Xn`?^8ru3"Ƃ~ c&OSj;hc̐k+RSWch>@HG=@@Fv/7/YEX$/$>YEX/>YEX/>Y01+.54674+.5467 b *9PI$`! a ,9QI'c_?)Z  0@8_>,[=0=<<TL1K +EX/>YEX/>YEX / >YEX"/">Y01632&'&7676754&5456%>32&'&5476754&5456| ^.@#Pu K% `=*,BO u`c=-=C &-@4*9A+] -=:;$K) +EX / >YEX/>Y01+.5467#4` *;O K$ `_>*Y&3=80)1 +/ /EX / >YEX/>Y01>32&'&54367675&5O=).@Q H& _*;@-] #.B4 e  + +A]A &6FVqAeuq и/ / +01%4632#"&4632#"&!!A--BB-.@A--BB-.@~-AB,.BB.?@--BBɂ!k&\!p&<>KQ@@Fv/7?YEX/>YEX/>Yܸ01"32654&'76327'#"''7&54ZxzXZ{wE_D\dh\D_E99E_DZjgYD_E9,{YYz{X]wE_E99E_E\ef\D_D88D_DXji*>@@Fv/7?/......10IhIha@RX878Y J H*>@@Fv/7?/......10IhIha@RX878Y 5HL854 n + +AjzqA]A )9IYq  +014632#"&4@./>@-.@%/@A..?@5K.  +//0172'67.6,CVyC9@A,w:/Dqm32&'&7676754&5456%>32&'&54356754&5456|;*.@#Pu K% `>),BO u`*:=.=D &-@4*:A,] -=:;1K'4@L +EX/>YEX/>YEX///>YEX/>YEX / >YEX;/;>Y5A +5;9и/Aи/ A]A '7GWqAfvqG01 #2#"&546"32654&2#"&546"32654&2#"&546"32654&prnnom6NN66PQ|poomZ" N88QS}ompo6PP66PQKKmnnoK66JK55LėnomnO8JK76J?mnnpL67IK55M9&$hJa&(et9&$yrJap&(^Ja&(Ck1&,l 5&,n-u&,&,Cn9&24e9&2t9&2CkA&8oA&8nAS&8CJK) +EX/>YEX/>Y01!##JC;L<vK?@@Fv/7//-I. {$A+TQ..R1h&K +EX/>Y01!!KTK  +/EX/>Y012#"&546"32654&C`aB@__@ /.!!23K\BB[]@A]P. !,,! .=v +//EX/>Y01654'&'3#'6K)C62%sDD$F(*C\q<&K7 +/EX/>YEX/>Y901373#qq§K@\mF-ɸ +./и/ܸA]AqA@P`qA]A qAqܸܸи/ ܸи/и/%и &и -и-/ //%/01".#4.56.#5>.537m054)!  M  !)450 BJuouJJuouJd/=>;;>=/hEG +=< +=и/=и/<и/<+и+/3'&#4>.52>'6.#5>.53?054))450 054))450 "_/=>;;>=//=>;;>=/-}=' + +/ +01!#!-S3=@:GC + +и // +и013265#53546;#"3#+DcNN|Dc|cDcb}cDb} 5J-S + + +AjzqA]A )9IYq и /*9*/Aj*z*qA*******]A **)*9*I*Y*q"ܺ "9/EX/>YEX/>YEX/>YEX$/$>Y- +ܸܺ -9&и'012654.#3#'5346;2#53>54&#1So=Ddo|\yFCvO3ZE(QR`};fPok}i=vG@D;(  +/ / +01267.'7@x&i9``9i&x55JNTTNJ55TZ +////0173%73T9YM"I8LMcK"I,O,K A +EX/>YEX/>Y9ܺ 9017!!'7'7G*K=~L>}H(yK U + +и EX/>YEX/>Y99017#'7&邻+K=~L/>}H<&6p@K&Vı1&=hDpT&]ķ Q}K4 + +и/EX/>Y013#3Q}6K  + /!/ܸܸ и/ ܸиEX/>YEX/>Y + ܸܸ и 01%2654&#!3#2#!#535ӓ(zs7$T~+) ]X`kڙrS&<h!kK&\ e + / / ܸܸ и/EX/>YEX / >Y +и01!##5!##syxl( +  + и/  и /и/"и"/ +% +% +  + и ии!01.#"3#3#32673#".'#535#53632m<@ }g"}$ROx愋ΆWԵN愧vy  +////017''7'!\\]l]\]L@4Ÿ +5/6/5)и)/ܸ6 ܸ ܺ) 90) 9EX&/&>Y +. +.&A]A '7GWqAfvq0.901";27654'&#&+5327#"$547>36&''>6QYJ\l228WY#5pl#8߀|8ElEJ6.CizXvHQGpA>RIp ^݀Zz<p & + +  + AjzqA]A )9IYq9/!ܸ и /!и/и/и/и/ ( + + +# +#и012654&#"#"'3!53##5!#632͐j~swwns~č͏̑jщ . :  +//01"&54632,Ò:ɓ˒Dx7 &θ +'/(/ ܸAjzqA]A )9IYq'и/ܸ и /и/и/!и!// +# +# +012654&#"#"'3!53##53#632͐j~swwX~č͏̑jщl9nK&$,^a&Dd  + +01!!dYa>l + +01!!a U0 J&%HK&EsDJK&%HK&EqJK&%n HK&E 9&&'I{g3B&F'qIHK&UH&5bH&UHK&5HK&UH&5l4&R93&2sK&7j g&W AK&8G@C&XGq@5&6]q9K&V5&6{9K&V5d&69&VSA&8C!&XA1&8qC&XA&8!C}&X291&$qa&D9K&$G<@a&DG@9&&gq3K&F59&&{3K&FH&1PoJK&Qp^&,x&a#/&,o!,&T1&,f&-/p-qW&MlpJ &/p`&O>+p1&=nDp@&]1&=3Dp&]'=5-&:Jn<-K&ZV&<n!kK&\9&$ta(&D9&&a3&FW=9&& s3K&FJ&'sPzf&GR<Ja1&(dq4&HJa&({4(&HJa&(4&HgAJaK&(G@4&HG@Ja&(q4K&H9&*{/vK&J9&*{/v2&Jc 9&*g/v&J5AA&8pC(&XWA&8CD&XW9&2n4(&R9 &24Q&RH&10{JK&Q&7{/#&W i&,n('1K&,G@/vM&LG@9c&*/v&JJ&+nx&K,z1K&,-o/qM&LMr=K&.HK&NJ K&/K&O>`J e&/aT&O>#~J K&/#WK&O>4HK&1TJ&QeK&K%S +// ܸܸи/ܸиии иии/ //EX/>YEX/>Y + + и ии01!!533##!##537:ggƂa]RĔ5Wp&QK&7_,&WK&'"0K&G2WQK +//ܸ ܸи/и/EX / >YEX / >YEX/>YEX/>YEX/>Y + 9  901>5##33'F c !Ff'oKj>lA + /!/ܸܸ  и / ܸ ии/ 9и/EX/>YEX / >YEX/>YEX/>YAiyqA]A (8HXq 9014'&#"#36323'5>767UYY\\suuĖKݽ[[qq"ć>lD/%=AZd&8C&X9&$ naK&D;&,n/K&; 9&2n4K&RA&8nCK&X9K$#>&`'l/7 +8/9/ܸ80и0/ 09AjzqA]A )9IYq0!A!!!!!!!]A !!&!6!F!V!qAe!u!q+09 + +и&и(и*0123!53>76.&3!53.7>7>|Tm# 8N.$9bG)DzcczD'E`9$.L6 "n3]LEKAxn0!e{G`XX`G{e!0nxAKEL]3;&pJK%R(0 + +EX/>Y +013!!R  +/EX/>Y01% 3!ow7|M(4^@@@@~v .FVR l  \ ` < ZD\jTNZXZD*b (P< !!"#|#$2$$%|&&'()L)* **+F++,8,|,,-&-2->-J-V-b-n-z-----------. .."...:.F.R.^.j.v...../|041R1p1234n445F56N67:8t9:b::;0;;;<<==>>p>??\???@@A,A^AAB&CCC&C2C>CJCVCbCnCzCCCCCCCDDHDdDDDDEF.FRFGGGGGGH4HxHHHHHIJIVIbIIJ.JTKKKLLLLLLLLLLMMMM*M:MFMRM^MjMvMMMMMMMMMMMN NN"N.N:NFNRN^NjNvNNNNNNNNNNNO OO"O.O:OFORO^OjOvOOOOOOOOOOOPPPP*P6PBPNP\PjPvPPPPPPPPPPPQQQQ*Q6QBQNQZQfQrQQQQQQQQQQQRRR R,R8RDRPR\RRRSSSST?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~.nulluni00A0uni0192uni00DFuni20ACmacronperiodcenteredrcaronRcaronuni0157uni0156racuteRacuteomacronOmacronuni0162uni0163UogonekuogonekSacutesacute Scircumflex scircumflexUtildeutildeUmacronumacronUringuringAmacronamacronAogonekaogonek Ccircumflex ccircumflexNacutenacuteItildeitildeImacronimacronuni0130 Jcircumflex jcircumflexLacutelacuteZacutezacuteuni017Buni017C Wcircumflex wcircumflex Ycircumflex ycircumflexAbreveabreveuni010Auni010BDcarondcaronEmacronemacronEbreveebreveuni0116uni0117EogonekeogonekEcaronecaron Gcircumflex gcircumflexuni0120uni0121Ubreveubreveuni0170uni0171Obreveobreveuni0150uni0151NcaronncaronTcarontcaronIbreveibreveIogonekiogonekuni0122uni0123 Hcircumflex hcircumflexIJijuni0136uni0137uni013Buni013CLcaronlcaronLdotldotuni0145uni0146hbarHbaruni0149Tbartbaruni0110uni0111EngengUhornuhornuni01CDuni01CEuni01CFuni01D0uni01D1uni01D2uni01D3uni01D4Alphauni0390uni038FBetaGammaDelta`<$@$*$2$62$92DWD\HYHZKHLMNHQ pRZUDUHUJUQ8URUUVGAYHYRZR[H      !"#$% &!'!(")#*$+%,&-&.'/(0)1*2+3,4,5-6.7/8091:1;2<3=4>5?6@6A7B8C9D:E;F<G<H=I>J?K@LAMANBOCPDQERFSFTGUHVIWJXKYLZL[M\N]O^P_Q`QaRbScTdUeVfWgWhXiYjZk[l\m\n]o^p_q`rasatbucvdwexfygzg{h|i}j~kllmnopqqrstuvwwxyz{||}~GDGraph-1.44/Graph/0000755000175000001440000000000010614025002012430 5ustar benusersGDGraph-1.44/Graph/Error.pm0000644000175000001440000002173110347715245014105 0ustar benusers#========================================================================== # Copyright (c) 1995-2000 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GD::Graph::Error.pm # # $Id: Error.pm,v 1.8 2005/12/14 04:08:05 ben Exp $ # #========================================================================== package GD::Graph::Error; ($GD::Graph::Error::VERSION) = '$Revision: 1.8 $' =~ /\s([\d.]+)/; use strict; use Carp; my %Errors; use vars qw( $Debug $ErrorLevel $CriticalLevel ); $Debug = 0; # Warnings from 0 to 4, Errors from 5 to 9, and Critical 10 and above. $ErrorLevel = 5; $CriticalLevel = 10; =head1 NAME GD::Graph::Error - Error handling for GD::Graph classes =head1 SYNOPSIS use GD::Graph::Error_subclass; =head1 DESCRIPTION This class is a parent for all GD::Graph classes, including GD::Graph::Data, and offers error and warning handling and some debugging control. Errors are stored in a lexical hash in this package, so the implementation of the subclass should be irrelevant. =head1 PUBLIC METHODS These methods can be used by users of any of the subclasses of GD::Graph::Error to get at the errors of objects or classes. =head2 $object->error() OR Class->error() Returns a list of all the errors that the current object has accumulated. In scalar context, returns the last error. If called as a class method it works at a class level. This is handy when a constructor fails, for example: my $data = GD::Graph::Data->new() or die GD::Graph::Data->error; $data->read(file => '/foo/bar.data') or die $data->error; or if you really are only interested in the last error: $data->read(file => '/foo/bar.data') or die scalar $data->error; This implementation does not clear the error list, so if you don't die on errors, you will need to make sure to never ask for anything but the last error (put this in scalar context) or to call C now and again. Errors are more verbose about where the errors originated if the $GD::Graph::Error::Debug variable is set to a true value, and even more verbose if this value is larger than 5. If $Debug is larger than 3, both of these will always return the full list of errors and warnings (although the meaning of C and C does not change). =cut sub _error { my $self = shift; my $min_level = shift || 0; my $max_level = shift || 1 << 31; return unless exists $Errors{$self}; my $error = $Errors{$self}; my @return; @return = map { ($Debug > 3 ? "[$_->{level}] " : '') . "$_->{msg}" . ($Debug ? " at $_->{whence}[1] line $_->{whence}[2]" : '') . ($Debug > 5 ? " => $_->{caller}[0]($_->{caller}[2])" : '') . "\n" } grep { $_->{level} >= $min_level && $_->{level} <= $max_level } @$error; wantarray && @return > 1 and $return[-1] =~ s/\n/\n\t/ or $return[-1] =~ s/\n//; return wantarray ? @return : $return[-1]; } sub error { my $self = shift; $Debug > 3 and return $self->_error(); $self->_error($ErrorLevel); } sub warning { my $self = shift; $Debug > 3 and return $self->_error(); $self->_error(0, $ErrorLevel - 1); } =head2 $object->has_error() OR Class->has_error() =head2 $object->has_warning() OR Class->has_warning() Returns true if there are pending errors (warnings) for the object (or class). To be more precise, it returns a list of errors in list context, and the number of errors in scalar context. This allows you to check for errors and warnings after a large number of operations which each might fail: $data->read(file => '/foo/bar.data') or die $data->error; while (my @foo = $sth->fetchrow_array) { $data->add_point(@foo); } $data->set_x(12, 'Foo'); $data->has_warning and warn $data->warning; $data->has_error and die $data->error; The reason to call this, instead of just calling C or C and looking at its return value, is that this method is much more efficient and fast. If you want to count anything as bad, just set $ErrorLevel to 0, after which you only need to call C. =cut sub has_error { my $self = shift; return unless exists $Errors{$self}; grep { $_->{level} >= $ErrorLevel } @{$Errors{$self}}; } sub has_warning { my $self = shift; return unless exists $Errors{$self}; grep { $_->{level} < $ErrorLevel } @{$Errors{$self}}; } =head2 $object->clear_errors() or Class->clear_errors() Clears all outstanding errors. =cut sub clear_errors { my $self = shift; delete $Errors{$self}; } =head1 PROTECTED METHODS These methods are only to be called from within this class and its Subclasses. =head2 $object->_set_error(I) or Class->_set_error(I) =head2 $object->_set_warning(I) or Class->_set_warning(I) Subclasses call this to set an error. The argument can be a reference to an array, of which the first element should be the error level, and the second element the error message. Alternatively, it can just be the message, in which case the error level will be assumed to be $ErrorLevel. If the error level is >= $CriticalLevel the program will die, using Carp::croak to display the current message, as well as all the other error messages pending. In the current implementation these are almost identical when called with a scalar argument, except that the default ewrror level is different. When called with an array reference, they are identical in function. This may change in the future. They're mainly here for code clarity. =cut # Private, for construction of error hash. This should probably be an # object, but that's too much work right now. sub __error_hash { my $caller = shift; my $default = shift; my $msg = shift; my %error = (caller => $caller); if (ref($msg) && ref($msg) eq 'ARRAY' && @{$msg} >= 2) { # Array reference $error{level} = $msg->[0]; $error{msg} = $msg->[1]; } elsif (ref($_[0]) eq '') { # simple scalar $error{level} = $default; $error{msg} = $msg; } else { # someting else, which I can't deal with warn "Did you read the documentation for GD::Graph::Error?"; return; } my $lvl = 1; while (my @c = caller($lvl)) { $error{whence} = [@c[0..2]]; $lvl++; } return \%error; } sub _set_error { my $self = shift; return unless @_; while (@_) { my $e_h = __error_hash([caller], $ErrorLevel, shift) or return; push @{$Errors{$self}}, $e_h; croak $self->error if $e_h->{level} >= $CriticalLevel; } return; } sub _set_warning { my $self = shift; return unless @_; while (@_) { my $e_h = __error_hash([caller], $ErrorLevel, shift) or return; push @{$Errors{$self}}, $e_h; croak $self->error if $e_h->{level} >= $CriticalLevel; } return; } =head2 $object->_move_errors Move errors from an object into the class it belongs to. This can be useful if something nasty happens in the constructor, while instantiating one of these objects, and you need to move these errors into the class space before returning. (see GD::Graph::Data::new for an example) =cut sub _move_errors { my $self = shift; my $class = ref($self); push @{$Errors{$class}}, @{$Errors{$self}}; return; } sub _dump { my $self = shift; require Data::Dumper; my $dd = Data::Dumper->new([$self], ['me']); $dd->Dumpxs; } =head1 VARIABLES =head2 $GD::Graph::Error::Debug The higher this value, the more verbose error messages will be. At the moment, any true value will cause the line number and source file of the caller at the top of the stack to be included, a value of more than 2 will include the error severity, and a value of more than 5 will also include the direct caller's (i.e. the spot where the error message was generated) line number and package. Default: 0. =head2 $GD::Graph::Error::ErrorLevel Errors levels below this value will be counted as warnings, and error levels above (and inclusive) up to $CriticalLevel will be counted as errors. This is also the default error level for the C<_set_error()> method. This value should be 0 or larger, and smaller than $CriticalLevel. Default: 5. =head2 $GD::Graph::Error::CriticalLevel Any errorlevel of or above this level will immediately cause the program to die with the specified message, using Carp::croak. Default: 10. =head1 NOTES As with all Modules for Perl: Please stick to using the interface. If you try to fiddle too much with knowledge of the internals of this module, you could get burned. I may change them at any time. =head1 AUTHOR Martien Verbruggen Emgjv@tradingpost.com.auE =head2 Copyright (c) Martien Verbruggen. All rights reserved. This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO L, L =cut "Just another true value"; GDGraph-1.44/Graph/Data.pm0000644000175000001440000004145410614014571013660 0ustar benusers#========================================================================== # Copyright (c) 1995-2000 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GD::Graph::Data.pm # # $Id: Data.pm,v 1.22 2007/04/26 03:16:09 ben Exp $ # #========================================================================== package GD::Graph::Data; ($GD::Graph::Data::VERSION) = '$Revision: 1.22 $' =~ /\s([\d.]+)/; use strict; use GD::Graph::Error; @GD::Graph::Data::ISA = qw( GD::Graph::Error ); =head1 NAME GD::Graph::Data - Data set encapsulation for GD::Graph =head1 SYNOPSIS use GD::Graph::Data; =head1 DESCRIPTION This module encapsulates the data structure that is needed for GD::Graph and friends. An object of this class contains a list of X values, and a number of lists of corresponding Y values. This only really makes sense if the Y values are numerical, but you can basically store anything. Undefined values have a special meaning to GD::Graph, so they are treated with care when stored. Many of the methods of this module are intended for internal use by GD::Graph and the module itself, and will most likely not be useful to you. Many won't even I useful to you... =head1 EXAMPLES use GD::Graph::Data; use GD::Graph::bars; my $data = GD::Graph::Data->new(); $data->read(file => '/data/sales.dat', delimiter => ','); $data = $data->copy(wanted => [2, 4, 5]); # Add the newer figures from the database use DBI; # do DBI things, like connecting to the database, statement # preparation and execution while (@row = $sth->fetchrow_array) { $data->add_point(@row); } my $chart = GD::Graph::bars->new(); my $gd = $chart->plot($data); or for quick changes to legacy code # Legacy code builds array like this @data = ( [qw(Jan Feb Mar)], [1, 2, 3], [5, 4, 3], [6, 3, 7] ); # And we quickly need to do some manipulations on that my $data = GD::Graph::Data->new(); $data->copy_from(\@data); # And now do all the new stuff that's wanted. while (@foo = bar_baz()) { $data->add_point(@foo); } =head1 METHODS =head2 $data = GD::Graph::Data->new() Create a new GD::Graph::Data object. =cut # Error constants use constant ERR_ILL_DATASET => 'Illegal dataset number'; use constant ERR_ILL_POINT => 'Illegal point number'; use constant ERR_NO_DATASET => 'No data sets set'; use constant ERR_ARGS_NO_HASH => 'Arguments must be given as a hash list'; sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = []; bless $self => $class; $self->copy_from(@_) or return $self->_move_errors if (@_); return $self; } sub DESTROY { my $self = shift; $self->clear_errors(); } sub _set_value { my $self = shift; my ($nd, $np, $val) = @_; # Make sure we have empty arrays in between if ($nd > $self->num_sets) { # XXX maybe do this with splice for ($self->num_sets .. $nd - 1) { push @{$self}, []; } } $self->[$nd][$np] = $val; return $self; } =head2 $data->set_x($np, $value); Set the X value of point I<$np> to I<$value>. Points are numbered starting with 0. You probably will never need this. Returns undef on failure. =cut sub set_x { my $self = shift; $self->_set_value(0, @_); } =head2 $data->get_x($np) Get the X value of point I<$np>. See L<"set_x">. =cut sub get_x { my $self = shift; my $np = shift; return $self->_set_error(ERR_ILL_POINT) unless defined $np && $np >= 0; $self->[0][$np]; } =head2 $data->set_y($nd, $np, $value); Set the Y value of point I<$np> in data set I<$nd> to I<$value>. Points are numbered starting with 0, data sets are numbered starting with 1. You probably will never need this. Returns undef on failure. =cut sub set_y { my $self = shift; return $self->_set_error(ERR_ILL_DATASET) unless defined $_[0] && $_[0] >= 1; $self->_set_value(@_); } =head2 $data->get_y($nd, $np) Get the Y value of point I<$np> in data set I<$nd>. See L<"set_y">. This will return undef on an error, but the fact that it returns undef does not mean there was an error (since undefined values can be stored, and therefore returned). =cut sub get_y { my $self = shift; my ($nd, $np) = @_; return $self->_set_error(ERR_ILL_DATASET) unless defined $nd && $nd >= 1 && $nd <= $self->num_sets; return $self->_set_error(ERR_ILL_POINT) unless defined $np && $np >= 0; $self->[$nd][$np]; } =head2 $data->get_y_cumulative($nd, $np) Get the cumulative value of point I<$np> in data set<$nd>. The cumulative value is obtained by adding all the values of the points I<$np> in the data sets 1 to I<$nd>. =cut sub get_y_cumulative { my $self = shift; my ($nd, $np, $incl_vec) = @_; return $self->_set_error(ERR_ILL_DATASET) unless defined $nd && $nd >= 1 && $nd <= $self->num_sets; return $self->_set_error(ERR_ILL_POINT) unless defined $np && $np >= 0; my $value; my @indices = $incl_vec ? grep($_ <= $nd, @$incl_vec) : 1 .. $nd; for my $i ( @indices ) { $value += $self->[$i][$np] || 0; } return $value; } sub _get_min_max { my $self = shift; my $nd = shift; my ($min, $max); for my $val (@{$self->[$nd]}) { next unless defined $val; $min = $val if !defined $min || $val < $min; $max = $val if !defined $max || $val > $max; } return $self->_set_error("No (defined) values in " . ($nd == 0 ? "X list" : "dataset $nd")) unless defined $min && defined $max; return ($min, $max); } =head2 $data->get_min_max_x Returns a list of the minimum and maximum x value or the empty list on failure. =cut sub get_min_max_x { my $self = shift; $self->_get_min_max(0); } =head2 $data->get_min_max_y($nd) Returns a list of the minimum and maximum y value in data set $nd or the empty list on failure. =cut sub get_min_max_y { my $self = shift; my $nd = shift; return $self->_set_error(ERR_ILL_DATASET) unless defined $nd && $nd >= 1 && $nd <= $self->num_sets; $self->_get_min_max($nd); } =head2 $data->get_min_max_y_all() Returns a list of the minimum and maximum y value in all data sets or the empty list on failure. =cut sub get_min_max_y_all { my $self = shift; my ($min, $max); for (my $ds = 1; $ds <= $self->num_sets; $ds++) { my ($ds_min, $ds_max) = $self->get_min_max_y($ds); next unless defined $ds_min; $min = $ds_min if !defined $min || $ds_min < $min; $max = $ds_max if !defined $max || $ds_max > $max; } return $self->_set_error('No (defined) values in any data set') unless defined $min && defined $max; return ($min, $max); } # Undocumented, not part of interface right now. Might expose at later # point in time. sub set_point { my $self = shift; my $np = shift; return $self->_set_error(ERR_ILL_POINT) unless defined $np && $np >= 0; for (my $ds = 0; $ds < @_; $ds++) { $self->_set_value($ds, $np, $_[$ds]); } return $self; } =head2 $data->add_point($X, $Y1, $Y2 ...) Adds a point to the data set. The base for the addition is the current number of X values. This means that if you have a data set with the contents (X1, X2) (Y11, Y12) (Y21) (Y31, Y32, Y33, Y34) a $data->add_point(Xx, Y1x, Y2x, Y3x, Y4x) will result in (X1, X2, Xx ) (Y11, Y12, Y1x) (Y21, undef, Y2x) (Y31, Y32, Y3x, Y34) (undef, undef, Y4x) In other words: beware how you use this. As long as you make sure that all data sets are of equal length, this method is safe to use. =cut sub add_point { my $self = shift; $self->set_point(scalar $self->num_points, @_); } =head2 $data->num_sets() Returns the number of data sets. =cut sub num_sets { my $self = shift; @{$self} - 1; } =head2 $data->num_points() In list context, returns a list with its first element the number of X values, and the subsequent elements the number of respective Y values for each data set. In scalar context returns the number of points that have an X value set, i.e. the number of data sets that would result from a call to C. =cut sub num_points { my $self = shift; return (0) unless @{$self}; wantarray ? map { scalar @{$_} } @{$self} : scalar @{$self->[0]} } =head2 $data->x_values() Return a list of all the X values. =cut sub x_values { my $self = shift; return $self->_set_error(ERR_NO_DATASET) unless @{$self}; @{$self->[0]}; } =head2 $data->y_values($nd) Return a list of the Y values for data set I<$nd>. Data sets are numbered from 1. Returns the empty list if $nd is out of range, or if the data set at $nd is empty. =cut sub y_values { my $self = shift; my $nd = shift; return $self->_set_error(ERR_ILL_DATASET) unless defined $nd && $nd >= 1 && $nd <= $self->num_sets; return $self->_set_error(ERR_NO_DATASET) unless @{$self}; @{$self->[$nd]}; } =head2 $data->reset() OR GD::Graph::Data->reset() As an object method: Reset the data container, get rid of all data and error messages. As a class method: get rid of accumulated error messages and possible other crud. =cut sub reset { my $self = shift; @{$self} = () if ref($self); $self->clear_errors(); return $self; } =head2 $data->make_strict() Make all data set lists the same length as the X list by truncating data sets that are too long, and filling data sets that are too short with undef values. always returns a true value. =cut sub make_strict { my $self = shift; for my $ds (1 .. $self->num_sets) { my $data_set = $self->[$ds]; my $short = $self->num_points - @{$data_set}; next if $short == 0; if ($short > 0) { my @fill = (undef) x $short; push @{$data_set}, @fill; } else { splice @{$data_set}, $short; } } return $self; } =head2 $data->cumulate(preserve_undef => boolean) The B parameter will summarise the Y value sets as follows: the first Y value list will be unchanged, the second will contain a sum of the first and second, the third will contain the sum of first, second and third, and so on. Returns undef on failure. if the argument I is set to a true value, then the sum of exclusively undefined values will be preserved as an undefined value. If it is not present or a false value, undef will be treated as zero. Note that this still will leave undefined values in the first data set alone. Note: Any non-numerical defined Y values will be treated as 0, but you really shouldn't be using this to store that sort of Y data. =cut sub cumulate { my $self = shift; return $self->_set_error(ERR_ARGS_NO_HASH) if (@_ && @_ % 2); my %args = @_; # For all the sets, starting at the last one, ending just # before the first for (my $ds = $self->num_sets; $ds > 1; $ds--) { # For each point in the set for my $point (0 .. $#{$self->[$ds]}) { # Add the value for each point in lower sets to this one for my $i (1 .. $ds - 1) { # If neither are defined, we want to preserve the # undefinedness of this point. If we don't do this, then # the mathematical operation will force undef to be a 0. next if $args{preserve_undef} && ! defined $self->[$ds][$point] && ! defined $self->[$i][$point]; $self->[$ds][$point] += $self->[$i][$point] || 0; } } } return $self; } =head2 $data->wanted(indexes) Removes all data sets except the ones in the argument list. It will also reorder the data sets in the order given. Returns undef on failure. To remove all data sets except the first, sixth and second, in that order: $data->wanted(1, 6, 2) or die $data->error; =cut sub wanted { my $self = shift; for my $wanted (@_) { return $self->_set_error("Wanted index $wanted out of range 1-" . $self->num_sets) if $wanted < 1 || $wanted > $self->num_sets; } @{$self} = @{$self}[0, @_]; return $self; } =head2 $data->reverse Reverse the order of the data sets. =cut sub reverse { my $self = shift; @{$self} = ($self->[0], reverse @{$self}[1..$#{$self}]); return $self; } =head2 $data->copy_from($data_ref) Copy an 'old' style GD::Graph data structure or another GD::Graph::Data object into this object. This will remove the current data. Returns undef on failure. =cut sub copy_from { my $self = shift; my $data = shift; return $self->_set_error('Not a valid source data structure') unless defined $data && ( ref($data) eq 'ARRAY' || ref($data) eq __PACKAGE__); $self->reset; my $i = 0; for my $data_set (@{$data}) { return $self->_set_error("Invalid data set: $i") unless ref($data_set) eq 'ARRAY'; push @{$self}, [@{$data_set}]; $i++; } return $self; } =head2 $data->copy() Returns a copy of the object, or undef on failure. =cut sub copy { my $self = shift; my $new = $self->new(); $new->copy_from($self); return $new; } =head2 $data->read(I) Read a data set from a file. This will remove the current data. returns undef on failure. This method uses the standard module Text::ParseWords to parse lines. If you don't have this for some odd reason, don't use this method, or your program will die. B: The default data file format is tab separated data (which can be changed with the delimiter argument). Comment lines are any lines that start with a #. In the following example I have replaced literal tabs with for clarity # This is a comment, and will be ignored Jan1224 Feb1337 # March is missing Mar Apr918 Valid arguments are: I, mandatory. The file name of the file to read from, or a reference to a file handle or glob. $data->read(file => '/data/foo.dat') or die $data->error; $data->read(file => \*DATA) or die $data->error; $data->read(file => $file_handle) or die $data->error; I, optional. Give this a true value if you don't want lines with an initial # to be skipped. $data->read(file => '/data/foo.dat', no_comment => 1); I, optional. A regular expression that will become the delimiter instead of a single tab. $data->read(file => '/data/foo.dat', delimiter => '\s+'); $data->read(file => '/data/foo.dat', delimiter => qr/\s+/); =cut sub read { my $self = shift; return $self->_set_error(ERR_ARGS_NO_HASH) if (@_ && @_ % 2); my %args = @_; return $self->_set_error('Missing required argument: file') unless $args{file}; my $delim = $args{delimiter} || "\t"; $self->reset(); # The following will die if these modules are not present, as # documented. require Text::ParseWords; my $fh; local *FH; if (UNIVERSAL::isa($args{file}, "GLOB")) { $fh = $args{file}; } else { # $fh = \do{ local *FH }; # Odd... This dumps core, sometimes in 5.005 $fh = \*FH; # XXX Need this for perl 5.005 open($fh, $args{file}) or return $self->_set_error("open ($args{file}): $!"); } while (my $line = <$fh>) { chomp $line; next if $line =~ /^#/ && !$args{no_comment}; my @fields = Text::ParseWords::parse_line($delim, 1, $line); next unless @fields; $self->add_point(@fields); } return $self; } =head2 $data->error() OR GD::Graph::Data->error() Returns a list of all the errors that the current object has accumulated. In scalar context, returns the last error. If called as a class method it works at a class level. This method is inherited, see L for more information. =cut =head2 $data->has_error() OR GD::Graph::Data->has_error() Returns true if the object (or class) has errors pending, false if not. In some cases (see L<"copy">) this is the best way to check for errors. This method is inherited, see L for more information. =cut =head1 NOTES As with all Modules for Perl: Please stick to using the interface. If you try to fiddle too much with knowledge of the internals of this module, you could get burned. I may change them at any time. Specifically, I probably won't always keep this implemented as an array reference. =head1 AUTHOR Martien Verbruggen Emgjv@tradingpost.com.auE =head2 Copyright (c) Martien Verbruggen. All rights reserved. This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO L, L =cut "Just another true value"; GDGraph-1.44/Graph/area.pm0000644000175000001440000000564410614014571013720 0ustar benusers#========================================================================== # Copyright (c) 1995-2000 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GD::Graph::area.pm # # $Id: area.pm,v 1.17 2007/04/26 03:16:09 ben Exp $ # #========================================================================== package GD::Graph::area; ($GD::Graph::area::VERSION) = '$Revision: 1.17 $' =~ /\s([\d.]+)/; use strict; use GD::Graph::axestype; @GD::Graph::area::ISA = qw( GD::Graph::axestype ); # PRIVATE sub draw_data_set { my $self = shift; # object reference my $ds = shift; # number of the data set my @values = $self->{_data}->y_values($ds) or return $self->_set_error("Impossible illegal data set: $ds", $self->{_data}->error); # Select a data colour my $dsci = $self->set_clr($self->pick_data_clr($ds)); my $brci = $self->set_clr($self->pick_border_clr($ds)); # Create a new polygon my $poly = GD::Polygon->new(); my (@top,@bottom); # Add the data points for (my $i = 0; $i < @values; $i++) { my $value = $values[$i]; next unless defined $value; my $bottom = $self->_get_bottom($ds, $i); $value = $self->{_data}->get_y_cumulative($ds, $i) if $self->{cumulate}; my ($x, $y) = $self->val_to_pixel($i + 1, $value, $ds); push @top, [$x, $y]; # Need to keep track of this stuff for hotspots, and because # it's the only reliable way of closing the polygon, without # making odd assumptions. push @bottom, [$x, $bottom]; # Hotspot stuff # XXX needs fixing. Not used at the moment. next unless defined $self->{_hotspots}->[$ds]->[$i]; if ($i == 0) { $self->{_hotspots}->[$ds]->[$i] = ["poly", $x, $y, $x , $bottom, $x - 1, $bottom, $x - 1, $y, $x, $y]; } else { $self->{_hotspots}->[$ds]->[$i] = ["poly", $poly->getPt($i), @{$bottom[$i]}, @{$bottom[$i-1]}, $poly->getPt($i-1), $poly->getPt($i)]; } } foreach my $pair (@top, reverse @bottom) { $poly->addPt( @$pair ); } # Draw a filled and a line polygon $self->{graph}->filledPolygon($poly, $dsci) if defined $dsci; $self->{graph}->polygon($poly, $brci) if defined $brci; # Draw the accent lines if (defined $brci && ($self->{right} - $self->{left})/@values > $self->{accent_treshold}) { for my $i ( 0 .. $#top ) { my ($x, $y) = @{$top[$i]}; my $bottom = $bottom[$i]->[1]; $self->{graph}->dashedLine($x, $y, $x, $bottom, $brci); } } return $ds } "Just another true value"; GDGraph-1.44/Graph/axestype.pm0000644000175000001440000017004310614014571014646 0ustar benusers#========================================================================== # Copyright (c) 1995-1998 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GD::Graph::axestype.pm # # $Id: axestype.pm,v 1.45 2007/04/26 03:16:09 ben Exp $ # #========================================================================== package GD::Graph::axestype; ($GD::Graph::axestype::VERSION) = '$Revision: 1.45 $' =~ /\s([\d.]+)/; use strict; use GD::Graph; use GD::Graph::utils qw(:all); use Carp; @GD::Graph::axestype::ISA = qw(GD::Graph); use constant PI => 4 * atan2(1,1); my %Defaults = ( # Set the length for the 'short' ticks on the axes. x_tick_length => 4, y_tick_length => 4, # Do you want ticks to span the entire width of the graph? x_long_ticks => 0, y_long_ticks => 0, # Number of ticks for the y axis y_tick_number => 5, x_tick_number => undef, # CONTRIB Scott Prahl x_tick_offset => 0, # CONTRIB Damon Brodi # Skip every nth label. if 1 will print every label on the axes, # if 2 will print every second, etc.. x_label_skip => 1, y_label_skip => 1, # Do we want ticks on the x axis? x_ticks => 1, x_all_ticks => 0, # Where to place the x and y labels x_label_position => 3/4, y_label_position => 1/2, # vertical printing of x labels x_labels_vertical => 0, # Draw axes as a box? (otherwise just left and bottom) box_axis => 1, # Disable axes? # undef -> all axes, 0 -> Only line for bars, other -> no axes at all. no_axes => undef, # Use two different axes for the first and second dataset. The first # will be displayed using the left axis, the second using the right # axis. You cannot use more than two datasets when this option is on. two_axes => 0, # Which axis to use for each dataset. This only is in effect when # two_axes is true. The axis number will wrap around, just like # the dclrs array. use_axis => [1, 2], # Print values on the axes? x_plot_values => 1, y_plot_values => 1, # Space between axis and text axis_space => 4, # Do you want bars to be drawn on top of each other, or side by side? overwrite => 0, # This will replace 'overwrite = 2'. For now, it is hardcoded to set # overwrite to 2 cumulate => 0, # Do you want me to correct the width of the graph, so that bars are # always drawn with a nice integer number of pixels? # # The GD::Graph::bars::initialise sub will switch this on. # Do not set this to anything else than undef! correct_width => undef, # XXX The following two need to get better defaults. Maybe computed. # Draw the zero axis in the graph in case there are negative values zero_axis => 0, # Draw the zero axis, but do not draw the bottom axis, in case # box-axis == 0 # This also moves the x axis labels to the zero axis zero_axis_only => 0, # Size of the legend markers legend_marker_height => 8, legend_marker_width => 12, legend_spacing => 4, legend_placement => 'BC', # '[BR][LCR]' lg_cols => undef, # Display the y values above the bar or point in the graph. show_values => undef, values_vertical => undef, # vertical? values_space => 4, # extra spacing values_format => undef, # how to format the value # Draw the X axis left and the y1 axis at the bottom (y2 at top) rotate_chart => undef, # CONTRIB Edwin Hildebrand # How narrow is a dataset allowed to become before we drop the # accents? accent_treshold => 4, # Format of the numbers on the x and y axis y_number_format => undef, y1_number_format => undef, # CONTRIB Andrew OBrien y2_number_format => undef, # CONTRIB Andrew OBrien x_number_format => undef, # CONTRIB Scott Prahl # and some attributes without default values x_label => undef, y_label => undef, y1_label => undef, y2_label => undef, x_min_value => undef, x_max_value => undef, y_min_value => undef, y1_min_value => undef, y2_min_value => undef, y_max_value => undef, y1_max_value => undef, y2_max_value => undef, y_min_range => undef, # CONTRIB Ben Tilly y1_min_range => undef, y2_min_range => undef, borderclrs => undef, # XXX # Multiple inheritance (linespoints and mixed) finally bit me. The # _has_defaults and set methods can only work correctly when the # spot where the defaults are kept are in a mutual parent, which # would be this. The odd implementation of SUPER doesn't help # XXX points # The size of the marker to use in the points and linespoints graphs # in pixels marker_size => 4, # attributes with no default markers => undef, # XXX lines # The width of the line to use in the lines and linespoints graphs # in pixels line_width => 1, # Set the scale of the line types line_type_scale => 8, # Which line types to use line_types => [1], # Skip undefined values, and don't draw them at all skip_undef => 0, # XXX bars # Spacing between the bars and groups of bars bar_width => undef, bar_spacing => 0, bargroup_spacing=> 0, # CONTRIB Grant McLean # cycle through colours per data point, not set cycle_clrs => 0, # colour of the shadow shadowclr => 'dgray', shadow_depth => 0, # XXX mixed default_type => 'lines', types => undef, ); sub _has_default { my $self = shift; my $attr = shift || return; exists $Defaults{$attr} || $self->SUPER::_has_default($attr); } sub initialise { my $self = shift; $self->SUPER::initialise(); while (my($key, $val) = each %Defaults) { $self->{$key} = $val } $self->set_x_label_font(GD::gdSmallFont); $self->set_y_label_font(GD::gdSmallFont); $self->set_x_axis_font(GD::gdTinyFont); $self->set_y_axis_font(GD::gdTinyFont); $self->set_legend_font(GD::gdTinyFont); $self->set_values_font(GD::gdTinyFont); } # PUBLIC sub plot { my $self = shift; my $data = shift; $self->check_data($data) or return; $self->init_graph() or return; $self->setup_text() or return; $self->setup_legend(); $self->setup_coords() or return; $self->draw_text(); unless (defined $self->{no_axes}) { $self->draw_axes(); $self->draw_ticks() or return; } $self->draw_data() or return; $self->draw_values() or return; $self->draw_legend(); return $self->{graph} } sub set { my $self = shift; my %args = @_; for (keys %args) { /^tick_length$/ and do { $self->{x_tick_length} = $self->{y_tick_length} = $args{$_}; delete $args{$_}; next; }; /^long_ticks$/ and do { $self->{x_long_ticks} = $self->{y_long_ticks} = $args{$_}; delete $args{$_}; next; }; /^overwrite$/ and do { $self->{cumulate} = 1 if $args{$_} == 2; $self->{overwrite} = $args{$_}; delete $args{$_}; next; }; /^cumulate$/ and do { $self->{cumulate} = $args{$_}; # XXX And for now $self->{overwrite} = 2 if $args{$_}; delete $args{$_}; next; }; } return $self->SUPER::set(%args); } sub setup_text { my $self = shift; $self->{gdta_x_label}->set(colour => $self->{lci}); $self->{gdta_y_label}->set(colour => $self->{lci}); $self->{xlfh} = $self->{gdta_x_label}->get('height'); $self->{ylfh} = $self->{gdta_y_label}->get('height'); $self->{gdta_x_axis}->set(colour => $self->{alci}); $self->{gdta_y_axis}->set(colour => $self->{alci}); $self->{xafh} = $self->{gdta_x_axis}->get('height'); $self->{yafh} = $self->{gdta_x_axis}->get('height'); $self->{gdta_title}->set(colour => $self->{tci}); $self->{gdta_title}->set_align('top', 'center'); $self->{tfh} = $self->{gdta_title}->get('height'); $self->{gdta_legend}->set(colour => $self->{legendci}); $self->{gdta_legend}->set_align('top', 'left'); $self->{lgfh} = $self->{gdta_legend}->get('height'); $self->{gdta_values}->set(colour => $self->{valuesci}); unless ($self->{rotate_chart}) { if ($self->{values_vertical}) { $self->{gdta_values}->set_align('center', 'left'); } else { $self->{gdta_values}->set_align('bottom', 'center'); } } else { if ($self->{values_vertical}) { $self->{gdta_values}->set_align('top', 'center'); } else { $self->{gdta_values}->set_align('center', 'left'); } } return $self; } sub set_x_label_font # (fontname) { my $self = shift; $self->_set_font('gdta_x_label', @_); } sub set_y_label_font # (fontname) { my $self = shift; $self->_set_font('gdta_y_label', @_); } sub set_x_axis_font # (fontname) { my $self = shift; $self->_set_font('gdta_x_axis', @_); } sub set_y_axis_font # (fontname) { my $self = shift; $self->_set_font('gdta_y_axis', @_); } sub set_values_font { my $self = shift; $self->_set_font('gdta_values', @_); } sub set_legend # List of legend keys { my $self = shift; $self->{legend} = [@_]; } sub set_legend_font # (font name) { my $self = shift; $self->_set_font('gdta_legend', @_); } sub get_hotspot { my $self = shift; my $ds = shift; # Which data set my $np = shift; # Which data point? if (defined $np && defined $ds) { return @{$self->{_hotspots}->[$ds]->[$np]}; } elsif (defined $ds) { return @{$self->{_hotspots}->[$ds]}; } else { return @{$self->{_hotspots}}; } } sub _set_feature_coords { my $self = shift; my $feature = shift; my $type = shift; $self->{_feat_coords}->{$feature} = [ $type, @_ ]; } sub _set_text_feature_coords { my $self = shift; my $feature = shift; $self->_set_feature_coords($feature, "rect", @_[0,1,4,5]); } sub get_feature_coordinates { my $self = shift; my $feature = shift; if ($feature) { $self->{_feat_coords}->{$feature}; } else { $self->{_feat_coords}; } } # PRIVATE # inherit check_data from GD::Graph # # calculate the bottom of the bounding box for the graph # sub setup_bottom_boundary { my $self = shift; $self->{bottom} = $self->{height} - $self->{b_margin} - 1; if (! $self->{rotate_chart}) { # X label $self->{bottom} -= $self->{xlfh} + $self->{text_space} if $self->{xlfh}; # X axis tick labels $self->{bottom} -= $self->{x_label_height} + $self->{axis_space} if $self->{xafh}; } else { # Y1 label $self->{bottom} -= $self->{ylfh} + $self->{text_space} if $self->{y1_label}; # Y1 axis labels $self->{bottom} -= $self->{y_label_height}[1] + $self->{axis_space} if $self->{y_label_height}[1]; } } # # Calculate the top of the bounding box for the graph # sub setup_top_boundary { my $self = shift; $self->{top} = $self->{t_margin}; # Chart title $self->{top} += $self->{tfh} + $self->{text_space} if $self->{tfh}; if (! $self->{rotate_chart}) { # Make sure the text for the y axis tick markers fits on the canvas $self->{top} = $self->{yafh}/2 if $self->{top} == 0; } else { if ($self->{two_axes}) { # Y2 label $self->{top} += $self->{ylfh} + $self->{text_space} if $self->{y2_label}; # Y2 axis labels $self->{top} += $self->{y_label_height}[2] + $self->{axis_space} if $self->{y_label_height}[2]; } } } # # calculate the left of the bounding box for the graph # sub setup_left_boundary { my $self = shift; $self->{left} = $self->{l_margin}; if (! $self->{rotate_chart}) { # Y1 label $self->{left} += $self->{ylfh} + $self->{text_space} if $self->{y1_label}; # Y1 axis labels $self->{left} += $self->{y_label_len}[1] + $self->{axis_space} if $self->{y_label_len}[1]; } else { # X label $self->{left} += $self->{xlfh} + $self->{text_space} if $self->{x_label}; # X axis labels $self->{left} += $self->{x_label_width} + $self->{axis_space} if $self->{x_label_width}; } } # # calculate the right of the bounding box for the graph # sub setup_right_boundary { my $self = shift; $self->{right} = $self->{width} - $self->{r_margin} - 1; if (! $self->{rotate_chart}) { if ($self->{two_axes}) { # Y2 label $self->{right} -= $self->{ylfh} + $self->{text_space} if $self->{y2_label}; # Y2 axis label $self->{right} -= $self->{y_label_len}[2] + $self->{axis_space} if $self->{y_label_len}[2]; } } else { # Adjust right margin to allow last label of y axes. Only do # this when the right margin doesn't have enough space # already. # # TODO Don't assume rightmost label is the same as the # longest label (stored in y_label_len) The worst that can # happen now is that we reserve too much space. my $max_len = $self->{y_label_len}[1]; if ($self->{two_axes}) { $max_len = $self->{y_label_len}[2] if $self->{y_label_len}[2] > $max_len; } $max_len = int ($max_len/2); if ($self->{right} + $max_len >= $self->{width} - $self->{r_margin}) { $self->{right} -= $max_len; } } } sub _setup_boundaries { my $self = shift; $self->setup_bottom_boundary(); $self->setup_top_boundary(); $self->setup_left_boundary(); $self->setup_right_boundary(); if ($self->correct_width && !$self->{x_tick_number}) { if (! $self->{rotate_chart}) { # Make sure we have a nice integer number of pixels $self->{r_margin} += ($self->{right} - $self->{left}) % ($self->{_data}->num_points + 1); $self->setup_right_boundary(); } else { # Make sure we have a nice integer number of pixels $self->{b_margin} += ($self->{bottom} - $self->{top}) % ($self->{_data}->num_points + 1); $self->setup_bottom_boundary(); } } return $self->_set_error('Vertical size too small') if $self->{bottom} <= $self->{top}; return $self->_set_error('Horizontal size too small') if $self->{right} <= $self->{left}; return $self; } # This method should return 1 if the width of the graph needs to be # corrected to whole integers, and 0 if not. The default behaviour is to # not correct the width. Individual classes should override this by # setting the $self->{correct_width} attribute in their initialise # method. Only in complex cases (see mixed.pm) should this method be # overridden sub correct_width { $_[0]->{correct_width} } sub setup_x_step_size_v { my $s = shift; # calculate the step size for x data # CONTRIB Changes by Scott Prahl if (defined $s->{x_tick_number}) { my $delta = ($s->{right} - $s->{left})/($s->{x_max} - $s->{x_min}); # 'True' numerical X axis addition # From: Gary Deschaines if (defined($s->{x_min_value}) && defined($s->{x_max_value})) { $s->{x_offset} = $s->{left}; $s->{x_step} = $delta; } else { $s->{x_offset} = ($s->{true_x_min} - $s->{x_min}) * $delta + $s->{left}; $s->{x_step} = ($s->{true_x_max} - $s->{true_x_min}) * $delta/($s->{_data}->num_points - 1); } } else { $s->{x_step} = ($s->{right} - $s->{left})/($s->{_data}->num_points + 1); $s->{x_offset} = $s->{left}; } } sub setup_x_step_size_h { my $s = shift; # calculate the step size for x data # CONTRIB Changes by Scott Prahl if (defined $s->{x_tick_number}) { my $delta = ($s->{bottom} - $s->{top})/($s->{x_max} - $s->{x_min}); # 'True' numerical X axis addition # From: Gary Deschaines if (defined($s->{x_min_value}) && defined($s->{x_max_value})) { $s->{x_offset} = $s->{top}; $s->{x_step} = $delta; } else { $s->{x_offset} = ($s->{true_x_min} - $s->{x_min}) * $delta + $s->{top}; $s->{x_step} = ($s->{true_x_max} - $s->{true_x_min}) * $delta/($s->{_data}->num_points - 1); } } else { $s->{x_step} = ($s->{bottom} - $s->{top})/($s->{_data}->num_points + 1); $s->{x_offset} = $s->{top}; } } sub setup_coords { my $s = shift; # Do some sanity checks $s->{two_axes} = 0 if $s->{_data}->num_sets < 2 || $s->{two_axes} < 0; $s->{two_axes} = 1 if $s->{two_axes} > 1; delete $s->{y_label2} unless $s->{two_axes}; # Set some heights for text $s->{tfh} = 0 unless $s->{title}; $s->{xlfh} = 0 unless $s->{x_label}; # Make sure the y1 axis has a label if there is one set for y in # general $s->{y1_label} = $s->{y_label} if !$s->{y1_label} && $s->{y_label}; # Set axis tick text heights and widths to 0 if they don't need to # be plotted. $s->{xafh} = 0, $s->{xafw} = 0 unless $s->{x_plot_values}; $s->{yafh} = 0, $s->{yafw} = 0 unless $s->{y_plot_values}; # Calculate minima and maxima for the axes $s->set_max_min() or return; # Create the labels for the axes, and calculate the max length $s->create_y_labels(); $s->create_x_labels(); # CONTRIB Scott Prahl # Calculate the boundaries of the chart $s->_setup_boundaries() or return; # CONTRIB Scott Prahl # make sure that we can generate valid x tick marks undef($s->{x_tick_number}) if $s->{_data}->num_points < 3; undef($s->{x_tick_number}) if !defined $s->{x_max} || !defined $s->{x_min} || $s->{x_max} == $s->{x_min}; $s->{rotate_chart} ? $s->setup_x_step_size_h() : $s->setup_x_step_size_v(); # get the zero axis level my ($zl, $zb) = $s->val_to_pixel(0, 0, 1); my ($min,$val,$max) = $s->{rotate_chart} ? ( $s->{left}, $zl, $s->{right} ) : ( $s->{top}, $zb, $s->{bottom} ); $s->{zeropoint} = $min > $val ? $min : $max < $val ? $max : $val; # More sanity checks $s->{x_label_skip} = 1 if $s->{x_label_skip} < 1; $s->{y_label_skip} = 1 if $s->{y_label_skip} < 1; $s->{y_tick_number} = 1 if $s->{y_tick_number} < 1; return $s; } sub create_y_labels { my $self = shift; # XXX This should really be y_label_width $self->{y_label_len}[$_] = 0 for 1, 2; $self->{y_label_height}[$_] = 0 for 1, 2; for my $t (0 .. $self->{y_tick_number}) { # XXX Ugh, why did I ever do it this way? How bloody obscure. for my $axis (1 .. ($self->{two_axes} + 1)) { my $label = $self->{y_min}[$axis] + $t * ($self->{y_max}[$axis] - $self->{y_min}[$axis]) / $self->{y_tick_number}; $self->{y_values}[$axis][$t] = $label; if (my ($fmt) = grep defined, map($self->{"y${_}_number_format"},$axis,'') ) { $label = ref $fmt eq 'CODE' ? $fmt->($label) : sprintf($fmt, $label); } $self->{gdta_y_axis}->set_text($label); my $len = $self->{gdta_y_axis}->get('width'); $self->{y_labels}[$axis][$t] = $label; # TODO Allow vertical y labels $self->{y_label_len}[$axis] = $len if $len > $self->{y_label_len}[$axis]; $self->{y_label_height}[$axis] = $self->{yafh}; } } } sub get_x_axis_label_length { my $self = shift; my @values = $self->{x_tick_number} ? @{$self->{x_values}} : $self->{_data}->x_values; my $maxlen = 0; foreach my $label (@values) { $self->{gdta_x_axis}->set_text($label); my $len = $self->{gdta_x_axis}->get('width'); $maxlen = $len if $maxlen < $len; } return $maxlen; } # CONTRIB Scott Prahl sub create_x_labels { my $self = shift; my $maxlen = 0; $self->{x_label_height} = 0; $self->{x_label_width} = 0; if (defined $self->{x_tick_number}) { # We want to emulate numerical x axes foreach my $t (0..$self->{x_tick_number}) { my $label = $self->{x_min} + $t * ($self->{x_max} - $self->{x_min})/$self->{x_tick_number}; $self->{x_values}[$t] = $label; if (defined $self->{x_number_format}) { $label = ref $self->{x_number_format} eq 'CODE' ? &{$self->{x_number_format}}($label) : sprintf($self->{x_number_format}, $label); } $self->{gdta_x_label}->set_text($label); my $len = $self->{gdta_x_label}->get('width'); $self->{x_labels}[$t] = $label; $maxlen = $len if $len > $self->{x_label_height}; } } else { $maxlen = $self->get_x_axis_label_length; } $self->{x_label_height} = $self->{x_labels_vertical} ? $maxlen : $self->{xafh}; $self->{x_label_width} = $self->{x_labels_vertical} ? $self->{xafh} : $maxlen; } # # The drawing of labels for the axes. This is split up in the four # positions a label can appear in, depending on a few settings. These # settings are all dealt with in the draw_x_labels and draw_y_labels # subroutines, which in turn call the approriate directional label # drawer # sub draw_left_label { my ($self, $label, $align) = @_; $label->set_align('top', 'left'); my $tx = $self->{l_margin}; my $ty = $self->{bottom} - $align * ($self->{bottom} - $self->{top}) + $align * $label->get('width'); $label->draw($tx, $ty, PI/2); } sub draw_bottom_label { my ($self, $label, $align) = @_; $label->set_align('bottom', 'left'); my $tx = $self->{left} + $align * ($self->{right} - $self->{left}) - $align * $label->get('width'); my $ty = $self->{height} - $self->{b_margin}; $label->draw($tx, $ty, 0); } sub draw_top_label { my ($self, $label, $align) = @_; $label->set_align('top', 'left'); my $tx = $self->{left} + $align * ($self->{right} - $self->{left}) - $align * $label->get('width'); my $ty = $self->{t_margin}; $ty += $self->{tfh} + $self->{text_space} if $self->{tfh}; $label->draw($tx, $ty, 0); } sub draw_right_label { my ($self, $label, $align) = @_; $label->set_align('bottom', 'left'); my $tx = $self->{width} - $self->{r_margin}; my $ty = $self->{bottom} - $align * ($self->{bottom} - $self->{top}) + $align * $label->get('width'); $label->draw($tx, $ty, PI/2); } sub draw_x_label { my $self = shift; my ($tx, $ty, $a); my @coords; # coordinates of the label drawn return unless $self->{x_label}; $self->{gdta_x_label}->set_text($self->{x_label}); if ($self->{rotate_chart}) { @coords = $self->draw_left_label($self->{gdta_x_label}, $self->{x_label_position}); } else { @coords = $self->draw_bottom_label($self->{gdta_x_label}, $self->{x_label_position}); } $self->_set_text_feature_coords("x_label", @coords); } sub draw_y_labels { my $self = shift; my @coords; # coordinates of the labels drawn if (defined $self->{y1_label}) { $self->{gdta_y_label}->set_text($self->{y1_label}); if ($self->{rotate_chart}) { @coords = $self->draw_bottom_label($self->{gdta_y_label}, $self->{y_label_position}); } else { @coords = $self->draw_left_label($self->{gdta_y_label}, $self->{y_label_position}); } $self->_set_text_feature_coords("y1_label", @coords); $self->_set_text_feature_coords("y_label", @coords); } if ( $self->{two_axes} && defined $self->{y2_label} ) { $self->{gdta_y_label}->set_text($self->{y2_label}); if ($self->{rotate_chart}) { @coords = $self->draw_top_label($self->{gdta_y_label}, $self->{y_label_position}); } else { @coords = $self->draw_right_label($self->{gdta_y_label}, $self->{y_label_position}); } $self->_set_text_feature_coords("y2_label", @coords); } } sub draw_text { my $self = shift; if ($self->{title}) { my $xc = $self->{left} + ($self->{right} - $self->{left})/2; $self->{gdta_title}->set_align('top', 'center'); $self->{gdta_title}->set_text($self->{title}); my @coords = $self->{gdta_title}->draw($xc, $self->{t_margin}); $self->_set_text_feature_coords("title", @coords); } $self->draw_x_label(); $self->draw_y_labels(); } sub draw_axes { my $self = shift; my ($l, $r, $b, $t) = ( $self->{left}, $self->{right}, $self->{bottom}, $self->{top} ); # Sanity check for zero_axis and zero_axis_only unless ($self->{y_min}[1] < 0 && $self->{y_max}[1] > 0) { $self->{zero_axis} = 0; $self->{zero_axis_only} = 0; } if ( $self->{box_axis} ) { $self->{graph}->filledRectangle($l+1, $t+1, $r-1, $b-1, $self->{boxci}) if $self->{boxci}; $self->{graph}->rectangle($l, $t, $r, $b, $self->{fgci}); } else { $self->{graph}->line($l, $t, $l, $b, $self->{fgci}); $self->{graph}->line($l, $b, $r, $b, $self->{fgci}) unless ($self->{zero_axis_only}); $self->{graph}->line($r, $b, $r, $t, $self->{fgci}) if ($self->{two_axes}); } if ($self->{zero_axis} or $self->{zero_axis_only}) { my ($x, $y) = $self->val_to_pixel(0, 0, 1); $self->{graph}->line($l, $y, $r, $y, $self->{fgci}); } $self->_set_feature_coords("axes", "rect", $l, $b, $r, $t); } # # Ticks and values for y axes # sub draw_y_ticks_h { my $self = shift; for my $t (0 .. $self->{y_tick_number}) { for my $axis (1 .. ($self->{two_axes} + 1)) { my $value = $self->{y_values}[$axis][$t]; my $label = $self->{y_labels}[$axis][$t]; my ($x, $y) = $self->val_to_pixel(0, $value, -$axis); $y = ($axis == 1) ? $self->{bottom} : $self->{top}; if ($self->{y_long_ticks}) { $self->{graph}->line( $x, $self->{bottom}, $x, $self->{top}, $self->{fgci} ) unless ($axis-1); } else { $self->{graph}->line( $x, $y, $x, $y - $self->{y_tick_length}, $self->{fgci} ); } next if $t % ($self->{y_label_skip}) || ! $self->{y_plot_values}; $self->{gdta_y_axis}->set_text($label); if ($axis == 1) { $self->{gdta_y_axis}->set_align('top', 'center'); $y += $self->{axis_space}; } else { $self->{gdta_y_axis}->set_align('bottom', 'center'); $y -= $self->{axis_space}; } $self->{gdta_y_axis}->draw($x, $y); } } return $self; } sub draw_y_ticks_v { my $self = shift; for my $t (0 .. $self->{y_tick_number}) { # XXX Ugh, why did I ever do it this way? How bloody obscure. for my $axis (1 .. ($self->{two_axes} + 1)) { my $value = $self->{y_values}[$axis][$t]; my $label = $self->{y_labels}[$axis][$t]; my ($x, $y) = $self->val_to_pixel(0, $value, -$axis); $x = ($axis == 1) ? $self->{left} : $self->{right}; if ($self->{y_long_ticks}) { $self->{graph}->line( $x, $y, $x + $self->{right} - $self->{left}, $y, $self->{fgci} ) unless ($axis-1); } else { $self->{graph}->line( $x, $y, $x + (3 - 2 * $axis) * $self->{y_tick_length}, $y, $self->{fgci} ); } next if $t % ($self->{y_label_skip}) || ! $self->{y_plot_values}; $self->{gdta_y_axis}->set_text($label); if ($axis == 1) { $self->{gdta_y_axis}->set_align('center', 'right'); $x -= $self->{axis_space}; } else { $self->{gdta_y_axis}->set_align('center', 'left'); $x += $self->{axis_space}; } $self->{gdta_y_axis}->draw($x, $y); } } return $self; } sub draw_y_ticks { #TODO Clean this up! $_[0]->{rotate_chart} ? goto &draw_y_ticks_h : goto &draw_y_ticks_v; } # # Ticks and values for x axes # sub draw_x_ticks_h { my $self = shift; for (my $i = 0; $i < $self->{_data}->num_points; $i++) { my ($x, $y) = $self->val_to_pixel($i + 1, 0, 1); $x = $self->{left} unless $self->{zero_axis_only}; # CONTRIB Damon Brodie for x_tick_offset next if (!$self->{x_all_ticks} and ($i - $self->{x_tick_offset}) % $self->{x_label_skip} and $i != $self->{_data}->num_points - 1 ); if ($self->{x_ticks}) { if ($self->{x_long_ticks}) { $self->{graph}->line($self->{left}, $y, $self->{right}, $y, $self->{fgci}); } else { $self->{graph}->line( $x, $y, $x + $self->{x_tick_length}, $y, $self->{fgci}); } } # CONTRIB Damon Brodie for x_tick_offset next if ($i - $self->{x_tick_offset}) % ($self->{x_label_skip}) and $i != $self->{_data}->num_points - 1; my $text = $self->{_data}->get_x($i); if (defined $text) { $self->{gdta_x_axis}->set_text($text); my $angle = 0; if ($self->{x_labels_vertical}) { $self->{gdta_x_axis}->set_align('bottom', 'center'); $angle = PI/2; } else { $self->{gdta_x_axis}->set_align('center', 'right'); } $self->{gdta_x_axis}->draw($x - $self->{axis_space}, $y, $angle); } elsif ($INC{'warnings.pm'} && warnings::enabled('uninitialized') || $^W ) { carp("Uninitialized label value at index $i"); } } return $self; } sub draw_x_ticks_v { my $self = shift; for (my $i = 0; $i < $self->{_data}->num_points; $i++) { my ($x, $y) = $self->val_to_pixel($i + 1, 0, 1); $y = $self->{bottom} unless $self->{zero_axis_only}; # CONTRIB Damon Brodie for x_tick_offset next if (!$self->{x_all_ticks} and ($i - $self->{x_tick_offset}) % $self->{x_label_skip} and $i != $self->{_data}->num_points - 1 ); if ($self->{x_ticks}) { if ($self->{x_long_ticks}) { $self->{graph}->line($x, $self->{bottom}, $x, $self->{top}, $self->{fgci}); } else { $self->{graph}->line($x, $y, $x, $y - $self->{x_tick_length}, $self->{fgci}); } } # CONTRIB Damon Brodie for x_tick_offset next if ($i - $self->{x_tick_offset}) % ($self->{x_label_skip}) and $i != $self->{_data}->num_points - 1; my $text = $self->{_data}->get_x($i); if (defined $text) { $self->{gdta_x_axis}->set_text($text); my $angle = 0; if ($self->{x_labels_vertical}) { $self->{gdta_x_axis}->set_align('center', 'right'); $angle = PI/2; } else { $self->{gdta_x_axis}->set_align('top', 'center'); } $self->{gdta_x_axis}->draw($x, $y + $self->{axis_space}, $angle); } elsif ($INC{'warnings.pm'} && warnings::enabled('uninitialized') || $^W ) { carp("Uninitialized label value at index $i"); } } return $self; } sub draw_x_ticks { #TODO Clean this up! $_[0]->{rotate_chart} ? goto &draw_x_ticks_h : goto &draw_x_ticks_v; } # CONTRIB Scott Prahl # Assume x array contains equally spaced x-values # and generate an appropriate axis # #### # 'True' numerical X axis addition # From: Gary Deschaines # # These modification to draw_x_ticks_number pass x-tick values to the # val_to_pixel subroutine instead of x-tick indices when ture numerical # x-axis mode is detected. Also, x_tick_offset and x_label_skip are # processed differently when true numerical x-axis mode is detected to # allow labeled major x-tick marks and un-labeled minor x-tick marks. # # For example: # # x_tick_number => 14, # x_ticks => 1, # x_long_ticks => 1, # x_tick_length => -4, # x_min_value => 100, # x_max_value => 800, # x_tick_offset => 2, # x_label_skip => 2, # # # ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ # | | | | | | | | | | | | | # 1 -| | | | | | | | | | | | | # | | | | | | | | | | | | | # 0 _|_________|____|____|____|____|____|____|____|____|____|____|_________| # | | | | | | | | | | | # 200 300 400 500 600 700 sub draw_x_ticks_number { my $self = shift; for my $i (0 .. $self->{x_tick_number}) { my ($value, $x, $y); if (defined($self->{x_min_value}) && defined($self->{x_max_value})) { next if ($i - $self->{x_tick_offset}) < 0; next if ($i + $self->{x_tick_offset}) > $self->{x_tick_number}; $value = $self->{x_values}[$i]; ($x, $y) = $self->val_to_pixel($value, 0, 1); } else { $value = ($self->{_data}->num_points - 1) * ($self->{x_values}[$i] - $self->{true_x_min}) / ($self->{true_x_max} - $self->{true_x_min}); ($x, $y) = $self->val_to_pixel($value + 1, 0, 1); } $y = $self->{bottom} unless $self->{zero_axis_only}; if ($self->{x_ticks}) { if ($self->{x_long_ticks}) { # XXX This mod needs to be done everywhere ticks are # drawn if ( $self->{x_tick_length} >= 0 ) { $self->{graph}->line($x, $self->{bottom}, $x, $self->{top}, $self->{fgci}); } else { $self->{graph}->line( $x, $self->{bottom} - $self->{x_tick_length}, $x, $self->{top}, $self->{fgci}); } } else { $self->{graph}->line($x, $y, $x, $y - $self->{x_tick_length}, $self->{fgci} ); } } # If we have to skip labels, we'll do it here. # Make sure to always draw the last one. next if $i % $self->{x_label_skip} && $i != $self->{x_tick_number}; $self->{gdta_x_axis}->set_text($self->{x_labels}[$i]); if ($self->{x_labels_vertical}) { $self->{gdta_x_axis}->set_align('center', 'right'); my $yt = $y + $self->{text_space}/2; $self->{gdta_x_axis}->draw($x, $yt, PI/2); } else { $self->{gdta_x_axis}->set_align('top', 'center'); my $yt = $y + $self->{text_space}/2; $self->{gdta_x_axis}->draw($x, $yt); } } return $self; } sub draw_ticks { my $self = shift; $self->draw_y_ticks() or return; return $self unless $self->{x_plot_values}; if (defined $self->{x_tick_number}) { $self->draw_x_ticks_number() or return; } else { $self->draw_x_ticks() or return; } return $self; } sub draw_data { my $self = shift; # Calculate bar_spacing from bar_width if ($self->{bar_width}) { my $chart_width = !$self->{rotate_chart} ? $self->{right} - $self->{left} : $self->{bottom} - $self->{top}; my $n_bars = $self->{_data}->num_points; my $n_sets = $self->{_data}->num_sets; my $bar_space = $chart_width/($n_bars + 1) / ($self->{overwrite} ? 1 : $n_sets); $self->{bar_spacing} = $bar_space - $self->{bar_width}; $self->{bar_spacing} = 0 if $self->{bar_spacing} < 0; } # XXX is this comment still pertinent? # The drawing of 'cumulated' sets needs to be done in reverse, # for area and bar charts. This is mainly because of backward # compatibility for (my $dsn = 1; $dsn <= $self->{_data}->num_sets; $dsn++) { $self->draw_data_set($dsn) or return; } return $self } # # Draw the values of the data point with the bars, lines or markers sub draw_values { my $self = shift; return $self unless $self->{show_values}; my $text_angle = $self->{values_vertical} ? PI/2 : 0; my (@bars,@others); if ($self->isa('GD::Graph::mixed') ) { # 1-indexed, like data-sets themselves my @types = $self->types; push @{'bars' eq $types[$_ - 1] ? \@bars : \@others}, $_ for 1 .. @types; $self->GD::Graph::bars::draw_values(@bars) if @bars; } else { @others = 1 .. $self->{_data}->num_sets; } foreach my $dsn ( @others ) { my @values = $self->{_data}->y_values($dsn) or return $self->_set_error("Impossible illegal data set: $dsn", $self->{_data}->error); my @display = $self->{show_values}->y_values($dsn) or next; for (my $i = 0; $i < @values; $i++) { next unless defined $display[$i]; my ($xp, $yp); if (defined($self->{x_min_value}) && defined($self->{x_max_value})) { ($xp, $yp) = $self->val_to_pixel( $self->{_data}->get_x($i), $values[$i], $dsn); } else { ($xp, $yp) = $self->val_to_pixel($i+1, $values[$i], $dsn); } $yp -= $self->{values_space}; my $value = $display[$i]; if (defined $self->{values_format}) { $value = ref $self->{values_format} eq 'CODE' ? &{$self->{values_format}}($value) : sprintf($self->{values_format}, $value); } $self->{gdta_values}->set_text($value); $self->{gdta_values}->draw($xp, $yp, $text_angle); } } return $self } # # draw_data_set is in sub classes # sub draw_data_set { # ABSTRACT my $self = shift; $self->die_abstract( "sub draw_data missing, ") } # # This method corrects the minimum and maximum y values for chart # types that need to always include a zero point. # This is supposed to be called before the methods that pick # good-looking values. # # Input: current minimum and maximum. # Output: new minimum and maximum. # sub _correct_y_min_max { my $self = shift; my ($min, $max) = @_; # Make sure bars and area always have a zero offset # Only bars and areas need return ($min, $max) unless $self->isa("GD::Graph::bars") or $self->isa("GD::Graph::area"); # If either $min or $max are 0, we can return return ($min, $max) if $max == 0 or $min == 0; # If $min and $max on opposite end of zero axis, no work needed return ($min, $max) unless $min/$max > 0; if ($min > 0) { $min = 0; } else { $max = 0; } return ($min, $max); } # # Figure out the maximum values for the vertical exes, and calculate # a more or less sensible number for the tops. # sub set_max_min { my $self = shift; # XXX fix to calculate min and max for each data set # independently, and store in an array. Then, based on use_axis, # pick the minimust and maximust for each axis, and use those. # First, calculate some decent values if ( $self->{two_axes} ) { # XXX this is almost certainly a bug: this key is not set anywhere my $min_range_1 = defined($self->{min_range_1}) ? $self->{min_range_1} : $self->{min_range}; my $min_range_2 = defined($self->{min_range_2}) ? $self->{min_range_2} : $self->{min_range}; my(@y_min, @y_max); for my $nd (1 .. $self->{_data}->num_sets) { my $axis = $self->{use_axis}->[$nd - 1]; my($y_min, $y_max) = $self->{_data}->get_min_max_y($nd); if (!defined $y_min[$axis] || $y_min[$axis] > $y_min) { $y_min[$axis] = $y_min; } if (!defined $y_max[$axis] || $y_max[$axis] < $y_max) { $y_max[$axis] = $y_max; } } ( $self->{y_min}[1], $self->{y_max}[1], $self->{y_min}[2], $self->{y_max}[2], $self->{y_tick_number} ) = _best_dual_ends( $self->_correct_y_min_max($y_min[1], $y_max[1]), $min_range_1, $self->_correct_y_min_max($y_min[2], $y_max[2]), $min_range_2, $self->{y_tick_number} ); } else { my ($y_min, $y_max); if ($self->{cumulate}) { my $data_set = $self->{_data}->copy(); $data_set->cumulate; ($y_min, $y_max) = $data_set->get_min_max_y($data_set->num_sets); } else { ($y_min, $y_max) = $self->{_data}->get_min_max_y_all; } ($y_min, $y_max) = $self->_correct_y_min_max($y_min, $y_max); ($self->{y_min}[1], $self->{y_max}[1], $self->{y_tick_number}) = _best_ends($y_min, $y_max, @$self{'y_tick_number','y_min_range'}); } if (defined($self->{x_tick_number})) { if (defined($self->{x_min_value}) && defined($self->{x_max_value})) { $self->{true_x_min} = $self->{x_min_value}; $self->{true_x_max} = $self->{x_max_value}; } else { ($self->{true_x_min}, $self->{true_x_max}) = $self->{_data}->get_min_max_x; ($self->{x_min}, $self->{x_max}, $self->{x_tick_number}) = _best_ends($self->{true_x_min}, $self->{true_x_max}, @$self{'x_tick_number','x_min_range'}); } } # Overwrite these with any user supplied ones $self->{y_min}[1] = $self->{y_min_value} if defined $self->{y_min_value}; $self->{y_min}[2] = $self->{y_min_value} if defined $self->{y_min_value}; $self->{y_max}[1] = $self->{y_max_value} if defined $self->{y_max_value}; $self->{y_max}[2] = $self->{y_max_value} if defined $self->{y_max_value}; $self->{y_min}[1] = $self->{y1_min_value} if defined $self->{y1_min_value}; $self->{y_max}[1] = $self->{y1_max_value} if defined $self->{y1_max_value}; $self->{y_min}[2] = $self->{y2_min_value} if defined $self->{y2_min_value}; $self->{y_max}[2] = $self->{y2_max_value} if defined $self->{y2_max_value}; $self->{x_min} = $self->{x_min_value} if defined $self->{x_min_value}; $self->{x_max} = $self->{x_max_value} if defined $self->{x_max_value}; if ($self->{two_axes}) { # If we have two axes, we need to make sure that the zero is at # the same spot. # And we need to change the number of ticks on the axes my $l_range = $self->{y_max}[1] - $self->{y_min}[1]; my $r_range = $self->{y_max}[2] - $self->{y_min}[2]; my $l_top = $self->{y_max}[1]/$l_range; my $r_top = $self->{y_max}[2]/$r_range; my $l_bot = $self->{y_min}[1]/$l_range; my $r_bot = $self->{y_min}[2]/$r_range; if ($l_top > $r_top) { $self->{y_max}[2] = $l_top * $r_range; $self->{y_min}[1] = $r_bot * $l_range; $self->{y_tick_number} *= 1 + abs $r_bot - $l_bot; } else { $self->{y_max}[1] = $r_top * $l_range; $self->{y_min}[2] = $l_bot * $r_range; $self->{y_tick_number} *= 1 + abs $r_top - $l_top; } } # Check to see if we have sensible values if ($self->{two_axes}) { for my $i (1 .. $self->{_data}->num_sets) { my ($min, $max) = $self->{_data}->get_min_max_y($i); return $self->_set_error("Minimum for y" . $i . " too large") if $self->{y_min}[$self->{use_axis}[$i-1]] > $min; return $self->_set_error("Maximum for y" . $i . " too small") if $self->{y_max}[$self->{use_axis}[$i-1]] < $max; } } return $self; } # CONTRIB Scott Prahl # # Calculate best endpoints and number of intervals for an axis and # returns ($nice_min, $nice_max, $n), where $n is the number of # intervals and # # $nice_min <= $min < $max <= $nice_max # # Usage: # ($nmin,$nmax,$nint) = _best_ends(247, 508); # ($nmin,$nmax) = _best_ends(247, 508, 5); # use 5 intervals # ($nmin,$nmax,$nint) = _best_ends(247, 508, [4..7]); # best of 4,5,6,7 intervals # ($nmin,$nmax,$nint) = _best_ends(247, 508, 'auto'); # best of 3,4,5,6 intervals # ($nmin,$nmax,$nint) = _best_ends(247, 508, [2..5]); # best of 2,3,4,5 intervals sub _best_ends { my ($min, $max, $n_ref, $min_range) = @_; # Adjust for the min range if need be ($min, $max) = _fit_vals_range($min, $max, $min_range); my ($best_min, $best_max, $best_num) = ($min, $max, 1); # Check that min and max are not the same, and not 0 ($min, $max) = ($min) ? ($min * 0.5, $min * 1.5) : (-1,1) if ($max == $min); # mgjv - Sometimes, for odd values, and only one data set, this will be # necessary _after_ the previous step, not before. Data sets of one # long with negative values were causing infinite loops later on. ($min, $max) = ($max, $min) if ($min > $max); my @n = ref($n_ref) ? @$n_ref : $n_ref; if (@n <= 0) { @n = (3..6); } else { @n = map { ref($_) ? @$_ : /(\d+)/i ? $1 : (3..6) } @n; } my $best_fit = 1e30; my $range = $max - $min; # create array of interval sizes my $s = 1; while ($s < $range) { $s *= 10 } while ($s > $range) { $s /= 10 } my @step = map {$_ * $s} (0.2, 0.5, 1, 2, 5); for my $n (@n) { # Try all numbers of intervals next if ($n < 1); for my $step (@step) { next if ($n != 1) and ($step < $range/$n) || ($step <= 0); # $step too small my ($nice_min, $nice_max, $fit) = _fit_interval($min, $max, $n, $step); next if $best_fit <= $fit; $best_min = $nice_min; $best_max = $nice_max; $best_fit = $fit; $best_num = $n; } } return ($best_min, $best_max, $best_num) } # CONTRIB Ben Tilly # # Calculate best endpoints and number of intervals for a pair of axes # where it is trying to line up the scale of the two intervals. It # returns ($nice_min_1, $nice_max_1, $nice_min_2, $nice_max_2, $n), # where $n is the number of intervals and # # $nice_min_1 <= $min_1 < $max_1 <= $nice_max_1 # $nice_min_2 <= $min_2 < $max_2 <= $nice_max_2 # # and 0 will appear at the same point on both axes. # # Usage: # ($nmin_1,$nmax_1,$nmin_2,$nmax_2,$nint) = _best_dual_ends(247, 508, undef, -1, 5, undef, [2..5]); # etc. (The usage of the last arguments just parallels _best_ends.) # sub _best_dual_ends { my ($min_1, $max_1) = _fit_vals_range(splice @_, 0, 3); my ($min_2, $max_2) = _fit_vals_range(splice @_, 0, 3); my @rem_args = @_; # Fix the situation where both min_1 and max_1 are 0, which makes it # loop forever ($min_1, $max_1) = (0, 1) unless $min_1 or $max_1; my $scale_1 = _max(abs($min_1), abs($max_1)); my $scale_2 = _max(abs($min_2), abs($max_2)); $scale_1 = defined($scale_2) ? $scale_2 : 1 unless defined($scale_1); $scale_2 = $scale_1 unless defined($scale_2); my $ratio = $scale_1 / ($scale_2 || 1); my $fact_1 = my $fact_2 = 1; while ($ratio < sqrt(0.1)) { $ratio *= 10; $fact_2 *= 10; } while ($ratio > sqrt(10)) { $ratio /= 10; $fact_1 *= 10; } my ($best_min_1, $best_max_1, $best_min_2, $best_max_2, $best_n, $best_fit) = ($min_1, $max_1, $min_2, $max_2, 1, 1e10); # Now try all of the ratios of "simple numbers" in the right size-range foreach my $frac ( [1,1], [1,2], [1,3], [2,1], [2,3], [2,5], [3,1], [3,2], [3,4], [3,5], [3,8], [3,10], [4,3], [4,5], [5,2], [5,3], [5,4], [5,6], [5,8], [6,5], [8,3], [8,5], [10,3] ) { my $bfact_1 = $frac->[0] * $fact_1; my $bfact_2 = $frac->[1] * $fact_2; my $min = _min( $min_1/$bfact_1, $min_2/$bfact_2 ); my $max = _max( $max_1/$bfact_1, $max_2/$bfact_2 ); my ($bmin, $bmax, $n) = _best_ends($min, $max, @rem_args); my ($bmin_1, $bmax_1) = ($bfact_1*$bmin, $bfact_1*$bmax); my ($bmin_2, $bmax_2) = ($bfact_2*$bmin, $bfact_2*$bmax); my $fit = _measure_interval_fit($bmin_1, $min_1, $max_1, $bmax_1) + _measure_interval_fit($bmin_2, $min_2, $max_2, $bmax_2); next if $best_fit < $fit; ( $best_min_1, $best_max_1, $best_min_2, $best_max_2, $best_n, $best_fit ) = ( $bmin_1, $bmax_1, $bmin_2, $bmax_2, $n, $fit ); } return ($best_min_1, $best_max_1, $best_min_2, $best_max_2, $best_n); } # Takes $min, $max, $step_count, $step_size. Assumes $min <= $max and both # $step_count and $step_size are positive. Returns the fitted $min, $max, # and a $fit statistic (where smaller is better). Failure to fit the # interval results in a poor fit statistic. :-) sub _fit_interval { my ($min, $max, $step_count, $step_size) = @_; my $nice_min = $step_size * int($min/$step_size); $nice_min -= $step_size if ($nice_min > $min); my $nice_max = ($step_count == 1) ? $step_size * int($max/$step_size + 1) : $nice_min + $step_count * $step_size; my $fit = _measure_interval_fit($nice_min, $min, $max, $nice_max); # Prevent division by zero errors further up return ($min, $max, 0) if ($step_size == 0); return ($nice_min, $nice_max, $fit); } # Takes 2 values and a minimum range. Returns a min and max which holds # both values and is at least that minimum size sub _fit_vals_range { my ($min, $max, $min_range) = @_; ($min, $max) = ($max, $min) if $max < $min; if (defined($min_range) and $min_range > $max - $min) { my $nice_min = $min_range * int($min/$min_range); $nice_min = $nice_min - $min_range if $min < $nice_min; my $nice_max = $max < $nice_min + $min_range ? $nice_min + $min_range : $max; ($min, $max) = ($nice_min, $nice_max); } return (0+$min, 0+$max); } # Takes $bmin, $min, $max, $bmax and returns a fit statistic for how well # ($bmin, $bmax) encloses the interval ($min, $max). Smaller is better, # and failure to fit will be a very bad fit. Assumes that $min <= $max # and $bmin < $bmax. sub _measure_interval_fit { my ($bmin, $min, $max, $bmax) = @_; return 1000 if $bmin > $min or $bmax < $max; my $range = $max - $min; my $brange = $bmax - $bmin; return $brange < 10 * $range ? ($brange / $range) : 10; } sub _get_bottom { my $self = shift; my ($ds, $np) = @_; my $bottom = $self->{zeropoint}; if ($self->{cumulate} && $ds > 1) { my $left; my $pvalue = $self->{_data}->get_y_cumulative($ds - 1, $np); ($left, $bottom) = $self->val_to_pixel($np + 1, $pvalue, $ds); $bottom = $left if $self->{rotate_chart}; } return $bottom; } # # Convert value coordinates to pixel coordinates on the canvas. # TODO Clean up all the rotate_chart stuff # sub val_to_pixel # ($x, $y, $dataset) or ($x, $y, -$axis) in real coords { # return [x, y] in pixel coords my $self = shift; my ($x, $y, $i) = @_; # XXX use_axis my $axis = 1; if ( $self->{two_axes} ) { $axis = $i < 0 ? -$i : $self->{use_axis}[$i - 1]; } my $y_min = $self->{y_min}[$axis]; my $y_max = $self->{y_max}[$axis]; my $y_range = ($y_max - $y_min) || 1; # XXX the above might be an appropriate place for a conditional warning my $y_step = $self->{rotate_chart} ? abs(($self->{right} - $self->{left}) / $y_range) : abs(($self->{bottom} - $self->{top}) / $y_range); my $ret_x; my $origin = $self->{rotate_chart} ? $self->{top} : $self->{left}; if (defined($self->{x_min_value}) && defined($self->{x_max_value})) { $ret_x = $origin + ($x - $self->{x_min}) * $self->{x_step}; } else { $ret_x = ($self->{x_tick_number} ? $self->{x_offset} : $origin) + $x * $self->{x_step}; } my $ret_y = $self->{rotate_chart} ? $self->{left} + ($y - $y_min) * $y_step : $self->{bottom} - ($y - $y_min) * $y_step; return $self->{rotate_chart} ? (_round($ret_y), _round($ret_x)) : (_round($ret_x), _round($ret_y)); } # # Legend # sub setup_legend { my $self = shift; return unless defined $self->{legend}; my $maxlen = 0; my $num = 0; # Save some variables $self->{r_margin_abs} = $self->{r_margin}; $self->{b_margin_abs} = $self->{b_margin}; foreach my $legend (@{$self->{legend}}) { if (defined($legend) and $legend ne "") { $self->{gdta_legend}->set_text($legend); my $len = $self->{gdta_legend}->get('width'); $maxlen = ($maxlen > $len) ? $maxlen : $len; $num++; } last if $num >= $self->{_data}->num_sets; } $self->{lg_num} = $num or return; # not actually bug 20792 (unsure that this will ever get hit, but if it does..!) # calculate the height and width of each element my $legend_height = _max($self->{lgfh}, $self->{legend_marker_height}); $self->{lg_el_width} = $maxlen + $self->{legend_marker_width} + 3 * $self->{legend_spacing}; $self->{lg_el_height} = $legend_height + 2 * $self->{legend_spacing}; my ($lg_pos, $lg_align) = split(//, $self->{legend_placement}); if ($lg_pos eq 'R') { # Always work in one column $self->{lg_cols} = 1; $self->{lg_rows} = $num; # Just for completeness, might use this in later versions $self->{lg_x_size} = $self->{lg_cols} * $self->{lg_el_width}; $self->{lg_y_size} = $self->{lg_rows} * $self->{lg_el_height}; # Adjust the right margin for the rest of the graph $self->{r_margin} += $self->{lg_x_size}; # Set the x starting point $self->{lg_xs} = $self->{width} - $self->{r_margin}; # Set the y starting point, depending on alignment if ($lg_align eq 'T') { $self->{lg_ys} = $self->{t_margin}; } elsif ($lg_align eq 'B') { $self->{lg_ys} = $self->{height} - $self->{b_margin} - $self->{lg_y_size}; } else # default 'C' { my $height = $self->{height} - $self->{t_margin} - $self->{b_margin}; $self->{lg_ys} = int($self->{t_margin} + $height/2 - $self->{lg_y_size}/2) ; } } else # 'B' is the default { # What width can we use my $width = $self->{width} - $self->{l_margin} - $self->{r_margin}; (!defined($self->{lg_cols})) and $self->{lg_cols} = int($width/$self->{lg_el_width}) || 1; # bug 20792 $self->{lg_cols} = _min($self->{lg_cols}, $num); $self->{lg_rows} = int($num / $self->{lg_cols}) + (($num % $self->{lg_cols}) ? 1 : 0); $self->{lg_x_size} = $self->{lg_cols} * $self->{lg_el_width}; $self->{lg_y_size} = $self->{lg_rows} * $self->{lg_el_height}; # Adjust the bottom margin for the rest of the graph $self->{b_margin} += $self->{lg_y_size}; # Set the y starting point $self->{lg_ys} = $self->{height} - $self->{b_margin}; # Set the x starting point, depending on alignment if ($lg_align eq 'R') { $self->{lg_xs} = $self->{width} - $self->{r_margin} - $self->{lg_x_size}; } elsif ($lg_align eq 'L') { $self->{lg_xs} = $self->{l_margin}; } else # default 'C' { $self->{lg_xs} = int($self->{l_margin} + $width/2 - $self->{lg_x_size}/2); } } } sub draw_legend { my $self = shift; return unless defined $self->{legend}; my $xl = $self->{lg_xs} + $self->{legend_spacing}; my $y = $self->{lg_ys} + $self->{legend_spacing} - 1; my $i = 0; my $row = 1; my $x = $xl; # start position of current element foreach my $legend (@{$self->{legend}}) { $i++; last if $i > $self->{_data}->num_sets; my $xe = $x; # position within an element next unless defined($legend) && $legend ne ""; $self->draw_legend_marker($i, $xe, $y); $xe += $self->{legend_marker_width} + $self->{legend_spacing}; my $ys = int($y + $self->{lg_el_height}/2 - $self->{lgfh}/2); $self->{gdta_legend}->set_text($legend); $self->{gdta_legend}->draw($xe, $ys); $x += $self->{lg_el_width}; if (++$row > $self->{lg_cols}) { $row = 1; $y += $self->{lg_el_height}; $x = $xl; } } } # # This will be virtual; every sub class should define their own # if this one doesn't suffice # sub draw_legend_marker # data_set_number, x, y { my $s = shift; my $n = shift; my $x = shift; my $y = shift; my $g = $s->{graph}; my $ci = $s->set_clr($s->pick_data_clr($n)); return unless defined $ci; $y += int($s->{lg_el_height}/2 - $s->{legend_marker_height}/2); $g->filledRectangle( $x, $y, $x + $s->{legend_marker_width}, $y + $s->{legend_marker_height}, $ci ); $g->rectangle( $x, $y, $x + $s->{legend_marker_width}, $y + $s->{legend_marker_height}, $s->{acci} ); } "Just another true value"; GDGraph-1.44/Graph/hbars.pm0000644000175000001440000000313710347715415014112 0ustar benusers#========================================================================== # Copyright (c) 1995-1998 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GD::Graph::hbars.pm # # $Id: hbars.pm,v 1.3 2005/12/14 04:09:49 ben Exp $ # #========================================================================== package GD::Graph::hbars; ($GD::Graph::hbars::VERSION) = '$Revision: 1.3 $' =~ /\s([.\d]+)/; use strict; use GD::Graph::bars; use GD::Graph::utils qw(:all); use GD::Graph::colour qw(:colours); @GD::Graph::hbars::ISA = qw(GD::Graph::bars); sub initialise { my $self = shift; $self->SUPER::initialise(); $self->set(rotate_chart => 1); } "Just another true value"; __END__ =head1 NAME GD::Graph::hbars - make bar graphs with horizontal bars =head1 SYNOPSIS use GD::Graph::hbars; =head1 DESCRIPTION This is a wrapper module which is completely identical to creating a GD::Graph::bars object with the C attribute set to a true value. =head1 SEE ALSO L =head1 AUTHOR Martien Verbruggen Emgjv@tradingpost.com.auE =head2 Copyright (c) Martien Verbruggen =head2 Acknowledgements The original author of most of the code needed to implement this was brian d foy, who sent this module to me after I complained I didn't have the time to implement horizontal bar charts. I took the code that lived in here, and distributed it over axestype.pm and bars.pm, to allow for a better integration all around. His code, in turn, was mainly based on an earlier version of bars.pm and axestype.pm. =cut GDGraph-1.44/Graph/pie.pm0000644000175000001440000003115110614014571013555 0ustar benusers#========================================================================== # Copyright (c) 1995-1998 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GD::Graph::pie.pm # # $Id: pie.pm,v 1.21 2007/04/26 03:16:09 ben Exp $ # #========================================================================== package GD::Graph::pie; ($GD::Graph::pie::VERSION) = '$Revision: 1.21 $' =~ /\s([\d.]+)/; use strict; use constant PI => 4 * atan2(1,1); use GD; use GD::Graph; use GD::Graph::utils qw(:all); use GD::Graph::colour qw(:colours :lists); use GD::Text::Align; use Carp; @GD::Graph::pie::ISA = qw( GD::Graph ); my $ANGLE_OFFSET = 90; my %Defaults = ( # Set the height of the pie. # Because of the dependency of this on runtime information, this # is being set in GD::Graph::pie::initialise # pie_height => _round(0.1*${'width'}), pie_height => undef, # Do you want a 3D pie? '3d' => 1, # The angle at which to start the first data set # 0 is at the front/bottom start_angle => 0, # Angle below which a label on a pie slice is suppressed. suppress_angle => 0, # CONTRIB idea ryan # and some public attributes without defaults label => undef, # This misnamed attribute is used for pie marker colours axislabelclr => 'black', ); # PRIVATE sub _has_default { my $self = shift; my $attr = shift || return; exists $Defaults{$attr} || $self->SUPER::_has_default($attr); } sub initialise { my $self = shift; $self->SUPER::initialise(); while (my($key, $val) = each %Defaults) { $self->{$key} = $val } $self->set( pie_height => _round(0.1 * $self->{height}) ); $self->set_value_font(gdTinyFont); $self->set_label_font(gdSmallFont); } # PUBLIC methods, documented in pod sub plot { my $self = shift; my $data = shift; $self->check_data($data) or return; $self->init_graph() or return; $self->setup_text() or return; $self->setup_coords() or return; $self->draw_text() or return; $self->draw_pie() or return; $self->draw_data() or return; return $self->{graph}; } sub set_label_font # (fontname) { my $self = shift; $self->_set_font('gdta_label', @_) or return; $self->{gdta_label}->set_align('bottom', 'center'); } sub set_value_font # (fontname) { my $self = shift; $self->_set_font('gdta_value', @_) or return; $self->{gdta_value}->set_align('center', 'center'); } # Inherit defaults() from GD::Graph # inherit checkdata from GD::Graph # Setup the coordinate system and colours, calculate the # relative axis coordinates in respect to the canvas size. sub setup_coords() { my $self = shift; # Make sure we're not reserving space we don't need. $self->{'3d'} = 0 if $self->{pie_height} <= 0; $self->set(pie_height => 0) unless $self->{'3d'}; my $tfh = $self->{title} ? $self->{gdta_title}->get('height') : 0; my $lfh = $self->{label} ? $self->{gdta_label}->get('height') : 0; # Calculate the bounding box for the pie, and # some width, height, and centre parameters (don't forget fenceposts!) $self->{bottom} = $self->{height} - $self->{pie_height} - $self->{b_margin} - ( $lfh ? $lfh + $self->{text_space} : 0 ) - 1; $self->{top} = $self->{t_margin} + ( $tfh ? $tfh + $self->{text_space} : 0 ); return $self->_set_error('Vertical size too small') if $self->{bottom} - $self->{top} <= 0; $self->{left} = $self->{l_margin}; $self->{right} = $self->{width} - $self->{r_margin} - 1; # ensure that the center is a single pixel, not a half-pixel position $self->{right}-- if ($self->{right} - $self->{left}) % 2; $self->{bottom}-- if ($self->{bottom} - $self->{top}) % 2; return $self->_set_error('Horizontal size too small') if $self->{right} - $self->{left} <= 0; $self->{w} = $self->{right} - $self->{left} + 1; $self->{h} = $self->{bottom} - $self->{top} + 1; $self->{xc} = ($self->{right} + $self->{left})/2; $self->{yc} = ($self->{bottom} + $self->{top})/2; return $self; } # inherit open_graph from GD::Graph # Setup the parameters for the text elements sub setup_text { my $self = shift; if ( $self->{title} ) { #print "'$s->{title}' at ($s->{xc},$s->{t_margin})\n"; $self->{gdta_title}->set(colour => $self->{tci}); $self->{gdta_title}->set_text($self->{title}); } if ( $self->{label} ) { $self->{gdta_label}->set(colour => $self->{lci}); $self->{gdta_label}->set_text($self->{label}); } $self->{gdta_value}->set(colour => $self->{alci}); return $self; } # Put the text on the canvas. sub draw_text { my $self = shift; $self->{gdta_title}->draw($self->{xc}, $self->{t_margin}) if $self->{title}; $self->{gdta_label}->draw($self->{xc}, $self->{height} - $self->{b_margin}) if $self->{label}; return $self; } # draw the pie, without the data slices sub draw_pie { my $self = shift; my $left = $self->{xc} - $self->{w}/2; $self->{graph}->arc( $self->{xc}, $self->{yc}, $self->{w}, $self->{h}, 0, 360, $self->{acci} ); $self->{graph}->arc( $self->{xc}, $self->{yc} + $self->{pie_height}, $self->{w}, $self->{h}, 0, 180, $self->{acci} ) if ( $self->{'3d'} ); $self->{graph}->line( $left, $self->{yc}, $left, $self->{yc} + $self->{pie_height}, $self->{acci} ); $self->{graph}->line( $left + $self->{w}, $self->{yc}, $left + $self->{w}, $self->{yc} + $self->{pie_height}, $self->{acci} ); return $self; } # Draw the data slices sub draw_data { my $self = shift; my $total = 0; my @values = $self->{_data}->y_values(1); # for now, only one pie.. for (@values) { $total += $_ } return $self->_set_error("Pie data total is <= 0") unless $total > 0; my $ac = $self->{acci}; # Accent colour my $pb = $self->{start_angle}; for (my $i = 0; $i < @values; $i++) { # Set the data colour my $dc = $self->set_clr_uniq($self->pick_data_clr($i + 1)); # Set the angles of the pie slice # Angle 0 faces down, positive angles are clockwise # from there. # --- # / \ # | | # \ | / # --- # 0 # $pa/$pb include the start_angle (so if start_angle # is 90, there will be no pa/pb < 90. my $pa = $pb; $pb += my $slice_angle = 360 * $values[$i]/$total; # Calculate the end points of the lines at the boundaries of # the pie slice my ($xe, $ye) = cartesian( $self->{w}/2, $pa, $self->{xc}, $self->{yc}, $self->{h}/$self->{w} ); $self->{graph}->line($self->{xc}, $self->{yc}, $xe, $ye, $ac); # Draw the lines on the front of the pie $self->{graph}->line($xe, $ye, $xe, $ye + $self->{pie_height}, $ac) if in_front($pa) && $self->{'3d'}; # Make an estimate of a point in the middle of the pie slice # And fill it ($xe, $ye) = cartesian( 3 * $self->{w}/8, ($pa+$pb)/2, $self->{xc}, $self->{yc}, $self->{h}/$self->{w} ); $self->{graph}->fillToBorder($xe, $ye, $ac, $dc); # If it's 3d, colour the front ones as well # # if one slice is very large (>180 deg) then we will need to # fill it twice. sbonds. # # Independently noted and fixed by Jeremy Wadsack, in a slightly # different way. if ($self->{'3d'}) { foreach my $fill ($self->_get_pie_front_coords($pa, $pb)) { my ($fx,$fy) = @$fill; my $new_y = $fy + $self->{pie_height}/2; # Edge case (literally): if lines have converged, back up # looking for a gap to fill while ( $new_y > $fy ) { if ($self->{graph}->getPixel($fx,$new_y) != $ac) { $self->{graph}->fillToBorder($fx, $new_y, $ac, $dc); last; } } continue { $new_y-- } } } } # CONTRIB Jeremy Wadsack # # Large text, sticking out over the pie edge, could cause 3D pies to # fill improperly: Drawing the text for a given slice before the # next slice was drawn and filled could make the slice boundary # disappear, causing the fill colour to flow out. With this # implementation, all the text is on top of the pie. $pb = $self->{start_angle}; for (my $i = 0; $i < @values; $i++) { next unless $values[$i]; my $pa = $pb; $pb += my $slice_angle = 360 * $values[$i]/$total; next if $slice_angle <= $self->{suppress_angle}; my ($xe, $ye) = cartesian( 3 * $self->{w}/8, ($pa+$pb)/2, $self->{xc}, $self->{yc}, $self->{h}/$self->{w} ); $self->put_slice_label($xe, $ye, $self->{_data}->get_x($i)); } return $self; } #GD::Graph::pie::draw_data sub _get_pie_front_coords # (angle 1, angle 2) { my $self = shift; my $pa = level_angle(shift); my $pb = level_angle(shift); my @fills = (); if (in_front($pa)) { if (in_front($pb)) { # both in front # don't do anything # Ah, but if this wraps all the way around the back # then both pieces of the front need to be filled. # sbonds. if ($pa > $pb ) { # This takes care of the left bit on the front # Since we know exactly where we are, and in which # direction this works, we can just get the coordinates # for $pa. my ($x, $y) = cartesian( $self->{w}/2, $pa, $self->{xc}, $self->{yc}, $self->{h}/$self->{w} ); # and move one pixel to the left, but only if we don't # fall out of the pie!. push @fills, [$x - 1, $y] if $x - 1 > $self->{xc} - $self->{w}/2; # Reset $pa to the right edge of the front arc, to do # the right bit on the front. $pa = level_angle(-$ANGLE_OFFSET); } } else { # start in front, end in back $pb = $ANGLE_OFFSET; } } else { if (in_front($pb)) { # start in back, end in front $pa = $ANGLE_OFFSET - 180; } elsif ( # both in back, but wrapping around the front # CONTRIB kedlubnowski, Dan Rosendorf $pa > 90 && $pb > 90 && $pa >= $pb or $pa < -90 && $pb < -90 && $pa >= $pb or $pa < -90 && $pb > 90 ) { $pa=$ANGLE_OFFSET - 180; $pb=$ANGLE_OFFSET; } else { return; } } my ($x, $y) = cartesian( $self->{w}/2, ($pa + $pb)/2, $self->{xc}, $self->{yc}, $self->{h}/$self->{w} ); push @fills, [$x, $y]; return @fills; } # return true if this angle is on the front of the pie # XXX UGLY! We need to leave a slight room for error because of rounding # problems sub in_front { my $a = level_angle(shift); return $a > ($ANGLE_OFFSET - 180 + 0.00000001) && $a < $ANGLE_OFFSET - 0.000000001; } # XXX Ugh! I need to fix this. See the GD::Text module for better ways # of doing this. # return a value for angle between -180 and 180 sub level_angle # (angle) { my $a = shift; return level_angle($a-360) if ( $a > 180 ); return level_angle($a+360) if ( $a <= -180 ); return $a; } # put the slice label on the pie sub put_slice_label { my $self = shift; my ($x, $y, $label) = @_; return unless defined $label; $self->{gdta_value}->set_text($label); $self->{gdta_value}->draw($x, $y); } # return x, y coordinates from input # radius, angle, center x and y and a scaling factor (height/width) # # $ANGLE_OFFSET is used to define where 0 is meant to be sub cartesian { my ($r, $phi, $xi, $yi, $cr) = @_; return map _round($_), ( $xi + $r * cos(PI * ($phi + $ANGLE_OFFSET)/180), $yi + $cr * $r * sin(PI * ($phi + $ANGLE_OFFSET)/180) ) } "Just another true value"; GDGraph-1.44/Graph/bars.pm0000644000175000001440000002425510614014571013736 0ustar benusers#========================================================================== # Copyright (c) 1995-1998 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GD::Graph::bars.pm # # $Id: bars.pm,v 1.26 2007/04/26 03:16:09 ben Exp $ # #========================================================================== package GD::Graph::bars; ($GD::Graph::bars::VERSION) = '$Revision: 1.26 $' =~ /\s([\d.]+)/; use strict; use GD::Graph::axestype; use GD::Graph::utils qw(:all); use GD::Graph::colour qw(:colours); @GD::Graph::bars::ISA = qw(GD::Graph::axestype); use constant PI => 4 * atan2(1,1); sub initialise { my $self = shift; $self->SUPER::initialise(); $self->set(correct_width => 1); } sub draw_data { my $self = shift; $self->SUPER::draw_data() or return; unless ($self->{no_axes}) { # redraw the 'zero' axis if ($self->{rotate_chart}) { $self->{graph}->line( $self->{zeropoint}, $self->{top}, $self->{zeropoint}, $self->{bottom}, $self->{fgci} ); } else { $self->{graph}->line( $self->{left}, $self->{zeropoint}, $self->{right}, $self->{zeropoint}, $self->{fgci} ); } } return $self; } sub _top_values { my $self = shift; my @topvalues; if ($self->{cumulate}) { my $data = $self->{_data}; for my $i (0 .. $data->num_points - 1) { push @topvalues, $data->get_y_cumulative($data->num_sets, $i); } } return \@topvalues; } # # Draw the shadow # sub _draw_shadow { my $self = shift; my ($ds, $i, $value, $topvalues, $l, $t, $r, $b) = @_; my $bsd = $self->{shadow_depth} or return; my $bsci = $self->set_clr(_rgb($self->{shadowclr})); if ($self->{cumulate}) { return if $ds > 1; $value = $topvalues->[$i]; if ($self->{rotate_chart}) { $r = ($self->val_to_pixel($i + 1, $value, $ds))[0]; } else { $t = ($self->val_to_pixel($i + 1, $value, $ds))[1]; } } # XXX Clean this up if ($value >= 0) { if ($self->{rotate_chart}) { $self->{graph}->filledRectangle( $l, $t + $bsd, $r - $bsd, $b + $bsd, $bsci); } else { $self->{graph}->filledRectangle( $l + $bsd, $t + $bsd, $r + $bsd, $b, $bsci); } } else { if ($self->{rotate_chart}) { $self->{graph}->filledRectangle( $l + $bsd, $t, $r + $bsd, $b, $bsci); } else { $self->{graph}->filledRectangle( $l + $bsd, $b, $r + $bsd, $t + $bsd, $bsci); } } } sub draw_data_set_h { my $self = shift; my $ds = shift; my $bar_s = $self->{bar_spacing}/2; # Pick a data colour my $dsci = $self->set_clr($self->pick_data_clr($ds)); # contrib "Bremford, Mike" my $brci = $self->set_clr($self->pick_border_clr($ds)); my @values = $self->{_data}->y_values($ds) or return $self->_set_error("Impossible illegal data set: $ds", $self->{_data}->error); my $topvalues = $self->_top_values; for my $i (0 .. $#values) { my $value = $values[$i]; next unless defined $value; my $l = $self->_get_bottom($ds, $i); $value = $self->{_data}->get_y_cumulative($ds, $i) if ($self->{cumulate}); # CONTRIB Jeremy Wadsack # # cycle_clrs option sets the color based on the point, # not the dataset. $dsci = $self->set_clr($self->pick_data_clr($i + 1)) if $self->{cycle_clrs}; $brci = $self->set_clr($self->pick_data_clr($i + 1)) if $self->{cycle_clrs} > 1; # get coordinates of right and center of bar my ($r, $xp) = $self->val_to_pixel($i + 1, $value, $ds); # calculate top and bottom of bar my ($t, $b); my $window = $self->{x_step} - $self->{bargroup_spacing}; if (ref $self eq 'GD::Graph::mixed' || $self->{overwrite}) { $t = $xp - $window/2 + $bar_s + 1; $b = $xp + $window/2 - $bar_s; } else { $t = $xp - $window/2 + ($ds - 1) * $window/$self->{_data}->num_sets + $bar_s + 1; # GRANTM thinks this +1 should be conditional on bargroup_spacing being absent $b = $xp - $window/2 + $ds * $window/$self->{_data}->num_sets - $bar_s; } # draw the bar $self->_draw_shadow($ds, $i, $value, $topvalues, $l, $t, $r, $b); if ($value < 0) { ($r,$l) = ($l,$r) } $self->{graph}->filledRectangle($l, $t, $r, $b, $dsci) if defined $dsci; $self->{graph}->rectangle($l, $t, $r, $b, $brci) if defined $brci && $b - $t > $self->{accent_treshold}; $self->{_hotspots}->[$ds]->[$i] = ['rect', $l, $t, $r, $b]; } return $ds; } sub draw_data_set_v { my $self = shift; my $ds = shift; my $bar_s = $self->{bar_spacing}/2; # Pick a data colour my $dsci = $self->set_clr($self->pick_data_clr($ds)); # contrib "Bremford, Mike" my $brci = $self->set_clr($self->pick_border_clr($ds)); my @values = $self->{_data}->y_values($ds) or return $self->_set_error("Impossible illegal data set: $ds", $self->{_data}->error); my $topvalues = $self->_top_values; my ($bar_sets,$ds_adj) = ( $self->{_data}->num_sets , $ds ); if ( $self->isa( 'GD::Graph::mixed' ) ) { my @types = $self->types; $bar_sets = grep { $_ eq 'bars' } @types; $ds_adj = grep { $_ eq 'bars' } @types[0..$ds-1]; } for (my $i = 0; $i < @values; $i++) { my $value = $values[$i]; next unless defined $value; my $bottom = $self->_get_bottom($ds, $i); $value = $self->{_data}->get_y_cumulative($ds, $i) if ($self->{cumulate}); # CONTRIB Jeremy Wadsack # # cycle_clrs option sets the color based on the point, # not the dataset. $dsci = $self->set_clr($self->pick_data_clr($i + 1)) if $self->{cycle_clrs}; $brci = $self->set_clr($self->pick_data_clr($i + 1)) if $self->{cycle_clrs} > 1; # get coordinates of top and center of bar my ($xp, $t) = $self->val_to_pixel($i + 1, $value, $ds); # calculate left and right of bar my ($l, $r); my $window = $self->{x_step} - $self->{bargroup_spacing}; if ($self->{overwrite}) { $l = $xp - $window/2 + $bar_s + 1; $r = $xp + $window/2 - $bar_s; } else { $l = $xp - $window/2 + ($ds_adj - 1) * $window/$bar_sets + $bar_s + 1; # GRANTM thinks this +1 should be conditional on bargroup_spacing being absent $r = $xp - $window/2 + $ds_adj * $window/$bar_sets - $bar_s; } # draw the bar $self->_draw_shadow($ds, $i, $value, $topvalues, $l, $t, $r, $bottom); if ($value < 0) { ($bottom,$t) = ($t,$bottom) } $self->{graph}->filledRectangle($l, $t, $r, $bottom, $dsci) if defined $dsci; $self->{graph}->rectangle($l, $t, $r, $bottom, $brci) if defined $brci && $r - $l > $self->{accent_treshold}; $self->{_hotspots}->[$ds]->[$i] = ['rect', $l, $t, $r, $bottom] } return $ds; } sub draw_data_set { $_[0]->{rotate_chart} ? goto &draw_data_set_h : goto &draw_data_set_v; } sub draw_values { my $self = shift; return $self unless $self->{show_values}; my $has_args = @_; my $text_angle = $self->{values_vertical} ? PI/2 : 0; my @numPoints = $self->{_data}->num_points(); my @datasets = $has_args ? @_ : 1 .. $self->{_data}->num_sets; for my $dsn ( @datasets ) { # CONTRIB Romeo Juncu my @values = (); if (!$self->get("cumulate")) { @values = $self->{_data}->y_values($dsn) or return $self->_set_error("Impossible illegal data set: $dsn", $self->{_data}->error); } else { my $nPoints = $numPoints[$dsn] || 0; my $vec = $has_args ? \@datasets : undef; @values = map { $self->{_data}->get_y_cumulative($dsn, $_, $vec) } (0..$nPoints - 1) ; } my @display = $self->{show_values}->y_values($dsn) or next; for (my $i = 0; $i < @values; $i++) { next unless defined $display[$i]; my $value = $display[$i]; if (defined $self->{values_format}) { $value = ref $self->{values_format} eq 'CODE' ? &{$self->{values_format}}($value) : sprintf($self->{values_format}, $value); } my ($xp, $yp); if (defined($self->{x_min_value}) && defined($self->{x_max_value})) { ($xp, $yp) = $self->val_to_pixel( $self->{_data}->get_x($i), $values[$i], $dsn); } else { ($xp, $yp) = $self->val_to_pixel($i+1, $values[$i], $dsn); } if ($self->{rotate_chart}) { $xp += $self->{values_space}; unless ($self->{overwrite}) { $yp -= $self->{x_step}/2 - ($dsn - 0.5) * $self->{x_step}/@datasets; } } else { $yp -= $self->{values_space}; unless ($self->{overwrite}) { $xp -= $self->{x_step}/2 - ($dsn - 0.5) * $self->{x_step}/@datasets; } } $self->{gdta_values}->set_text($value); $self->{gdta_values}->draw($xp, $yp, $text_angle); } } return $self } "Just another true value"; GDGraph-1.44/Graph/colour.pm0000644000175000001440000001711410347715404014314 0ustar benusers#========================================================================== # Copyright (c) 1995-1998 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GD::Graph::colour.pm # # Description: # Package of colour manipulation routines, to be used # with GD::Graph. # # $Id: colour.pm,v 1.10 2005/12/14 04:09:40 ben Exp $ # #========================================================================== package GD::Graph::colour; ($GD::Graph::colour::VERSION) = '$Revision: 1.10 $' =~ /\s([\d.]+)/; =head1 NAME GD::Graph::colour - Colour manipulation routines for use with GD::Graph =head1 SYNOPSIS use GD::Graph::colour qw(:colours :lists :files :convert); =head1 DESCRIPTION The B package provides a few routines to work with colours. The functionality of this package is mainly defined by what is needed, now and historically, by the GD::Graph modules. =cut use vars qw( @EXPORT_OK %EXPORT_TAGS ); use strict; require Exporter; use Carp; @GD::Graph::colour::ISA = qw( Exporter ); @EXPORT_OK = qw( _rgb _luminance _hue add_colour colour_list sorted_colour_list read_rgb hex2rgb rgb2hex ); %EXPORT_TAGS = ( colours => [qw( add_colour _rgb _luminance _hue )], lists => [qw( colour_list sorted_colour_list )], files => [qw( read_rgb )], convert => [qw( hex2rgb rgb2hex )], ); my %RGB = ( white => [0xFF,0xFF,0xFF], lgray => [0xBF,0xBF,0xBF], gray => [0x7F,0x7F,0x7F], dgray => [0x3F,0x3F,0x3F], black => [0x00,0x00,0x00], lblue => [0x00,0x00,0xFF], blue => [0x00,0x00,0xBF], dblue => [0x00,0x00,0x7F], gold => [0xFF,0xD7,0x00], lyellow => [0xFF,0xFF,0x00], yellow => [0xBF,0xBF,0x00], dyellow => [0x7F,0x7F,0x00], lgreen => [0x00,0xFF,0x00], green => [0x00,0xBF,0x00], dgreen => [0x00,0x7F,0x00], lred => [0xFF,0x00,0x00], red => [0xBF,0x00,0x00], dred => [0x7F,0x00,0x00], lpurple => [0xFF,0x00,0xFF], purple => [0xBF,0x00,0xBF], dpurple => [0x7F,0x00,0x7F], lorange => [0xFF,0xB7,0x00], orange => [0xFF,0x7F,0x00], pink => [0xFF,0xB7,0xC1], dpink => [0xFF,0x69,0xB4], marine => [0x7F,0x7F,0xFF], cyan => [0x00,0xFF,0xFF], lbrown => [0xD2,0xB4,0x8C], dbrown => [0xA5,0x2A,0x2A], ); =head1 FUNCTIONS =head2 colour_list( I ) Returns a list of I colour names known to the package. Exported with the :lists tag. =cut sub colour_list { my $n = ( $_[0] ) ? $_[0] : keys %RGB; return (keys %RGB)[0 .. $n-1]; } =head2 sorted_colour_list( I ) Returns a list of I colour names known to the package, sorted by luminance or hue. B Right now it always sorts by luminance. Will add an option in a later stage to decide sorting method at run time. Exported with the :lists tag. =cut sub sorted_colour_list { my $n = $_[0] ? $_[0] : keys %RGB; return (sort by_luminance keys %RGB)[0 .. $n-1]; # return (sort by_hue keys %rgb)[0..$n-1]; sub by_luminance { _luminance(@{$RGB{$b}}) <=> _luminance(@{$RGB{$a}}) } sub by_hue { _hue(@{$RGB{$b}}) <=> _hue(@{$RGB{$a}}) } } =head2 _rgb( I ) Returns a list of the RGB values of I. if the colour name is a string of the form that is acceptable to the hex2rgb sub, then the colour will be added to the list dynamically. Exported with the :colours tag. =cut my %warned_clrs = (); # return the RGB values of the colour name sub _rgb { my $clr = shift or return; # Try adding the colour if it doesn't exist yet. It may be of a # parseable form add_colour($clr) unless exists $RGB{$clr}; my $rgb_ref = $RGB{$clr}; if (!defined $rgb_ref) { $rgb_ref = $RGB{'black'}; unless ($warned_clrs{$clr}) { $warned_clrs{$clr}++; carp "Colour $clr is not defined, reverting to black"; } }; @{$rgb_ref}; } =head2 _hue( I ) Returns the hue of the colour with the specified RGB values. Exported with the :colours tag. =head2 _luminance( I ) Returns the luminance of the colour with the specified RGB values. Exported with the :colours tag. =cut # return the luminance of the colour (RGB) sub _luminance { (0.212671 * $_[0] + 0.715160 * $_[1] + 0.072169 * $_[2])/0xFF } # return the hue of the colour (RGB) sub _hue { ($_[0] + $_[1] + $_[2])/(3 * 0xFF) } =head2 add_colour(colourname => [$r, $g, $b]) or add_colour('#7fe310') Self-explanatory. Exported with the :colours tag. =cut sub add_colour { my $name = shift; my $val = shift; if (!defined $val) { my @rgb = hex2rgb($name) or return; $val = [@rgb]; } if (ref $val && ref $val eq 'ARRAY') { $RGB{$name} = [@{$val}]; return $name; } return; } =head2 rgb2hex($red, $green, $blue) =head2 hex2rgb('#7fe310') These functions translate a list of RGB values into a hexadecimal string, as is commonly used in HTML and the Image::Magick API, and vice versa. Exported with the :convert tag. =cut # Color translation sub rgb2hex { return unless @_ == 3; my $color = '#'; foreach my $cc (@_) { $color .= sprintf("%02x", $cc); } return $color; } sub hex2rgb { my $clr = shift; my @rgb = $clr =~ /^#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/i; return unless @rgb; return map { hex $_ } @rgb; } =head2 read_rgb( F ) Reads in colours from a rgb file as used by the X11 system. Doing something like: use GD::Graph::bars; use GD::Graph::colour; GD::Graph::colour::read_rgb("rgb.txt") or die "cannot read colours"; Will allow you to use any colours defined in rgb.txt in your graph. Exported with the :files tag. =cut # # Read a rgb.txt file (X11) # # Expected format of the file: # # R G B colour name # # Fields can be separated by any number of whitespace # Lines starting with an exclamation mark (!) are comment and # will be ignored. # # returns number of colours read sub read_rgb($) # (filename) { my $fn = shift; my $n = 0; my $line; open(RGB, $fn) or return 0; while (defined($line = )) { next if ($line =~ /\s*!/); chomp($line); # remove leading white space $line =~ s/^\s+//; # get the colours my ($r, $g, $b, $name) = split(/\s+/, $line, 4); # Ignore bad lines next unless (defined $name); $RGB{$name} = [$r, $g, $b]; $n++; } close(RGB); return $n; } sub version { $GD::Graph::colour::VERSION } sub dump_colours { my $max = $_[0] ? $_[0] : keys %RGB; my $n = 0; my $clr; foreach $clr (sorted_colour_list($max)) { last if $n > $max; print "colour: $clr, " . "${$RGB{$clr}}[0], ${$RGB{$clr}}[1], ${$RGB{$clr}}[2]\n" } } "Just another true value"; __END__ =head1 PREDEFINED COLOUR NAMES white, lgray, gray, dgray, black, lblue, blue, dblue, gold, lyellow, yellow, dyellow, lgreen, green, dgreen, lred, red, dred, lpurple, purple, dpurple, lorange, orange, pink, dpink, marine, cyan, lbrown, dbrown. =head1 AUTHOR Martien Verbruggen Emgjv@tradingpost.com.auE =head2 Copyright GIFgraph: Copyright (c) 1995-1999 Martien Verbruggen. Chart::PNGgraph: Copyright (c) 1999 Steve Bonds. GD::Graph: Copyright (c) 1999 Martien Verbruggen. All rights reserved. This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO L, L GDGraph-1.44/Graph/FAQ.pod0000644000175000001440000001331310614014571013555 0ustar benusers=head1 NAME GD::Graph::FAQ - Frequently asked questions =head1 DESCRIPTION =head2 I get errors like "Can't call method METHOD on an undefined value". What gives? You probably had an error somewhere, most likely in the plot() method, and you didn't check for it. See the section on Error Handling in the documentation for L to find out how to deal with this sort of thing, and how to get more information about what the error was. =head2 I am drawing a bar chart, and the chart area is a lot smaller than the image. What is going on? As of version 1.30, GD::Graph automatically corrects the width of the plotting area of a chart if it needs to draw bars (i.e. for bars and some mixed charts). This is necessary, because rounding errors cause irregular gaps between or overlaps of bars if the bar is not an exact integer number of pixels wide. If you want the old behaviour back, set the correct_width attribute to a false value. =head2 I have my data in some format that doesn't look at all like the array that I am supposed to give to GD::Graph's plot method. Do I really need to mess around with array references? Not necessarily. Check out the GD::Graph::Data class. =head2 How do I stop those pesky accents appearing around bars or inside area charts? You can set the C option to a large enough value (larger than your chart). Alternatively, you may like it better to set the C attribute to be the same as the dclrs one. I'll probably include an option in a future version that gives better control over this. =head2 Where is the ActiveState ppm of GD::Graph? Ask them. I have asked them, but didn't get an answer. I don't know what to do to get it included in their set of ppms, and I really do not have the time to keep asking them. I believe that GD::graph has finally made it into ActiveState's ppm archive. However, I am going to leave this question here in case they get behind again. =head2 Do you have some example code for me? The distribution has a large set of examples in it. If you don't have the original distribution, please get it from CPAN (http://www.cpan.org/ or some local mirror). =head2 Will you support X or Y? If you send me a patch that (in a decent manner) adds the functionality to the latest version, I may very well add it for the next release. If you don't send me a patch, but just a question, you will have to be patient. (Please also see the section on bugs in the main body of L.) =head2 Why does export_format give me a weird string, instead of just 'png' or 'gif'? As of version 1.31, export_format in a list context returns all formats that GD can export. If you are only interested in the answer 'gif' or 'png', make sure that you call it in a scalar context. $export_format = GD::Graph->export_format; $export_format = $graph->export_format; print "Export format is ", scalar $graph->export_format, "\n"; print "Export format is " . $graph->export_format . "\n"; @export_formats = $graph->export_format; =head2 TrueType fonts don't work when I use GD::Graph from a CGI program. When your programs run as CGI, they typically do not have the same environment as when you use them from the command line. The Perl FAQ, section 9, has some information on this. It is also not guaranteed that your script runs from the directory that it is in. It is probably better to include something like: use GD::Text; GD::Text->font_path("/path/to/my/font_dir"); See the GD::Text documentation for more information about font paths. =head2 I'm trying to use GD's builtin fonts, but it's not working. Most likely, you are using the font short name, like gdGiantFont or gdMediumBoldFont, and you have not put a C in your program. This is needed, because these short names need to be exported into your name space by the GD library: use GD; # ... $graph->set_x_axis_font(gdMediumBoldFont); If you don't want to include the GD library, you can use the longer alternative names (which is what I'd recommend anyway): $graph1->set_x_axis_font(GD::Font->MediumBold); If you C then you will actually get an error message if you try to use the short names without including the GD module. Also see the L documentation for this information. =head2 When I have many data sets, some end up having the same colour. The default number of colours for data sets is seven, so if you use more than seven data sets, those colours will be re-used for the higher data sets. This is described in the entry for the C attribute in the L documentation. =head2 Can you tell me how to do X? Not necessarily (X might be kind of complicated, after all). Did you look in the samples for something similar? If not, you're probably best off seeing if you can get help from a group of people, rather than one or the other of the overworked individuals whose e-mail addresses are shown below. If you're more comfortable with asking a newsgroup for help, the canonical resource is Ecomp.lang.perl.miscE; if you prefer web forums, there is a good one at Ehttp://www.perlmonks.orgE. In either case, if you are not familiar with the forum and its denizens, you might wish to read the following helpful guide before posting your question: http://www.perlmonks.org/?node_id=172086 =head2 Can you fix this bug I've found? Well, I hope so. Please see the "BUGS" section in the main body of L for the best way to report it. =head1 AUTHOR Martien Verbruggen Emgjv@tradingpost.com.auE Current maintenance (including this release) by Benjamin Warfield Ebwarfield@cpan.orgE (c) Martien Verbruggen. All rights reserved. This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself. GDGraph-1.44/Graph/lines.pm0000644000175000001440000001053610347715714014130 0ustar benusers#========================================================================== # Copyright (c) 1995-1998 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GD::Graph::lines.pm # # $Id: lines.pm,v 1.15 2005/12/14 04:13:00 ben Exp $ # #========================================================================== package GD::Graph::lines; ($GD::Graph::lines::VERSION) = '$Revision: 1.15 $' =~ /\s([\d.]+)/; use strict; use GD; use GD::Graph::axestype; @GD::Graph::lines::ISA = qw( GD::Graph::axestype ); # PRIVATE sub draw_data_set { my $self = shift; my $ds = shift; my @values = $self->{_data}->y_values($ds) or return $self->_set_error("Impossible illegal data set: $ds", $self->{_data}->error); my $dsci = $self->set_clr($self->pick_data_clr($ds) ); my $type = $self->pick_line_type($ds); my ($xb, $yb); if (defined $values[0]) { if (defined($self->{x_min_value}) && defined($self->{x_max_value})) { ($xb, $yb) = $self->val_to_pixel($self->{_data}->get_x(0), $values[0], $ds); } else { ($xb, $yb) = $self->val_to_pixel(1, $values[0], $ds); } } for (my $i = 0; $i < @values; $i++) { if (!defined $values[$i]) { ($xb, $yb) = () if $self->{skip_undef}; next; } my ($xe, $ye); if (defined($self->{x_min_value}) && defined($self->{x_max_value})) { ($xe, $ye) = $self->val_to_pixel( $self->{_data}->get_x($i), $values[$i], $ds); } else { ($xe, $ye) = $self->val_to_pixel($i+1, $values[$i], $ds); } if (defined $xb) { $self->draw_line($xb, $yb, $xe, $ye, $type, $dsci) if defined $dsci; $self->{_hotspots}->[$ds]->[$i] = ['line', $xb, $yb, $xe, $ye, $self->{line_width}]; } ($xb, $yb) = ($xe, $ye); } return $ds; } sub pick_line_type { my $self = shift; my $num = shift; ref $self->{line_types} ? $self->{line_types}[ $num % (1 + $#{$self->{line_types}}) - 1 ] : $num % 4 ? $num % 4 : 4 } sub draw_line # ($xs, $ys, $xe, $ye, $type, $colour_index) { my $self = shift; my ($xs, $ys, $xe, $ye, $type, $clr) = @_; my $lw = $self->{line_width}; my $lts = $self->{line_type_scale}; my $style = gdStyled; my @pattern = (); LINE: { ($type == 2) && do { # dashed for (1 .. $lts) { push @pattern, $clr } for (1 .. $lts) { push @pattern, gdTransparent } $self->{graph}->setStyle(@pattern); last LINE; }; ($type == 3) && do { # dotted, for (1 .. 2) { push @pattern, $clr } for (1 .. 2) { push @pattern, gdTransparent } $self->{graph}->setStyle(@pattern); last LINE; }; ($type == 4) && do { # dashed and dotted for (1 .. $lts) { push @pattern, $clr } for (1 .. 2) { push @pattern, gdTransparent } for (1 .. 2) { push @pattern, $clr } for (1 .. 2) { push @pattern, gdTransparent } $self->{graph}->setStyle(@pattern); last LINE; }; # default: solid $style = $clr; } # Tried the line_width thing with setBrush, ugly results # TODO: This loop probably should be around the datasets # for nicer results my $i; for $i (1..$lw) { my $yslw = $ys + int($lw/2) - $i; my $yelw = $ye + int($lw/2) - $i; # Need the setstyle to reset $self->{graph}->setStyle(@pattern) if (@pattern); $self->{graph}->line( $xs, $yslw, $xe, $yelw, $style ); } } sub draw_legend_marker # (data_set_number, x, y) { my $self = shift; my ($n, $x, $y) = @_; my $ci = $self->set_clr($self->pick_data_clr($n)); return unless defined $ci; my $type = $self->pick_line_type($n); $y += int($self->{lg_el_height}/2); # Joe Smith local($self->{line_width}) = 2; # Make these show up better $self->draw_line( $x, $y, $x + $self->{legend_marker_width}, $y, $type, $ci ); } "Just another true value"; GDGraph-1.44/Graph/linespoints.pm0000644000175000001440000000227610347715724015370 0ustar benusers#========================================================================== # Copyright (c) 1995-1998 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GD::Graph::linespoints.pm # # $Id: linespoints.pm,v 1.8 2005/12/14 04:13:08 ben Exp $ # #========================================================================== package GD::Graph::linespoints; ($GD::Graph::linespoints::VERSION) = '$Revision: 1.8 $' =~ /\s([\d.]+)/; use strict; use GD::Graph::axestype; use GD::Graph::lines; use GD::Graph::points; # Even though multiple inheritance is not really a good idea, # since lines and points have the same parent class, I will do it here, # because I need the functionality of the markers and the line types @GD::Graph::linespoints::ISA = qw(GD::Graph::lines GD::Graph::points); # PRIVATE sub draw_data_set { my $self = shift; $self->GD::Graph::points::draw_data_set(@_) or return; $self->GD::Graph::lines::draw_data_set(@_); } sub draw_legend_marker { my $self = shift; $self->GD::Graph::points::draw_legend_marker(@_); $self->GD::Graph::lines::draw_legend_marker(@_); } "Just another true value"; GDGraph-1.44/Graph/utils.pm0000644000175000001440000000233610347715760014156 0ustar benusers#========================================================================== # Copyright (c) 1995-1999 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GD::Graph::utils.pm # # Description: # Package of general utilities. # # $Id: utils.pm,v 1.7 2005/12/14 04:13:36 ben Exp $ # #========================================================================== package GD::Graph::utils; ($GD::Graph::utils::VERSION) = '$Revision: 1.7 $' =~ /\s([\d.]+)/; use strict; use vars qw( @EXPORT_OK %EXPORT_TAGS ); require Exporter; @GD::Graph::utils::ISA = qw( Exporter ); @EXPORT_OK = qw(_max _min _round); %EXPORT_TAGS = (all => [qw(_max _min _round)]); sub _max { my ($a, $b) = @_; return undef if (!defined($a) and !defined($b)); return $a if (!defined($b)); return $b if (!defined($a)); ( $a >= $b ) ? $a : $b; } sub _min { my ($a, $b) = @_; return undef if (!defined($a) and !defined($b)); return $a if (!defined($b)); return $b if (!defined($a)); ( $a <= $b ) ? $a : $b; } sub _round { sprintf "%.0f", shift } sub version { $GD::Graph::utils::VERSION } "Just another true value"; GDGraph-1.44/Graph/points.pm0000644000175000001440000001176210347715754014340 0ustar benusers#========================================================================== # Copyright (c) 1995-1998 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GD::Graph::points.pm # # $Id: points.pm,v 1.13 2005/12/14 04:13:32 ben Exp $ # #========================================================================== package GD::Graph::points; ($GD::Graph::points::VERSION) = '$Revision: 1.13 $' =~ /\s([\d.]+)/; use strict; use GD::Graph::axestype; use GD::Graph::utils qw(:all); @GD::Graph::points::ISA = qw( GD::Graph::axestype ); # PRIVATE sub draw_data_set { my $self = shift; my $ds = shift; my @values = $self->{_data}->y_values($ds) or return $self->_set_error("Impossible illegal data set: $ds", $self->{_data}->error); # Pick a colour my $dsci = $self->set_clr($self->pick_data_clr($ds)); my $type = $self->pick_marker($ds); for (my $i = 0; $i < @values; $i++) { next unless defined $values[$i]; my ($xp, $yp); if (defined($self->{x_min_value}) && defined($self->{x_max_value})) { ($xp, $yp) = $self->val_to_pixel( $self->{_data}->get_x($i), $values[$i], $ds); } else { ($xp, $yp) = $self->val_to_pixel($i+1, $values[$i], $ds); } $self->marker($xp, $yp, $type, $dsci ); $self->{_hotspots}->[$ds]->[$i] = ['rect', $self->marker_coordinates($xp, $yp)]; } return $ds; } # Pick a marker type sub pick_marker # number { my $self = shift; my $num = shift; ref $self->{markers} ? $self->{markers}[ $num % (1 + $#{$self->{markers}}) - 1 ] : ($num % 8) || 8; } # Draw a marker sub marker_coordinates { my $self = shift; my ($xp, $yp) = @_; return ( $xp - $self->{marker_size}, $xp + $self->{marker_size}, $yp + $self->{marker_size}, $yp - $self->{marker_size}, ); } sub marker # $xp, $yp, $type, $colourindex { my $self = shift; my ($xp, $yp, $mtype, $mclr) = @_; return unless defined $mclr; my ($l, $r, $b, $t) = $self->marker_coordinates($xp, $yp); MARKER: { ($mtype == 1) && do { # Square, filled $self->{graph}->filledRectangle($l, $t, $r, $b, $mclr); last MARKER; }; ($mtype == 2) && do { # Square, open $self->{graph}->rectangle($l, $t, $r, $b, $mclr); last MARKER; }; ($mtype == 3) && do { # Cross, horizontal $self->{graph}->line($l, $yp, $r, $yp, $mclr); $self->{graph}->line($xp, $t, $xp, $b, $mclr); last MARKER; }; ($mtype == 4) && do { # Cross, diagonal $self->{graph}->line($l, $b, $r, $t, $mclr); $self->{graph}->line($l, $t, $r, $b, $mclr); last MARKER; }; ($mtype == 5) && do { # Diamond, filled $self->{graph}->line($l, $yp, $xp, $t, $mclr); $self->{graph}->line($xp, $t, $r, $yp, $mclr); $self->{graph}->line($r, $yp, $xp, $b, $mclr); $self->{graph}->line($xp, $b, $l, $yp, $mclr); $self->{graph}->fillToBorder($xp, $yp, $mclr, $mclr); last MARKER; }; ($mtype == 6) && do { # Diamond, open $self->{graph}->line($l, $yp, $xp, $t, $mclr); $self->{graph}->line($xp, $t, $r, $yp, $mclr); $self->{graph}->line($r, $yp, $xp, $b, $mclr); $self->{graph}->line($xp, $b, $l, $yp, $mclr); last MARKER; }; ($mtype == 7) && do { # Circle, filled $self->{graph}->arc($xp, $yp, 2 * $self->{marker_size}, 2 * $self->{marker_size}, 0, 360, $mclr); $self->{graph}->fillToBorder($xp, $yp, $mclr, $mclr); last MARKER; }; ($mtype == 8) && do { # Circle, open $self->{graph}->arc($xp, $yp, 2 * $self->{marker_size}, 2 * $self->{marker_size}, 0, 360, $mclr); last MARKER; }; ($mtype == 9) && do { # Horizontal line $self->{graph}->line($l, $yp, $r, $yp, $mclr); last MARKER; }; ($mtype == 10) && do { # vertical line $self->{graph}->line($xp, $t, $xp, $b, $mclr); last MARKER; }; } } sub draw_legend_marker { my $self = shift; my $n = shift; my $x = shift; my $y = shift; my $ci = $self->set_clr($self->pick_data_clr($n)); my $old_ms = $self->{marker_size}; my $ms = _min($self->{legend_marker_height}, $self->{legend_marker_width}); ($self->{marker_size} > $ms/2) and $self->{marker_size} = $ms/2; $x += int($self->{legend_marker_width}/2); $y += int($self->{lg_el_height}/2); $n = $self->pick_marker($n); $self->marker($x, $y, $n, $ci); $self->{marker_size} = $old_ms; } "Just another true value"; GDGraph-1.44/Graph/mixed.pm0000644000175000001440000000564710614014571014121 0ustar benusers#========================================================================== # Copyright (c) 1995-1998 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GD::Graph::mixed.pm # # $Id: mixed.pm,v 1.13 2007/04/26 03:16:09 ben Exp $ # #========================================================================== package GD::Graph::mixed; ($GD::Graph::mixed::VERSION) = '$Revision: 1.13 $' =~ /\s([\d.]+)/; use strict; use GD::Graph::axestype; use GD::Graph::lines; use GD::Graph::points; use GD::Graph::linespoints; use GD::Graph::bars; use GD::Graph::area; use Carp; # Even though multiple inheritance is not really a good idea, I will # do it here, because I need the functionality of the markers and the # line types We'll include axestype as the first one, to make sure # that's where we look first for methods. @GD::Graph::mixed::ISA = qw( GD::Graph::axestype GD::Graph::bars GD::Graph::lines GD::Graph::points ); sub initialise { my $self = shift; $self->SUPER::initialise(); } sub correct_width { my $self = shift; return $self->{correct_width} if defined $self->{correct_width}; for my $type ($self->{default_type}, @{$self->{types}}) { return 1 if $type eq 'bars'; } } sub draw_data_set { my $self = shift; my $ds = $_[0]; my $rc; my $type = $self->types($ds); # Try to execute the draw_data_set function in the package # specified by type $rc = eval '$self->GD::Graph::'.$type.'::draw_data_set(@_)'; # If we fail, we try it in the package specified by the # default_type, and warn the user if ($@) { carp "Set $ds, unknown type $type, assuming $self->{default_type}"; #carp "Error message: $@"; $rc = eval '$self->GD::Graph::'. $self->{default_type}.'::draw_data_set(@_)'; } # If even that fails, we bail out croak "Set $ds: unknown default type $self->{default_type}" if $@; return $rc; } sub draw_legend_marker { my $self = shift; my $ds = $_[0]; my $type = $self->types($ds); eval '$self->GD::Graph::'.$type.'::draw_legend_marker(@_)'; eval '$self->GD::Graph::'. $self->{default_type}.'::draw_legend_marker(@_)' if $@; } # undocumented as can be: returns the type-list (with the default # inserted as appropriate), or the type associated with a particular # (1-indexed) dataset number (undef if there is no such dataset). The # range check means that this cannot be called when there is no # GD::Graph::Data object in $self->{_data}. sub types { my $self = shift; if ( defined $_[0] ) { $_[0] > 0 && $_[0] <= $self->{_data}->num_sets ? $self->{types}->[$_[0] - 1] || $self->{default_type} : undef } else { map { $self->{types}->[$_ - 1] || $self->{default_type} } 1 .. $self->{_data}->num_sets; } } "Just another true value"; GDGraph-1.44/Graph.pm0000644000175000001440000014212110614023277013003 0ustar benusers#========================================================================== # Copyright (c) 1995-2000 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GD::Graph.pm # # Description: # Module to create graphs from a data set drawing on a GD::Image # object # # Package of a number of graph types: # GD::Graph::bars # GD::Graph::hbars # GD::Graph::lines # GD::Graph::points # GD::Graph::linespoints # GD::Graph::area # GD::Graph::pie # GD::Graph::mixed # # $Id: Graph.pm,v 1.55 2007/04/26 04:12:47 ben Exp $ # #========================================================================== # # GD::Graph # # Parent class containing data all graphs have in common. # package GD::Graph; ($GD::Graph::prog_version) = '$Revision: 1.55 $' =~ /\s([\d.]+)/; $GD::Graph::VERSION = '1.44'; use strict; use GD; use GD::Text::Align; use GD::Graph::Data; use GD::Graph::Error; use Carp; @GD::Graph::ISA = qw(GD::Graph::Error); # Some tools and utils use GD::Graph::colour qw(:colours); my %GDsize = ( 'x' => 400, 'y' => 300 ); my %Defaults = ( # Set the top, bottom, left and right margin for the chart. These # margins will be left empty. t_margin => 0, b_margin => 0, l_margin => 0, r_margin => 0, # Set the factor with which to resize the logo in the chart (need to # automatically compute something nice for this, really), set the # default logo file name, and set the logo position (UR, BR, UL, BL) logo => undef, logo_resize => 1.0, logo_position => 'LR', # Do we want a transparent background? transparent => 1, # Do we want interlacing? interlaced => 1, # Set the background colour, the default foreground colour (used # for axes etc), the textcolour, the colour for labels, the colour # for numbers on the axes, the colour for accents (extra lines, tick # marks, etc..) bgclr => 'white', # background colour fgclr => 'dblue', # Axes and grid boxclr => undef, # Fill colour for box axes, default: not used accentclr => 'gray', # bar, area and pie outlines. labelclr => 'dblue', # labels on axes axislabelclr => 'dblue', # values on axes legendclr => 'dblue', # Text for the legend textclr => 'dblue', # All text, apart from the following 2 valuesclr => 'dblue', # values printed above the points # data set colours dclrs => [qw(lred lgreen lblue lyellow lpurple cyan lorange)], # number of pixels to use as text spacing text_space => 4, # These have undefined values, but are here so that the set method # knows about them: title => undef, ); sub _has_default { my $self = shift; my $attr = shift || return; exists $Defaults{$attr} } # # PUBLIC methods, documented in pod. # sub new # ( width, height ) optional; { my $type = shift; my $self = {}; bless $self, $type; if (@_) { # If there are any parameters, they should be the size return GD::Graph->_set_error( "Usage: GD::Graph::::new(width, height)") unless @_ >= 2; $self->{width} = shift; $self->{height} = shift; } else { # There were obviously no parameters, so use defaults $self->{width} = $GDsize{'x'}; $self->{height} = $GDsize{'y'}; } # Initialise all relevant parameters to defaults # These are defined in the subclasses. See there. $self->initialise() or return; return $self; } sub get { my $self = shift; my @wanted = map $self->{$_}, @_; wantarray ? @wanted : $wanted[0]; } sub set { my $self = shift; my %args = @_; my $w = 0; foreach (keys %args) { # Enforce read-only attributes. /^width$/ || /^height$/ and do { $self->_set_warning("Read-only attribute '$_' not set"); $w++; next; }; $self->{$_} = $args{$_}, next if $self->_has_default($_); $w++; $self->_set_warning("No attribute '$_'"); } return $w ? undef : "No problems"; } # Generic routine to instantiate GD::Text::Align objects for text # attributes sub _set_font { my $self = shift; my $name = shift; if (! exists $self->{$name}) { $self->{$name} = GD::Text::Align->new($self->{graph}, valign => 'top', halign => 'center', ) or return $self->_set_error("Couldn't set font"); } $self->{$name}->set_font(@_); } sub set_title_font # (fontname, size) { my $self = shift; $self->_set_font('gdta_title', @_); } sub set_text_clr # (colour name) { my $self = shift; my $clr = shift; $self->set( textclr => $clr, labelclr => $clr, axislabelclr => $clr, valuesclr => $clr, ); } sub plot { # ABSTRACT my $self = shift; $self->die_abstract("sub plot missing,"); } # Set defaults that apply to all graph/chart types. # This is called by the default initialise methods # from the objects further down the tree. sub initialise { my $self = shift; foreach (keys %Defaults) { $self->set($_ => $Defaults{$_}); } $self->open_graph() or return; $self->set_title_font(GD::Font->Large) or return; } # Check the integrity of the submitted data # # Checks are done to assure that every input array # has the same number of data points, it sets the variables # that store the number of sets and the number of points # per set, and kills the process if there are no datapoints # in the sets, or if there are no data sets. sub check_data # \@data { my $self = shift; my $data = shift; $self->{_data} = GD::Graph::Data->new($data) or return $self->_set_error(GD::Graph::Data->error); $self->{_data}->make_strict; $self->{_data}->num_sets > 0 && $self->{_data}->num_points > 0 or return $self->_set_error('No data sets or points'); if ($self->{show_values}) { # If this isn't a GD::Graph::Data compatible structure, then # we'll just use the data structure. # # XXX We should probably check a few more things here, e.g. # similarity between _data and show_values. # my $ref = ref($self->{show_values}); if (! $ref || ($ref ne 'GD::Graph::Data' && $ref ne 'ARRAY')) { $self->{show_values} = $self->{_data} } elsif ($ref eq 'ARRAY') { $self->{show_values} = GD::Graph::Data->new($self->{show_values}) or return $self->_set_error(GD::Graph::Data->error); } } return $self; } # Open the graph output canvas by creating a new GD object. sub open_graph { my $self = shift; return $self->{graph} if exists $self->{graph}; $self->{graph} = 2.0 <= $GD::VERSION ? GD::Image->newPalette($self->{width}, $self->{height}) : GD::Image->new($self->{width}, $self->{height}); } # Initialise the graph output canvas, setting colours (and getting back # index numbers for them) setting the graph to transparent, and # interlaced, putting a logo (if defined) on there. sub init_graph { my $self = shift; $self->{bgci} = $self->set_clr(_rgb($self->{bgclr})); $self->{fgci} = $self->set_clr(_rgb($self->{fgclr})); $self->{tci} = $self->set_clr(_rgb($self->{textclr})); $self->{lci} = $self->set_clr(_rgb($self->{labelclr})); $self->{alci} = $self->set_clr(_rgb($self->{axislabelclr})); $self->{acci} = $self->set_clr(_rgb($self->{accentclr})); $self->{valuesci} = $self->set_clr(_rgb($self->{valuesclr})); $self->{legendci} = $self->set_clr(_rgb($self->{legendclr})); $self->{boxci} = $self->set_clr(_rgb($self->{boxclr})) if $self->{boxclr}; $self->{graph}->transparent($self->{bgci}) if $self->{transparent}; $self->{graph}->interlaced( $self->{interlaced} || undef ); # required by GD.pm # XXX yuck. This doesn't belong here.. or does it? $self->put_logo(); return $self; } sub _read_logo_file { my $self = shift; my $glogo; local (*LOGO); my $logo_path = $self->{logo}; open(LOGO, $logo_path) or do { carp "Unable to open logo file '$logo_path': $!";return}; binmode(LOGO); # if the file has an extension, use that importer my $gdimport; my @tried; # possibly forward-compatible: just try whatever file extension if ( $logo_path =~ /\.(\w+)$/i) { my $fmt = lc $1; $fmt = "jpeg" if 'jpg' eq $fmt; push @tried, uc $fmt; if ($gdimport = GD::Image->can("newFrom\u$fmt")) { if ('xpm' ne $fmt) { $glogo = GD::Image->$gdimport(\*LOGO) } else { $glogo = GD::Image->$gdimport($logo_path) } # quirky special case } } # if that didn't work, try using magic numbers if (!$glogo) { my $logodata; read LOGO,$logodata, -s LOGO; my %magic = ( pack("H8",'ffd8ffe0') => "jpeg", 'GIF8' => "gif", '.PNG' => "png", '/* X'=> "xpm", # technically '/* XPM */', but I'm hashing, here ); if (my $match = $magic{ substr $logodata, 0, 4 }) { push @tried, $match; my $matchmethod = "newFrom\u$match"; if ($gdimport = GD::Image->can($matchmethod . "Data")) { $glogo = GD::Image->$gdimport($logodata); } elsif ($gdimport = GD::Image->can($matchmethod)) { if ('xpm' eq $match) { $glogo = GD::Image->$gdimport($logo_path); } else { seek LOGO,0,0; $glogo = GD::Image->$gdimport(\*LOGO); } } # should this actually be "if (!$glogo), rather than an else? } else { # Hail Mary, full of Grace! Blessed art thou among women... push @tried, 'libgd best-guess'; $glogo = GD::Image->new($logodata); } } close LOGO or croak "Unable to close logo file '$logo_path': $!"; # XXX change to use warnings::enabled when we break 5.005 compatibility carp "Problems reading $logo_path (tried: @tried)" unless $glogo; return $glogo; } # read in the logo, and paste it on the graph canvas sub put_logo { my $self = shift; return unless defined $self->{logo}; my $glogo = $self->_read_logo_file() or return; my ($x, $y); my $r = $self->{logo_resize}; my $r_margin = (defined $self->{r_margin_abs}) ? $self->{r_margin_abs} : $self->{r_margin}; my $b_margin = (defined $self->{b_margin_abs}) ? $self->{b_margin_abs} : $self->{b_margin}; my ($w, $h) = $glogo->getBounds; LOGO: for ($self->{logo_position}) { /UL/i and do { $x = $self->{l_margin}; $y = $self->{t_margin}; last LOGO; }; /UR/i and do { $x = $self->{width} - $r_margin - $w * $r; $y = $self->{t_margin}; last LOGO; }; /LL/i and do { $x = $self->{l_margin}; $y = $self->{height} - $b_margin - $h * $r; last LOGO; }; # default "LR" $x = $self->{width} - $r_margin - $r * $w; $y = $self->{height} - $b_margin - $r * $h; last LOGO; } $self->{graph}->copyResized($glogo, $x, $y, 0, 0, $r * $w, $r * $h, $w, $h); } # Set a colour to work with on the canvas, by rgb value. # Return the colour index in the palette sub set_clr # GD::Image, r, g, b { my $self = shift; return unless @_; my $gd = $self->{graph}; # All of this could potentially be done by using colorResolve # The problem is that colorResolve doesn't return an error # condition (-1) if it can't allocate a color. Instead it always # returns 0. # Check if this colour already exists on the canvas my $i = $gd->colorExact(@_); # if not, allocate a new one, and return its index $i = $gd->colorAllocate(@_) if $i < 0; # if this fails, we should use colorClosest. $i = $gd->colorClosest(@_) if $i < 0; # TODO Deal with antialiasing here? if (0 && $self->can("setAntiAliased")) { $self->setAntiAliased($i); eval "$i = gdAntiAliased"; } return $i; } # Set a temporary colour that can be used with fillToBorder sub _set_tmp_clr { my $self = shift; # XXX Error checks! $self->{graph}->colorAllocate(0,0,0); } # Remove the temporary colour sub _rm_tmp_clr { my $self = shift; return unless @_; # XXX Error checks? $self->{graph}->colorDeallocate(shift); } # Set a colour, disregarding wether or not it already exists. This may # be necessary where one wants the same colour to have a different # index, as in pie slices of the same color as the edge. # Note that this could be cleaned up after needed, but we won't do that. sub set_clr_uniq # GD::Image, r, g, b { my $self = shift; return unless @_; $self->{graph}->colorAllocate(@_); } # Return an array of rgb values for a colour number sub pick_data_clr # number { my $self = shift; _rgb($self->{dclrs}[$_[0] % @{$self->{dclrs}} - 1]); } # contrib "Bremford, Mike" sub pick_border_clr # number { my $self = shift; ref $self->{borderclrs} ? _rgb($self->{borderclrs}[$_[0] % @{$self->{borderclrs}} - 1]) : _rgb($self->{accentclr}); } sub gd { my $self = shift; return $self->{graph}; } sub export_format { my $proto = shift; my @f = grep { GD::Image->can($_) && do { my $g = GD::Image->new(5,5); $g->colorAllocate(0,0,0); $g->$_() }; } qw(gif png jpeg xbm xpm gd gd2); wantarray ? @f : $f[0]; } # The following method is undocumented, and will not be supported as # part of the interface. There isn't really much reason to do so. sub import_format { my $proto = shift; # xpm now included despite bugginess--should document the problem, though my @f = grep { GD::Image->can("newFrom\u$_") } qw(gif png jpeg xbm xpm gd gd2); wantarray ? @f : $f[0]; } sub can_do_ttf { my $proto = shift; return GD::Text->can_do_ttf; } # DEBUGGING # data_dump obsolete now, use Data::Dumper sub die_abstract { my $self = shift; my $msg = shift; # ABSTRACT confess "Subclass (" . ref($self) . ") not implemented correctly: " . (defined($msg) ? $msg : "unknown error"); } "Just another true value"; __END__ =head1 NAME GD::Graph - Graph Plotting Module for Perl 5 =head1 SYNOPSIS use GD::Graph::moduleName; =head1 DESCRIPTION B is a I module to create charts using the GD module. The following classes for graphs with axes are defined: =over 4 =item C Create a line chart. =item C and C Create a bar chart with vertical or horizontal bars. =item C Create an chart, displaying the data as points. =item C Combination of lines and points. =item C Create a graph, representing the data as areas under a line. =item C Create a mixed type graph, any combination of the above. At the moment this is fairly limited. Some of the options that can be used with some of the individual graph types won't work very well. Bar graphs drawn after lines or points graphs may obscure the earlier data, and specifying bar_width will not produce the results you probably expected. =back Additional types: =over 4 =item C Create a pie chart. =back =head1 EXAMPLES See the samples directory in the distribution, and read the Makefile there. =head1 USAGE Fill an array of arrays with the x values and the values of the data sets. Make sure that every array is the same size, otherwise I will complain and refuse to compile the graph. @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 1, 2, 5, 6, 3, 1.5, 1, 3, 4], [ sort { $a <=> $b } (1, 2, 5, 6, 3, 1.5, 1, 3, 4) ] ); If you don't have a value for a point in a certain dataset, you can use B, and the point will be skipped. Create a new I object by calling the I method on the graph type you want to create (I is I, I, I, I, I, I or I). my $graph = GD::Graph::chart->new(400, 300); Set the graph options. $graph->set( x_label => 'X Label', y_label => 'Y label', title => 'Some simple graph', y_max_value => 8, y_tick_number => 8, y_label_skip => 2 ) or die $graph->error; and plot the graph. my $gd = $graph->plot(\@data) or die $graph->error; Then do whatever your current version of GD allows you to do to save the file. For versions of GD older than 1.19 (or more recent than 2.15), you'd do something like: open(IMG, '>file.gif') or die $!; binmode IMG; print IMG $gd->gif; close IMG; and for newer versions (1.20 and up) you'd write open(IMG, '>file.png') or die $!; binmode IMG; print IMG $gd->png; or open(IMG, '>file.gd2') or die $!; binmode IMG; print IMG $gd->gd2; Then there's also of course the possibility of using a shorter version (for each of the export functions that GD supports): print IMG $graph->plot(\@data)->gif; print IMG $graph->plot(\@data)->png; print IMG $graph->plot(\@data)->gd; print IMG $graph->plot(\@data)->gd2; If you want to write something that doesn't require your code to 'know' whether to use gif or png, you could do something like: if ($gd->can('png')) { # blabla } or you can use the convenience method C: my $format = $graph->export_format; open(IMG, ">file.$format") or die $!; binmode IMG; print IMG $graph->plot(\@data)->$format(); close IMG; or for CGI programs: use CGI qw(:standard); #... my $format = $graph->export_format; print header("image/$format"); binmode STDOUT; print $graph->plot(\@data)->$format(); (the parentheses after $format are necessary, to help the compiler decide that you mean a method name there) See under L<"SEE ALSO"> for references to other documentation, especially the FAQ. =head1 METHODS =head2 Methods for all graphs =over 4 =item GD::Graph::chart-Enew([width,height]) Create a new object $graph with optional width and heigth. Default width = 400, default height = 300. I is either I, I, I, I, I, I or I. =item $graph-Eset_text_clr(I) Set the colour of the text. This will set the colour of the titles, labels, and axis labels to I. Also see the options I, I and I. =item $graph-Eset_title_font(font specification) Set the font that will be used for the title of the chart. See L<"FONTS">. =item $graph-Eplot(I<\@data>) Plot the chart, and return the GD::Image object. =item $graph-Eset(attrib1 =E value1, attrib2 =E value2 ...) Set chart options. See OPTIONS section. =item $graph-Eget(attrib1, attrib2) Returns a list of the values of the attributes. In scalar context returns the value of the first attribute only. =item $graph-Egd() Get the GD::Image object that is going to be used to draw on. You can do this either before or after calling the plot method, to do your own drawing. B as of the current version, this GD::Image object will always be palette-based, even if the installed version of GD supports true-color images. Note also that if you draw on the GD::Image object before calling the plot method, you are responsible for making sure that the background colour is correct and for setting transparency. =item $graph-Eexport_format() Query the export format of the GD library in use. In scalar context, it returns 'gif', 'png' or undefined, which is sufficient for most people's use. In a list context, it returns a list of all the formats that are supported by the current version of GD. It can be called as a class or object method =item $graph-Ecan_do_ttf() Returns true if the current GD library supports TrueType fonts, False otherwise. Can also be called as a class method or static method. =back =head2 Methods for Pie charts =over 4 =item $graph-Eset_label_font(font specification) =item $graph-Eset_value_font(font specification) Set the font that will be used for the label of the pie or the values on the pie. See L<"FONTS">. =back =head2 Methods for charts with axes. =over 4 =item $graph-Eset_x_label_font(font specification) =item $graph-Eset_y_label_font(font specification) =item $graph-Eset_x_axis_font(font specification) =item $graph-Eset_y_axis_font(font specification) =item $graph-Eset_values_font(font specification) Set the font for the x and y axis label, the x and y axis value labels, and for the values printed above the data points. See L<"FONTS">. =item $graph-Eget_hotspot($dataset, $point) B: Return a coordinate specification for a point in a dataset. Returns a list. If the point is not specified, returns a list of array references for all points in the dataset. If the dataset is also not specified, returns a list of array references for each data set. See L<"HOTSPOTS">. =item $graph-Eget_feature_coordinates($feature_name) B: Return a coordinate specification for a certain feature in the chart. Currently, features that are defined are I, the coordinates of the rectangle within the axes; I, I and I, the labels printed along the axes, with I provided as an alias for I; and I which is the title text box. See L<"HOTSPOTS">. =back =head1 OPTIONS =head2 Options for all graphs =over 4 =item width, height The width and height of the canvas in pixels Default: 400 x 300. B<NB> At the moment, these are read-only options. If you want to set the size of a graph, you will have to do that with the I<new> method. =item t_margin, b_margin, l_margin, r_margin Top, bottom, left and right margin of the canvas. These margins will be left blank. Default: 0 for all. =item logo Name of a logo file. Generally, this should be the same format as your version of GD exports images in. Currently, this file may be in any format that GD can import, but please see L<GD> if you use an XPM file and get unexpected results. Default: no logo. =item logo_resize, logo_position Factor to resize the logo by, and the position on the canvas of the logo. Possible values for logo_position are 'LL', 'LR', 'UL', and 'UR'. (lower and upper left and right). Default: 'LR'. =item transparent If set to a true value, the produced image will have the background colour marked as transparent (see also option I<bgclr>). Default: 1. =item interlaced If set to a true value, the produced image will be interlaced. Default: 1. B<Note>: versions of GD higher than 2.0 (that is, since GIF support was restored after being removed owing to patent issues) do not support interlacing of GIF images. Support for interlaced PNG and progressive JPEG images remains available using this option. =back =head2 Colours =over 4 =item bgclr, fgclr, boxclr, accentclr, shadowclr Drawing colours used for the chart: background, foreground (axes and grid), axis box fill colour, accents (bar, area and pie outlines), and shadow (currently only for bars). All colours should have a valid value as described in L<"COLOURS">, except boxclr, which can be undefined, in which case the box will not be filled. =item shadow_depth Depth of a shadow, positive for right/down shadow, negative for left/up shadow, 0 for no shadow (default). Also see the C<shadowclr> and C<bar_spacing> options. =item labelclr, axislabelclr, legendclr, valuesclr, textclr Text Colours used for the chart: label (labels for the axes or pie), axis label (misnomer: values printed along the axes, or on a pie slice), legend text, shown values text, and all other text. All colours should have a valid value as described in L<"COLOURS">. =item dclrs (short for datacolours) This controls the colours for the bars, lines, markers, or pie slices. This should be a reference to an array of colour names as defined in L<GD::Graph::colour> (S<C<perldoc GD::Graph::colour>> for the names available). $graph->set( dclrs => [ qw(green pink blue cyan) ] ); The first (fifth, ninth) data set will be green, the next pink, etc. A colour can be C<undef>, in which case the data set will not be drawn. This can be useful for cumulative bar sets where you want certain data series (often the first one) not to show up, which can be used to emulate error bars (see examples 1-7 and 6-3 in the distribution). Default: [ qw(lred lgreen lblue lyellow lpurple cyan lorange) ] =item borderclrs This controls the colours of the borders of the bars data sets. Like dclrs, it is a reference to an array of colour names as defined in L<GD::Graph::colour>. Setting a border colour to C<undef> means the border will not be drawn. =item cycle_clrs If set to a true value, bars will not have a colour from C<dclrs> per dataset, but per point. The colour sequence will be identical for each dataset. Note that this may have a weird effect if you are drawing more than one data set. If this is set to a value larger than 1 the border colour of the bars will cycle through the colours in C<borderclrs>. =item accent_treshold Not really a colour, but it does control a visual aspect: Accents on bars are only drawn when the width of a bar is larger than this number of pixels. Accents inside areas are only drawn when the horizontal distance between points is larger than this number. Default 4 =back =head2 Options for graphs with axes. options for I<bars>, I<lines>, I<points>, I<linespoints>, I<mixed> and I<area> charts. =over 4 =item x_label, y_label The labels to be printed next to, or just below, the axes. Note that if you use the two_axes option that you need to use y1_label and y2_label. =item long_ticks, tick_length If I<long_ticks> is a true value, ticks will be drawn the same length as the axes. Otherwise ticks will be drawn with length I<tick_length>. if I<tick_length> is negative, the ticks will be drawn outside the axes. Default: long_ticks = 0, tick_length = 4. These attributes can also be set for x and y axes separately with x_long_ticks, y_long_ticks, x_tick_length and y_tick_length. =item x_ticks If I<x_ticks> is a true value, ticks will be drawm for the x axis. These ticks are subject to the values of I<long_ticks> and I<tick_length>. Default: 1. =item y_tick_number Number of ticks to print for the Y axis. Use this, together with I<y_label_skip> to control the look of ticks on the y axis. Default: 5. =item y_number_format This can be either a string, or a reference to a subroutine. If it is a string, it will be taken to be the first argument to a sprintf, with the value as the second argument: $label = sprintf( $s->{y_number_format}, $value ); If it is a code reference, it will be executed with the value as the argument: $label = &{$s->{y_number_format}}($value); This can be useful, for example, if you want to reformat your values in currency, with the - sign in the right spot. Something like: sub y_format { my $value = shift; my $ret; if ($value >= 0) { $ret = sprintf("\$%d", $value * $refit); } else { $ret = sprintf("-\$%d", abs($value) * $refit); } return $ret; } $graph->set( 'y_number_format' => \&y_format ); (Yes, I know this can be much shorter and more concise) Default: undef. =item y1_number_format, y2_number_format As with I<y_number_format>, these can be either a string, or a reference to a subroutine. These are used as formats for graphs with two y-axis scales so that independent formats can be used. For compatibility purposes, each of these will fall back on I<y_number_format> if not specified. Default: undef for both. =item x_label_skip, y_label_skip Print every I<x_label_skip>th number under the tick on the x axis, and every I<y_label_skip>th number next to the tick on the y axis. Default: 1 for both. =item x_tick_offset When x_label_skip is used, this will skip the first x_tick_offset values in the labels before starting to print. Let me give an example. If you have a series of X labels like qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec) and you set x_label_skip to 3, you will see ticks on the X axis for Jan, Apr, Jul, Oct and Dec. This is not always what is wanted. If you set x_tick_offset to 1, you get Feb, May, Aug, Nov and Dec, and if you set it to 2, you get Mar, Jun Sep and Dec, and this last one definitely looks better. A combination of 6 and 5 also works nice for months. Note that the value for x_tick_offset is periodical. This means that it will have the same effect for each nteger n in x_tick_offset + n * x_label_skip. =item x_all_ticks Force a print of all the x ticks, even if x_label_skip is set to a value Default: 0. =item x_label_position Controls the position of the X axis label (title). The value for this should be between 0 and 1, where 0 means aligned to the left, 1 means aligned to the right, and 1/2 means centered. Default: 3/4 =item y_label_position Controls the position of both Y axis labels (titles). The value for this should be between 0 and 1, where 0 means aligned to the bottom, 1 means aligned to the top, and 1/2 means centered. Default: 1/2 =item x_labels_vertical If set to a true value, the X axis labels will be printed vertically. This can be handy in case these labels get very long. Default: 0. =item x_plot_values, y_plot_values If set to a true value, the values of the ticks on the x or y axes will be plotted next to the tick. Also see I<x_label_skip, y_label_skip>. Default: 1 for both. =item box_axis Draw the axes as a box, if true. Default: 1. =item no_axes Draw no axes at all. If this is set to undef, all axes are drawn. If it is set to 0, the zero axis will be drawn, I<for bar charts only>. If this is set to a true value, no axes will be drawns at all. Value labels on the axes and ticks will also not be drawn, but axis lables are drawn. Default: undef. =item two_axes Use two separate axes for the first and second data set. The first data set will be set against the left axis, the second against the right axis. If more than two data sets are being plotted, the use_axis option should be used to specify which data sets use which axis. Note that if you use this option, that you need to use y1_label and y2_label, instead of just y_label, if you want the two axes to have different labels. The same goes for some other options starting with the letter 'y' and an underscore. Default: 0. =item use_axis If two y-axes are in use and more than two datasets are specified, set this option to an array reference containing a value of 1 or 2 (for the left and right scales respectively) for each dataset being plotted. That is, to plot three datasets with the second on a different scale than the first and third, set this to C<[1,2,1]>. Default: [1,2]. =item zero_axis If set to a true value, the axis for y values of 0 will always be drawn. This might be useful in case your graph contains negative values, but you want it to be clear where the zero value is. (see also I<zero_axis_only> and I<box_axes>). Default: 0. =item zero_axis_only If set to a true value, the zero axis will be drawn (see I<zero_axis>), and no axis at the bottom of the graph will be drawn. The labels for X values will be placed on the zero exis. Default: 0. =item y_max_value, y_min_value Maximum and minimum value displayed on the y axis. If two_axes is a true value, then y1_min_value, y1_max_value (for the left axis), and y2_min_value, y2_max_value (for the right axis) take precedence over these. The range (y_min_value..y_max_value) has to include all the values of the data points, or I<GD::Graph> will die with a message. For bar and area graphs, the range (y_min_value..y_max_value) has to include 0. If it doesn't, the values will be adapted before attempting to draw the graph. Default: Computed from data sets. =item axis_space This space will be left blank between the axes and the tick value text. Default: 4. =item text_space This space will be left open between text elements and the graph (text elements are title and axis labels. Default: 8. =item cumulate If this attribute is set to a true value, the data sets will be cumulated. This means that they will be stacked on top of each other. A side effect of this is that C<overwrite> will be set to a true value. Notes: This only works for bar and area charts at the moment. If you have negative values in your data sets, setting this option might produce odd results. Of course, the graph itself would be quite meaningless. =item overwrite If set to 0, bars of different data sets will be drawn next to each other. If set to 1, they will be drawn in front of each other. Default: 0. Note: Setting overwrite to 2 to produce cumulative sets is deprecated, and may disappear in future versions of GD::Graph. Instead see the C<cumulate> attribute. =item correct_width If this is set to a true value and C<x_tick_number> is false, then the width of the graph (or the height for rotated graphs like C<GD::Graph::hbar>) will be recalculated to make sure that each data point is exactly an integer number of pixels wide. You probably never want to fiddle with this. When this value is true, you will need to make sure that the number of data points is smaller than the number of pixels in the plotting area of the chart. If you get errors saying that your horizontal size if too small, you may need to manually switch this off, or consider using something else than a bar type for your chart. Default: 1 for bar, calculated at runtime for mixed charts, 0 for others. =back =head2 Plotting data point values with the data point Sometimes you will want to plot the value of a data point or bar above the data point for clarity. GD::Graph allows you to control this in a generic manner, or even down to the single point. =over 4 =item show_values Set this to 1 to display the value of each data point above the point or bar itself. No effort is being made to ensure that there is enough space for the text. Set this to a GD::Graph::Data object, or an array reference of the same shape, with the same dimensions as your data object that you pass in to the plot method. The reason for this option is that it allows you to make a copy of your data set, and selectively set points to C<undef> to disable plotting of them. my $data = GD::Graph::Data->new( [ [ 'A', 'B', 'C' ], [ 1, 2, 3 ], [ 11, 12, 13 ] ]); my $values = $data->copy; $values->set_y(1, 1, undef); $values->set_y(2, 0, undef); $graph->set(show_values => $values); $graph->plot($data); Default: 0. =item values_vertical If set to a true value, the values will be printed vertically, instead of horizontally. This can be handy if the values are long numbers. Default: 0. =item values_space Space to insert between the data point and the value to print. Default: 4. =item values_format How to format the values for display. See y_number_format for more information. Default: undef. =back =head2 Options for graphs with a numerical X axis First of all: GD::Graph does B<not> support numerical x axis the way it should. Data for X axes should be equally spaced. That understood: There is some support to make the printing of graphs with numerical X axis values a bit better, thanks to Scott Prahl. If the option C<x_tick_number> is set to a defined value, GD::Graph will attempt to treat the X data as numerical. Extra options are: =over 4 =item x_tick_number If set to I<'auto'>, GD::Graph will attempt to format the X axis in a nice way, based on the actual X values. If set to a number, that's the number of ticks you will get. If set to undef, GD::Graph will treat X data as labels. Default: undef. =item x_min_value, x_max_value The minimum and maximum value to use for the X axis. Default: computed. =item x_number_format See y_number_format =item x_label_skip See y_label_skip =back =head2 Options for graphs with bars =over 4 =item bar_width The width of a bar in pixels. Also see C<bar_spacing>. Use C<bar_width> If you want to have fixed-width bars, no matter how wide the chart gets. Default: as wide as possible, within the constraints of the chart size and C<bar_spacing> setting. =item bar_spacing Number of pixels to leave open between bars. This works well in most cases, but on some platforms, a value of 1 will be rounded off to 0. Use C<bar_spacing> to get a fixed amount of space between bars, with variable bar widths, depending on the width of the chart. Note that if C<bar_width> is also set, this setting will be ignored, and automatically calculated. Default: 0 =item bargroup_spacing Number of pixels (in addition to whatever is specified in C<bar_spacing>) to leave between groups of bars when multiple datasets are being displayed. Unlike C<bar_spacing>, however, this parameter will hold its value if C<bar_width> is set. =back =head2 Options for graphs with lines =over 4 =item line_types Which line types to use for I<lines> and I<linespoints> graphs. This should be a reference to an array of numbers: $graph->set( line_types => [3, 2, 4] ); Available line types are 1: solid, 2: dashed, 3: dotted, 4: dot-dashed. Default: [1] (always use solid) =item line_type_scale Controls the length of the dashes in the line types. default: 6. =item line_width The width of the line used in I<lines> and I<linespoints> graphs, in pixels. Default: 1. =item skip_undef For all other axes graph types, the default behaviour is (by their nature) to not draw a point when the Y value is C<undef>. For line charts the point gets skipped as well, but the line is drawn between the points n-1 to n+1 directly. If C<skip_undef> has a true value, there will be a gap in the chart where a Y value is undefined. Note that a line will not be drawn unless there are I<at least two> consecutive data points exist that have a defined value. The following data set will only plot a very short line towards the end if C<skip_undef> is set: @data = ( [ qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct ) ], [ 1, undef, 2, undef, 3, undef, 4, undef, 5, 6 ] ); This option is useful when you have a consecutive gap in your data, or with linespoints charts. If you have data where you have intermittent gaps, be careful when you use this. Default value: 0 =back =head2 Options for graphs with points =over 4 =item markers This controls the order of markers in I<points> and I<linespoints> graphs. This should be a reference to an array of numbers: $graph->set( markers => [3, 5, 6] ); Available markers are: 1: filled square, 2: open square, 3: horizontal cross, 4: diagonal cross, 5: filled diamond, 6: open diamond, 7: filled circle, 8: open circle, 9: horizontal line, 10: vertical line. Note that the last two are not part of the default list. Default: [1,2,3,4,5,6,7,8] =item marker_size The size of the markers used in I<points> and I<linespoints> graphs, in pixels. Default: 4. =back =head2 Options for mixed graphs =over 4 =item types A reference to an array with graph types, in the same order as the data sets. Possible values are: $graph->set( types => [qw(lines bars points area linespoints)] ); $graph->set( types => ['lines', undef, undef, 'bars'] ); values that are undefined or unknown will be set to C<default_type>. Default: all set to C<default_type> =item default_type The type of graph to draw for data sets that either have no type set, or that have an unknown type set. Default: lines =back =head2 Graph legends (axestype graphs only) At the moment legend support is minimal. B<Methods> =over 4 =item $graph-E<gt>set_legend(I<@legend_keys>); Sets the keys for the legend. The elements of @legend_keys correspond to the data sets as provided to I<plot()>. If a key is I<undef> or an empty string, the legend entry will be skipped. =item $graph-E<gt>set_legend_font(I<font name>); Sets the font for the legend text (see L<"FONTS">). Default: GD::gdTinyFont. =back B<Options> =over 4 =item legend_placement Where to put the legend. This should be a two letter key of the form: 'B[LCR]|R[TCB]'. The first letter indicates the placement (I<B>ottom or I<R>ight), and the second letter the alignment (I<L>eft, I<R>ight, I<C>enter, I<T>op, or I<B>ottom). Default: 'BC' If the legend is placed at the bottom, some calculations will be made to ensure that there is some 'intelligent' wrapping going on. if the legend is placed at the right, all entries will be placed below each other. =item legend_spacing The number of pixels to place around a legend item, and between a legend 'marker' and the text. Default: 4 =item legend_marker_width, legend_marker_height The width and height of a legend 'marker' in pixels. Defaults: 12, 8 =item lg_cols If you, for some reason, need to force the legend at the bottom to have a specific number of columns, you can use this. Default: computed =back =head2 Options for pie graphs =over 4 =item 3d If set to a true value, the pie chart will be drawn with a 3d look. Default: 1. =item pie_height The thickness of the pie when I<3d> is true. Default: 0.1 x height. =item start_angle The angle at which the first data slice will be displayed, with 0 degrees being "6 o'clock". Default: 0. =item suppress_angle If a pie slice is smaller than this angle (in degrees), a label will not be drawn on it. Default: 0. =item label Print this label below the pie. Default: undef. =back =head1 COLOURS All references to colours in the options for this module have been shortened to clr. The main reason for this was that I didn't want to support two spellings for the same word ('colour' and 'color') Wherever a colour is required, a colour name should be used from the package L<GD::Graph::colour>. S<C<perldoc GD::Graph::colour>> should give you the documentation for that module, containing all valid colour names. I will probably change this to read the systems rgb.txt file if it is available. =head1 FONTS Depending on your version of GD, this accepts both GD builtin fonts or the name of a TrueType font file. In the case of a TrueType font, you must specify the font size. See L<GD::Text> for more details and other things, since all font handling in GD::Graph is delegated to there. Examples: $graph->set_title_font('/fonts/arial.ttf', 18); $graph->set_legend_font(gdTinyFont); $graph->set_legend_font( ['verdana', 'arial', gdMediumBoldFont], 12) (The above discussion is based on GD::Text 0.65. Older versions have more restrictive behaviour). =head1 HOTSPOTS I<Note that this is an experimental feature, and its interface may, and likely will, change in the future. It currently does not work for area charts or pie charts.> GD::Graph keeps an internal set of coordinates for each data point and for certain features of a chart, like the title and axis labels. This specification is very similar to the HTML image map specification, and in fact exists mainly for that purpose. You can get at these hotspots with the C<get_hotspot> method for data point, and C<get_feature_coordinates> for the chart features. The <get_hotspot> method accepts two optional arguments, the number of the dataset you're interested in, and the number of the point in that dataset you're interested in. When called with two arguments, the method returns a list of one of the following forms: 'rect', x1, y1, x2, y2 'poly', x1, y1, x2, y2, x3, y3, .... 'line', xs, ys, xe, ye, width The parameters for C<rect> are the coordinates of the corners of the rectangle, the parameters for C<poly> are the coordinates of the vertices of the polygon, and the parameters for the C<line> are the coordinates for the start and end point, and the line width. It should be possible to almost directly translate these lists into HTML image map specifications. If the second argument to C<get_hotspot> is omitted, a list of references to arrays will be returned. This list represents all the points in the dataset specified, and each array referred to is of the form outlined above. ['rect', x1, y1, x2, y2 ], ['rect', x1, y1, x2, y2], ... if both arguments to C<get_hotspot> are omitted, the list that comes back will contain references to arrays for each data set, which in turn contain references to arrays for each point. [ ['rect', x1, y1, x2, y2 ], ['rect', x1, y1, x2, y2], ... ], [ ['line', xs, ys, xe, ye, w], ['line', xs, ys, xe, ye, w], ... ],... The C<get_feature> method, when called with the name of a feature, returns a single array reference with a type and coordinates as described above. When called with no arguments, a hash reference is returned with the keys being all the currently defined and set features, and the values array references with the type and coordinates for each of those features. =head1 ERROR HANDLING GD::Graph objects inherit from the GD::Graph::Error class (not the other way around), so they behave in the same manner. The main feature of that behaviour is that you have the error() method available to get some information about what went wrong. The GD::Graph methods all return undef if something went wrong, so you should be able to write safe programs like this: my $graph = GD::Graph->new() or die GD::Graph->error; $graph->set( %attributes ) or die $graph->error; $graph->plot($gdg_data) or die $graph->error; More advanced usage is possible, and there are some caveats with this error handling, which are all explained in L<GD::Graph::Error>. Unfortunately, it is almost impossible to gracefully recover from an error in GD::Graph, so you really should get rid of the object, and recreate it from scratch if you want to recover. For example, to adjust the correct_width attribute if you get the error "Horizontal size too small" or "Vertical size too small" (in the case of hbar), you could do something like: sub plot_graph { my $data = shift; my %attribs = @_; my $graph = GD::Graph::bars->new() or die GD::Graph->error; $graph->set(%attribs) or die $graph->error; $graph->plot($data) or die $graph->error; } my $gd; eval { $gd = plot_graph(\@data, %attribs) }; if ($@) { die $@ unless $@ =~ /size too small/; $gd = plot_graph(\@data, %attribs, correct_width => 0); } Of course, you could also adjust the width this way, and you can check for other errors. =head1 NOTES As with all Modules for Perl: Please stick to using the interface. If you try to fiddle too much with knowledge of the internals of this module, you could get burned. I may change them at any time. =head1 BUGS GD::Graph objects cannot be reused. To create a new plot, you have to create a new GD::Graph object. Rotated charts (ones with the X axis on the left) can currently only be created for bars. With a little work, this will work for all others as well. Please, be patient :) Other outstanding bugs can (alas) probably be found in the RT queue for this distribution, at http://rt.cpan.org/Public/Dist/Display.html?Name=GDGraph If you think you have found a bug, please check first to see if it has already been reported. If it has not, please do (you can use the web interface above or send e-mail to E<lt>bug-GDGraph@rt.cpan.orgE<gt>). Bug reports should contain as many as possible of the following: =over 4 =item * a concise description of the buggy behavior and how it differs from what you expected, =item * the versions of Perl, GD::Graph and GD that you are using, =item * a short demonstration script that shows the bug in action, =item * a patch that fixes it. :-) =back Of all of these, the third is probably the single most important, since producing a test case generally makes the explanation much more concise and understandable, as well as making it much simpler to show that the bug has been fixed. As an incidental benefit, if the bug is in fact caused by some code outside of GD::Graph, it will become apparent while you are writing the test case, thereby saving time and confusion for all concerned. =head1 AUTHOR Martien Verbruggen E<lt>mgjv@tradingpost.com.auE<gt> Current maintenance (including this release) by Benjamin Warfield E<lt>bwarfield@cpan.orgE<gt> =head2 Copyright GIFgraph: Copyright (c) 1995-1999 Martien Verbruggen. Chart::PNGgraph: Copyright (c) 1999 Steve Bonds. GD::Graph: Copyright (c) 1999 Martien Verbruggen. All rights reserved. This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head2 Acknowledgements Thanks to Steve Bonds for releasing Chart::PNGgraph, and keeping the code alive when GD reached version 1.20, and I didn't have time to do something about it. Thanks to the following people for contributing code, or sending me fixes: Dave Belcher, Steve Bonds, Mike Bremford, Damon Brodie, Gary Deschaines, brian d foy, Edwin Hildebrand, Ari Jolma, Tim Meadowcroft, Honza Pazdziora, Scott Prahl, Ben Tilly, Vegard Vesterheim, Jeremy Wadsack. And some people whose real name I don't know, and whose email address I'd rather not publicise without their consent. =head1 SEE ALSO L<GD::Graph::FAQ>, L<GD::Graph::Data>, L<GD::Graph::Error>, L<GD::Graph::colour> �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������GDGraph-1.44/README���������������������������������������������������������������������������������0000644�0001750�0000144�00000013756�10614024656�012301� 0����������������������������������������������������������������������������������������������������ustar �ben�����������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������This is GDGraph, a package to generate charts, using Lincoln Stein's GD.pm. See the documentation for some history and more information. The latest release is available from CPAN: http://www.cpan.org/. INSTALLATION Requirements: perl 5.6.0 GD >= 1.19 (recommended >= 1.23) GD::Text::Align (part of the GDTextUtils package) GD::Graph will not work with Perl 5.004. It most likely works with 5.005 (except for some odd problems with GD::Graph::Data::read(), which seem to be related to some obscure 5.005_03 bug, which I have not been able to track down), but I will no longer actively support it. to install: perl Makefile.PL make make install The tests are of limited value. The samples directory contains examples which also function as a test suite. To see the samples: make samples (use viewer to see samples/sample*.png or .gif) or cd samples make (use viewer to see sample*.png) The documentation available is contained in GD::Graph.pm, as pod. See it with perldoc GD::Graph after installation or perldoc -F Graph.pm before installation. TESTED PLATFORMS I have discontinued this list, because it is too hard to maintain. There is hardly any code in the module that could provide problems with inter-platform portability, but you never know. I will always test the modules against the latest stable perl (5.8.0 right now) and at least one older version (5.6.2). I will not explicitly test against older versions of Perl. I normally test against the newest version of GD, the last pre-2.0 version (1.41), and one version of the pre-PNG days (1.19). All of this happens on Linux. AUTHOR Martien Verbruggen mgjv@tradingpost.com.au Currently maintained by Benjamin Warfield bwarfield@cpan.org FIRST PNG PORT as Chart::PNGgraph Steve Bonds sbonds@agora.rdrop.com MOST IMPORTANT CHANGES SINCE VERSION 1.34 See file CHANGES MOST IMPORTANT CHANGES FOR VERSION 1.34 - Added GD::Graph::hbars, to create horizontal bar charts. Many thanks to brian d foy for doing almost all of the actual work. :) MOST IMPORTANT CHANGES FOR VERSION 1.30 - Added GD::Graph::Data as the preferred way of working with data sets. Internally all code has been changed to use these objects. - Many, many fundamental code changes, mainly to facilitate a future breakup of the code into separate Data, Chart and Graphics handling. All of this is internal, and there are not that many new options. (check the CHANGES file for more information) MOST IMPORTANT CHANGES FOR VERSION 1.20 - Namespace change to GD::Graph - No more links to GIF or PNG. We return a GD object now. It's the user's responsibility to save the right format. GIFgraph and (hopefully) Chart::PNGgraph will become wrappers around all this - Font support no longer part of these modules. Instead the package GDTextUtils is necessary. - Some bug fixes and extra options. MOST IMPORTANT CHANGES SINCE VERSION 1.10 - Namespace change from GIFgraph --> Chart::PNGgraph - No longer generates GIF format images due to Unisys LZW patent - Supports TrueType fonts MOST IMPORTANT CHANGES SINCE VERSION 1.04 - added bar_spacing option - added limited support for numerical X axis for equidistant X values (NOT for a real numerical graph!), thanks to Scott Prahl. - routines to automatically 'guess' nice upper and lower values for graphs have been replaced by one written by Scott Prahl MOST IMPORTANT CHANGES SINCE VERSION 1.03 - Added mixed type graph. GIFgraph::mixed options types and default_type - Added callback functionality to format y values option y_number_format - Added control over axis label placement option [xy]_label_position MOST IMPORTANT CHANGES SINCE VERSION 1.01 - Vertical printing of X axis labels - CHANGED DEFAULTS for zero_axis and zero_axis_only - Fixed problems with negative values, data ranges without 0, and printing of the x axis labels (I hope) - No more support for perl 5.003. Since perl 5.005 is out, and I don't have a 5.003 here to test all the time, I won't support it anymore. MOST IMPORTANT CHANGES SINCE VERSION 0.91 - Legends - Support for negative numbers - Ticks for X axis - line types and widths - Allow entries in data set to be undef (to skip them) - Changed 'zero' angle for pie charts (was right, now is front/bottom) - Definition of colours now possible. See PNGgraph::colour::read_rgb for details - See file CHANGES for more BUG FIXES IN THIS VERSION See file CHANGES REPORTING BUGS Please use rt.cpan.org to report any bugs with GD::Graph or GD::Text. Alternatively, you can email me, but I prefer it if you use the RT interface. When reporting a bug, please include the version of the module distribution you use, as well as your Perl version and platform (perl -V output will do). NOTES FOR WIN32 and Mac (pre OSX) These modules _should_ work on all platforms. Please direct any questions about the availability of these modules as PPM packages to ActiveState. I only make this available as a standard tar on CPAN. I have emailed ActiveState to ask what I was supposed to do, and have, until today, not received any answers. THANKS First of all. many, many thanks to Steve Bonds for adapting GIFgraph to version 1.20 of GD (the first version that did not support GIF anymore), and releasing it as Chart::PNGgraph. I really didn't have the time to look at it, and he stepped in and fixed the headache that Unisys had given me. Others who have contributed are mentioned in the documentation for GD::Graph in the AUTHOR section. COPYRIGHT GD::Graph Copyright (c) 1999-2002 Martien Verbruggen. All rights reserved. Chart::PNGgraph Copyright (c) 1999 Steve Bonds. All rights reserved. GIFgraph Copyright (c) 1995-1999 Martien Verbruggen. All rights reserved. This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself. I really felt like adding a clause to the copyright that excluded Unisys and its employees from the use of any of my code, at least without a license bought from me. I decided against it for several reasons, the main one being that I would just feel too dirty doing that. ������������������GDGraph-1.44/CHANGES��������������������������������������������������������������������������������0000644�0001750�0000144�00000032301�10614014571�012372� 0����������������������������������������������������������������������������������������������������ustar �ben�����������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������25 Apr 2007 - Patched bugs 21610, 20792, 20802, 23755 and 22932 - Updated POD to clarify current maintenance status, and encourage bug reporting via RT (and to point out some external help resources) - Release 1.44 17 May 2006 - Patched bugs 7307, 2944 (extended the fix to mixed graphs), 4177, and 16863. - Fixed a fencepost error in pie.pm that caused an occasional segfault (reported by John Westlund and Hank Leininger) - Fixed a bug that broke bar charts with no visible 0-axis (reported by Steve Foster) 19 Feb 2006 - Patched bugs 2218, 4632 (which had two duplicates), 7881, and 15374 - Failed to update CHANGES file before releasing 1.4307 to CPAN (oops) 4 Feb 2006 - Patched bugs 16880 and 16791 19 Dec 2005 - Resolved the following bug reports/feature requests from RT: 1363, 2944, 3346, 3850, 4104, 4380, 4384, 4469, 5275, 5282, 6751, 6786, 7287, 7819 - Straightened out $my_graph/$graph confusion in docs - Added five new sample scripts - Individual module versions now reflect a branch from original CVS versioning, in case things need to be merged at some later date. - Uploading to CPAN as 1.4305 under ~BWARFIELD because I can't seem to get in touch with Martien Verbruggen. 1 July 2003 - Fixed yet another division by 0 problem, for two_axes. - Added more tests to axestype.t - Cleaned up other test files. - Release 1.43 19 June 2003 - Fixed another division by 0 problem, introduced in 1.41 - Added test t/axestype.pm, which now tests for division by 0 error. - Released 1.42 17 June 2003 - Removed file BUGS from distribution. Too much work to keep up to date. Use rt.cpan.org, or email. - Fixed skip() calls in tests to work with ancient versions of Test.pm. - Made GD::Graph::Data::read() work with file handles under Perl 5.005. - Released 1.41 16 June 2003 - Fixed when zero axis inclusion is done for bar and are charts. - Fixed code to reserve area for hbar charts last y axis label 11 June 2003 - Added no_axes option, changed sample56 to reflect this 30 May 2003 - Added version number for GD::Text PREREQ_PM - Allow GD::Graph::Data::read() to read from file handle, instead of file - Added tests for data file reading, and test data - Release version 1.40 24 Feb 2003 - How come I never noticed this before? Right axis was disappearing when r_margin was zero. 22 Feb 2003 - Added patch by Ben Tilly from RT ticket 203 (manually, and much too late) to fix problems with picking decent values for axes when two_axes set to true. Added sample 57 20 Feb 2003 - Removed cetus font, because of unknown copyright status. - Release 1.39 (skip 1.38, internal release) 11 Feb 2003, continued after 1.37 release - Fixed version numbering - Added limited, preliminary get_feature_coordinates support. 11 Feb 2003 - Fixed =head1 in GD/Graph/FAQ.pod - release 1.37 10 Feb 2003 - Added some tests, mainly to make the CPAN testers happy :) The best way to test is still to use the samples. - Preparation for 1.36 Jan 2003 - Made detection of output formats more robust. Newer GDs break on simply testing with UNIVERSAL::can. - Added some documentation on error handling. 12 Jun 2002 - 21 Jun 2002 - Fixed various bugs: - Area charts don't allow undefined variables, die on hotspot code - allow "0.00" to be equal to 0 when determining min and max values for axes - fixed shadows for cumulative bars - Preparation for release 1.35 9 Jun 2002 - I just realised this file is severely out of date. I'll only keep track of the really big changes here, since I really can't remember what I've fixed and changed sine 1.33, and it's really too much work to go through all CVS comments. - Added hbars.pm, and put most of the framework in place to allow the other charts to be plotted rotated as well. - preparation of release 1.34 7 Oct 2000 - Addition of undefined data set colour. - Addition of bar_width option - Preparation of release 1.33 May - Sep 2000 - Various small bug fixes 7 May 2000 - Finalised code for value display - prepared for release of 1.32 6 May 2000 - Added FAQ to distribution - Fixed bug with calculation of bottom of plotting area (causing axis tick values to be cut off, when no label present) - Some 5.004 code retrogression 30 Apr 2000 - Fixed problems with overzealousness of correct_width attribute for mixed charts (report Jimmy Sieben) - Fixed problem with zero_axis and zero_axis_only drawing when y values are all on one side of 0 (report Matthew Darwin) - Fixed GD::Graph::Data::get_min_max_y and ppoints charts with numerical X axes (thanks Peter) - Fixed problem when data sets contain only zeroes (report Joe Pepin) - Added experimental support for hotspots 15 Apr 2000 - Added some code (thanks Gary) to deal better with 'numerical' X axes. - Prepared version 1.30 for release, mainly to make sure that patches that come in are done against the new code base 27 Feb 2000 - Added cumulate attribute, needs more code changes to fully replace 'overwrite == 2'. For now, it will work. 20 Feb 2000 - Added correct_width option - Fixed bug in pie. If one of the slices ended up at exactly 90 degrees, or very close to it, The fill would cause GD to core dump. Ugly. Introduced half a degree of relaxation there. There still are troubles with this. I really need to think of another way to do this. 15 - 17 Feb 2000 - Added Error class, removed error checking code from Data - Added $VERSION to each module - Fixed bug in can_do_ttf. Can now _really_ be called as static or class method. 14 Feb 2000 - Fixed bug in bar width. Removed some roundings, and always add 1 to left boundary. Also, adapt r_margin on the fly to make sure bars are always exactly the same width. This changes the look of graphs slightly, but it looks so much better in general. - Fixed bug in drawing of vertical x labels with x_tick_number enabled - Cleaned up code in setup_coords in axestype.pm a bit 12 Feb 2000 - Removed ReadFile sub from GD::Graph.pm. I never got around to making it part of the interface anyway. replaced by GD::Graph::Data. - Rewrote lots, and lots of code. General cleanup. Removal of direct work with data array. Now only works with interface of GD::Graph::Data object (hopefully) 09 Feb 2000 - Added GD::Graph::Data to distribution 27 Jan 2000 - Added patch from Hildebrand, which allows non-drawing of accents on bars with accent_treshold option - Fixed rounding problems with overwrite == 2, alert from Hildebrand, also a patch supplied which couldn't be used because of other code changes related to sample17 - Added sample18, supplied by Hildebrand as illustration of rounding problem. - Fixed off-by one error in pick_data_color whenever color pick is based on point instead of data set (cycle_clrs and pie) - Added accent_treshold option to area charts 09 Jan 2000 - Rewrote some documentation to reflect new GD::Text behaviour. 08 Jan 2000 - Rewrote set method to only accept documented attributes. - Made sure all documented attributes are part of the %Defaults hashes. - Changed inheritance slightly, because changing the set method and using access to file scoped variables didn't work very well with multiple inheritance in mixed and linespoints. All file scoped material now is kept in the common ancestor of these, i.e. axestype. 06 Jan 2000 - Added shadow patch from Jeremy Wadsack, changed a few things: Allow negative shadows, move his code out a bit more. - Added color cycling patch from Jeremy. Adapted it to new code, and added code to also allow cycling of colour of bar borders. - Documentation. 05 Jan 2000 - removed all references to perl version from any code. Leaving it up to users to find out for themselves. They'll just need to read the documentation. - Applied patch from Jeremy Wadsack fixing text sticking out of pie slices causing fills to fail. - cleanup of code in pie.pm: draw_data, filling front of pie, and _get_pie_front_coords. 03 Jan 2000 - Fixed two_axes and negative values - released 1.22 Dec 1999, mgjv - Development and support back to me, mgjv. GIFgraph and Chart::PNGgraph (hopefully) will both become wrappers around this new set of modules. - Renamed to GD::Graph - Removed direct font handling stuff, and moved font handling to GD::Text::Align objects - Removed methods for writing to files directly. it is now up to the user of the module to save the image to a file. GIFgraph and Chart::PNGgraph will still do this - plot method now returns a reference to a gd object, no longer the image data. GIFgraph and Chart::PNGgraph still exhibit old beahviour. - Added some new options, and split up some others. - Added new methods, mainly to detect the useability level of the current GD. - Changed any die and warn statements to croak and carp Thu October 21 1999 by sbonds@agora.rdrop.com - Chart::PNGgraph version 1.13 - Added primitive support for TrueType fonts - Fixed bug where 3d charts with very large slices would not have both parts of the front filled properly. Thu October 7 1999 by sbonds@agora.rdrop.com - Chart::PNGgraph version 1.12 - Changed namespace to Chart:PNGgraph so that CPAN will index it properly - Added "base" tests-- still very incomplete - Changed sample 5-2 to have multiple lines since this is what the html file described it as having. - Checks the read-only attributes 'pngx' and 'pngy' so these will not get accidently set. $g->set() returns undef if they are present, but the rest of the attributes will be set. Tue August 31 1999 by sbonds@agora.rdrop.com - Please contact me rather than the original author for problems unless you are convinced that the problems are not a result of the port to PNG - Converted GIFgraph-1.10 to PNGgraph-1.10 so it works properly with GD-1.20 - UNISYS has been increasingly defensive of the LZW patent used in GIF compression, which necessitates these kinds of fixes. Tue August 25 1998 - Fixed bug with undef values for first value in lines graphs - Changed one or two samples, and samples Makefile dependencies Tue August 25 1998 - Added bar_spacing option. - Fixed a slight drawing 'bug' while doing that. - Changed a few of the samples to use bar_spacing - Implemented numerical X axis, based on a changed axestype.pm from Scott Prahl <prahl@ece.ogi.edu>. many thanks. - Added sample54 to illustrate Tue August 18 1998 - Added rudimentary mixed type graph Mon August 17 1998 - Added control over axis label placement through x_label_position and y_label_position. - Added possibility to call a coderef to format the y labels. See y_number_format. (Idea: brian d foy <comdog@computerdog.com>) - Fixed some bugs (see file BUGS, version 1.04) Fri August 14 1998 - Uploaded version 1.03 to CPAN - Finally able to make some fixes - Changed defaults for zero_axis and zero_axis_only to 0. Were both 1. Needed to do this, because of all the confusion they cause - Test for defined $s->{y_(min|max)_value} (Honza Pazdziora <adelton@informatics.muni.cz>) (Vegard Vesterheim <vegardv@runit.sintef.no>) - Fixed handling of negative values (I hope) (brian d foy <comdog@computerdog.com>) - From now on, require 5.004. 5.003 is dead, and should be deprecated now that 5.005 is out. - Added 5.005 specific MakeMaker fields to Makefile.PL Tue May 12 1998 - Cleaned up a bit, finalised version 1.02, because of time contraints, and the need to get these bug fixes out. Didn't succeed. Mon Jan 19 1998 - Fixed some bugs (see file BUGS, version 1.02) - Added option x_all_ticks, to force all x ticks to be printed, even if x_label_skip is set. - Added option x_labels_vertical, to print x labels vertical (Thanks to DBelcher <dbelcher@cyberhino.com> for a patch) Fri Jan 9 1998 - Fixed some bugs (see file BUGS, version 1.01) - Added formatting for y labels (option y_label_format) Tue Dec 23 1997 - Changed PERL=perl5 to PERL=perl in samples/Makefile (D'OH!) - Added read_rgb to GIFgraph::colour to allow definition of own colours - Added t/colour.t - Removed a lot of unnecessary quotes all over the place Mon Dec 22 1997 - Center graph titles on axes, not on png - Added line types - Moved initialise() to each module with $self->SUPER inheritance - Added check for duplicate GD::Image object initialisation - Added binmode() to t/ff.pl to make tests compatible with Win32 platforms (D'OH). Thu Dec 18 1997 - Allow undef values in data sets, and skip them - Added prototyping of functions - Legends, finally requests from Petter Reinholdtsen <pere@link.no> Giorgos Andreadakis <gand@forthnet.gr> Tue Dec 16 1997 - Added documentation for dclrs and markers options - removed line_width and ReadFile from the documentation (unimplemented) - Started on port to win32 - Changed Area to use Polygon and to work with negative numbers Mon Dec 15 1997 - Added support for negative numbers in lines, points and linespoints graphs - Added new options: zero_axis, and zero_axis_only (code and documentation) - Added new options: y_min_value, y1_min_value, y2_min_value Fri Dec 12 1997 - Changed 0 angle for pies to be at front/bottom, to make calculations a bit easier - Added test scripts for 'make test' Before Fri Dec 05 1997 - Lots of minor tuning - Added x_ticks option requests from Will Mitayai Keeso Rowe - thelab@nmarcom.com mparvataneni@quadravision.com (Murali Parvataneni) - Added binmode() here and there to accommodate for platforms that need it. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������GDGraph-1.44/META.yml�������������������������������������������������������������������������������0000644�0001750�0000144�00000000564�10614023211�012645� 0����������������������������������������������������������������������������������������������������ustar �ben�����������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# http://module-build.sourceforge.net/META-spec.html #XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX# name: GDGraph version: 1.44 version_from: Graph.pm installdirs: site requires: GD: 1.18 GD::Text: 0.80 distribution_type: module generated_by: ExtUtils::MakeMaker version 6.21 ��������������������������������������������������������������������������������������������������������������������������������������������GDGraph-1.44/Dustismo.LICENSE�����������������������������������������������������������������������0000644�0001750�0000144�00000045227�10347716731�014237� 0����������������������������������������������������������������������������������������������������ustar �ben�����������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Dustismo is Copyright (C) 2002 Dustin Norlander Homepage: http://www.cheapskatefonts.com email: nutso@cheapskatefonts.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ------------------------------------------------------------------------------- GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. <one line to give the program's name and a brief idea of what it does.> Copyright (C) <year> <name of author> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. <signature of Ty Coon>, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������GDGraph-1.44/Makefile.PL����������������������������������������������������������������������������0000644�0001750�0000144�00000003215�10347716731�013365� 0����������������������������������������������������������������������������������������������������ustar �ben�����������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This -*- perl -*- script makes the Makefile # $Id: Makefile.PL,v 1.1 2005/12/14 04:21:45 ben Exp $ #--- Distribution section --- use ExtUtils::MakeMaker; use Config; #use ExtUtils::Manifest; #ExtUtils::Manifest::skipcheck(); my @clean = qw(*.old *.save tags); push @clean, map { "*/$_" } @clean; WriteMakefile( 'VERSION_FROM' => 'Graph.pm', #finds $VERSION 'DISTNAME' => 'GDGraph', 'NAME' => 'GD::Graph', ($] >= 5.005 ? ('ABSTRACT' => 'Produces charts with GD', 'AUTHOR' => 'Martien Verbruggen <mgjv@tradingpost.com.au>', ):() ), 'PREREQ_PM' => { 'GD' => '1.18', 'GD::Text' => '0.80', }, 'dist' => { 'COMPRESS' => 'gzip -9f', 'SUFFIX' => 'gz', }, 'clean' => { 'FILES' => join(" ", @clean), }, ); sub MY::postamble { qq( samples: all \@(cd samples && make PERL=$Config{'perlpath'}) \@echo Samples have been created in samples directory tags: ptags lib/GD/*.pm lib/GD/Graph/*.pm ) } sub MY::libscan { my ($self, $path) = @_; return if $path =~ m:(^|/)\..+\.swp$: or $path =~ m:(^|/)\.#.+\d$: or $path =~ m:\b(RCS|CVS|SCCS)\b: ; return $path; } print <<END; The automatic tests for GDGraph are not really a solid workout of the library. The best way to test the package is to run the examples before installing it. You can run the examples in the samples directory with `make samples` or by going into that directory, and just running `make`. If that fails, please read samples/Makefile. END �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������