1#========================================================================== 2# Copyright (c) 1995-1998 Martien Verbruggen 3#-------------------------------------------------------------------------- 4# 5# Name: 6# GIFgraph.pm 7# 8# Description: 9# Module to create graphs from a data set, outputting 10# GIF format graphics. 11# 12# Package of a number of graph types: 13# GIFgraph::bars 14# GIFgraph::lines 15# GIFgraph::points 16# GIFgraph::linespoints 17# GIFgraph::area 18# GIFgraph::pie 19# GIFgraph::mixed 20# 21# $Id: GIFgraph.pm,v 1.1.1.1 2002/02/26 10:16:37 oetiker Exp $ 22# 23#========================================================================== 24 25require 5.004; 26 27use strict; 28 29use vars qw(@ISA); 30 31# Use Lincoln Stein's GD and Thomas Boutell's libgd.a 32use GD; 33 34# 35# GIFgraph 36# 37# Parent class containing data all graphs have in common. 38# 39 40package GIFgraph; 41 42$GIFgraph::prog_name = 'GIFgraph.pm'; 43$GIFgraph::prog_rcs_rev = '$Revision: 1.1.1.1 $'; 44$GIFgraph::prog_version = 45 ($GIFgraph::prog_rcs_rev =~ /\s+(\d*\.\d*)/) ? $1 : "0.0"; 46 47$GIFgraph::VERSION = '1.10'; 48 49# Some tools and utils 50use GIFgraph::colour qw(:colours); 51 52my $OS; 53 54# Let's guess what the OS is 55# (from CGI.pm by Lincoln Stein) 56# OVERRIDE THE OS HERE IF THE GUESS IS WRONG 57 58# $OS = 'UNIX'; 59# $OS = 'MACINTOSH'; 60# $OS = 'WINDOWS'; 61# $OS = 'VMS'; 62# $OS = 'OS2'; 63 64# FIGURE OUT THE OS WE'RE RUNNING UNDER 65# Some systems support the $^O variable. If not 66# available then require() the Config library 67unless ($OS) { 68 unless ($OS = $^O) { 69 require Config; 70 $OS = $Config::Config{'osname'}; 71 } 72 if ($OS=~/Win/i) { 73 $OS = 'WINDOWS'; 74 } elsif ($OS=~/vms/i) { 75 $OS = 'VMS'; 76 } elsif ($OS=~/Mac/i) { 77 $OS = 'MACINTOSH'; 78 } elsif ($OS=~/os2/i) { 79 $OS = 'OS2'; 80 } else { 81 $OS = 'UNIX'; 82 } 83} 84 85$GIFgraph::needs_binmode = $OS=~/^(WINDOWS|VMS|OS2)/; 86 87my %GIFsize = ( 88 'x' => 400, 89 'y' => 300 90); 91 92my %Defaults = ( 93 94 # Set the top, bottom, left and right margin for the GIF. These 95 # margins will be left empty. 96 97 t_margin => 0, 98 b_margin => 0, 99 l_margin => 0, 100 r_margin => 0, 101 102 # Set the factor with which to resize the logo in the GIF (need to 103 # automatically compute something nice for this, really), set the 104 # default logo file name, and set the logo position (UR, BR, UL, BL) 105 106 logo_resize => 1.0, 107 logo => undef, 108 logo_position => 'LR', 109 110 # Write a transparent GIF? 111 112 transparent => 1, 113 114 # Write an interlaced GIF? 115 116 interlaced => 1, 117 118 # Set the background colour, the default foreground colour (used 119 # for axes etc), the textcolour, the colour for labels, the colour 120 # for numbers on the axes, the colour for accents (extra lines, tick 121 # marks, etc..) 122 123 bgclr => 'white', 124 fgclr => 'dblue', 125 textclr => 'dblue', 126 labelclr => 'dblue', 127 axislabelclr => 'dblue', 128 accentclr => 'gray', 129 130 # number of pixels to use as text spacing 131 132 text_space => 8, 133); 134 135{ 136 # 137 # PUBLIC methods, documented in pod. 138 # 139 sub new # ( width, height ) optional; 140 { 141 my $type = shift; 142 my $self = {}; 143 bless $self, $type; 144 145 if (@_) 146 { 147 # If there are any parameters, they should be the size 148 $self->{gifx} = shift; 149 150 # If there's an x size, there should also be a y size. 151 die "Usage: GIFgraph::<type>::new( [x_size, y_size] )\n" unless @_; 152 $self->{gify} = shift; 153 } 154 else 155 { 156 # There were obviously no parameters, so use defaults 157 $self->{gifx} = $GIFsize{'x'}; 158 $self->{gify} = $GIFsize{'y'}; 159 } 160 161 # Initialise all relevant parameters to defaults 162 # These are defined in the subclasses. See there. 163 $self->initialise( ); 164 165 return $self; 166 } 167 168 sub set 169 { 170 my $s = shift; 171 my %args = @_; 172 173 foreach (keys %args) 174 { 175 $s->{$_} = $args{$_}; 176 } 177 } 178 179 # These should probably not be used, or be rewritten to 180 # accept some keywords. Problem is that GD is very limited 181 # on fonts, and this routine just accepts GD font names. 182 # But.. it's not nice to require the user to include GD.pm 183 # just because she might want to change the font. 184 185 sub set_title_font # (fontname) 186 { 187 my $self = shift; 188 189 $self->{tf} = shift; 190 $self->set( 191 tfw => $self->{tf}->width, 192 tfh => $self->{tf}->height, 193 ); 194 } 195 196 sub set_text_clr # (colour name) 197 { 198 my $s = shift; 199 my $c = shift; 200 201 $s->set( 202 textclr => $c, 203 labelclr => $c, 204 axislabelclr => $c, 205 ); 206 } 207 208 sub plot # (\@data) 209 { 210 # ABSTRACT 211 my $s = shift; 212 $s->die_abstract( "sub plot missing," ); 213 } 214 215 sub plot_to_gif # ("file.gif", \@data) 216 { 217 my $s = shift; 218 my $file = shift; 219 my $data = shift; 220 221 open (GIFPLOT,">$file") || do 222 { 223 warn "Cannot open $file for writing: $!"; 224 return 0; 225 }; 226 binmode GIFPLOT if ($GIFgraph::needs_binmode); 227 print GIFPLOT $s->plot( $data ); 228 close(GIFPLOT); 229 } 230 231 # Routine to read GNU style data files 232 # NOT USEABLE 233 234 sub ReadFile 235 { 236 my $file = shift; 237 my @cols = @_; 238 my (@out, $i, $j); 239 240 @cols = 1 if ( $#cols < 1 ); 241 242 open (DATA, $file) || do { 243 warn "Cannot open file: $file"; 244 return []; 245 }; 246 247 $i=0; 248 while (defined(<DATA>)) 249 { 250 s/^\s+|\s+$//; 251 next if ( /^#/ || /^!/ || /^[ \t]*$/ ); 252 @_ = split(/[ \t]+/); 253 $out[0][$i] = $_[0]; 254 $j=1; 255 foreach (@cols) 256 { 257 if ( $_ > $#_ ) { 258 warn "Data column $_ not present"; 259 return []; 260 } 261 $out[$j][$i] = $_[$_]; $j++; 262 } 263 $i++; 264 } 265 close(DATA); 266 267 return @out; 268 269 } # ReadFile 270 271 # 272 # PRIVATE methods 273 # 274 275 # Set defaults that apply to all graph/chart types. 276 # This is called by the default initialise methods 277 # from the objects further down the tree. 278 279 sub initialise() 280 { 281 my $self = shift; 282 283 foreach (keys %Defaults) 284 { 285 $self->set( $_ => $Defaults{$_} ); 286 } 287 288 $self->set_title_font(GD::gdLargeFont); 289 290 $self->open_graph(); 291 } 292 293 294 # Check the integrity of the submitted data 295 # 296 # Checks are done to assure that every input array 297 # has the same number of data points, it sets the variables 298 # that store the number of sets and the number of points 299 # per set, and kills the process if there are no datapoints 300 # in the sets, or if there are no data sets. 301 302 sub check_data($) # \@data 303 { 304 my $self = shift; 305 my $data = shift; 306 307 $self->set(numsets => $#$data); 308 $self->set(numpoints => $#{@$data[0]}); 309 310 ( $self->{numsets} < 1 || $self->{numpoints} < 0 ) && die "No Data"; 311 312 my $i; 313 for $i ( 1..$self->{numsets} ) 314 { 315 die "Data array $i: length misfit" 316 unless ( $self->{numpoints} == $#{@$data[$i]} ); 317 } 318 } 319 320 # Open the graph output canvas by creating a new GD object. 321 322 sub open_graph() 323 { 324 my $self = shift; 325 if ( !exists $self->{graph} ) 326 { 327 my $graph = new GD::Image($self->{gifx}, $self->{gify}); 328 $self->{graph} = $graph; 329 return $graph; 330 } 331 else 332 { 333 return $self->{graph}; 334 } 335 } 336 337 # Initialise the graph output canvas, setting colours (and getting back 338 # index numbers for them) setting the graph to transparent, and 339 # interlaced, putting a logo (if defined) on there. 340 341 sub init_graph($) # GD::Image 342 { 343 my $self = shift; 344 my $graph = shift; 345 346 $self->{bgci} = $self->set_clr( $graph, _rgb($self->{bgclr}) ); 347 $self->{fgci} = $self->set_clr( $graph, _rgb($self->{fgclr}) ); 348 $self->{tci} = $self->set_clr( $graph, _rgb($self->{textclr}) ); 349 $self->{lci} = $self->set_clr( $graph, _rgb($self->{labelclr}) ); 350 $self->{alci} = $self->set_clr( $graph, _rgb($self->{axislabelclr}) ); 351 $self->{acci} = $self->set_clr( $graph, _rgb($self->{accentclr}) ); 352 $graph->transparent($self->{bgci}) if $self->{transparent}; 353 $graph->interlaced($self->{interlaced}); 354 $self->put_logo($graph); 355 } 356 357 # read in the logo, and paste it on the graph canvas 358 359 sub put_logo($) # GD::Image 360 { 361 my $self = shift; 362 my $graph = shift; 363 364 return unless(defined($self->{logo})); 365 366 my ($x, $y, $glogo); 367 my $r = $self->{logo_resize}; 368 369 my $r_margin = (defined $self->{r_margin_abs}) ? 370 $self->{r_margin_abs} : $self->{r_margin}; 371 my $b_margin = (defined $self->{b_margin_abs}) ? 372 $self->{b_margin_abs} : $self->{b_margin}; 373 374 open(GIFLOGO, $self->{logo}) || return; 375 binmode(GIFLOGO) if ($GIFgraph::needs_binmode); 376 unless ( $glogo = newFromGif GD::Image(\*GIFLOGO) ) 377 { 378 warn "Problems reading $self->{logo}"; 379 close(GIFLOGO); 380 return; 381 } 382 close(GIFLOGO); 383 384 my ($w, $h) = $glogo->getBounds; 385 LOGO: for ($self->{logo_position}) { 386 /UL/i && do { 387 $x = $self->{l_margin}; 388 $y = $self->{t_margin}; 389 last LOGO; 390 }; 391 /UR/i && do { 392 $x = $self->{gifx} - $r_margin - $w * $r; 393 $y = $self->{t_margin}; 394 last LOGO; 395 }; 396 /LL/i && do { 397 $x = $self->{l_margin}; 398 $y = $self->{gify} - $b_margin - $h * $r; 399 last LOGO; 400 }; 401 # default "LR" 402 $x = $self->{gifx} - $r_margin - $r * $w; 403 $y = $self->{gify} - $b_margin - $r * $h; 404 last LOGO; 405 } 406 $graph->copyResized($glogo, $x, $y, 0, 0, $r * $w, $r * $h, $w, $h); 407 undef $glogo; 408 } 409 410 # Set a colour to work with on the canvas, by rgb value. 411 # Return the colour index in the palette 412 413 sub set_clr($$$$) # GD::Image, r, g, b 414 { 415 my $s = shift; 416 my $g = shift; 417 my $i; 418 419 # Check if this colour already exists on the canvas 420 if ( ( $i = $g->colorExact( @_ ) ) < 0 ) 421 { 422 # if not, allocate a new one, and return it's index 423 return $g->colorAllocate( @_ ); 424 } 425 return $i; 426 } 427 428 # Set a colour, disregarding wether or not it already exists. 429 430 sub set_clr_uniq($$$$) # GD::Image, r, g, b 431 { 432 my $s=shift; 433 my $g=shift; 434 435 $g->colorAllocate( @_ ); 436 } 437 438 # Return an array of rgb values for a colour number 439 440 sub pick_data_clr($) # number 441 { 442 my $s = shift; 443 444 # Set up the data colour list if it doesn't exist yet. 445 # It seemed easier & more robust to me to do it here rather than 446 # relying on users doing it. AF 447 $s->set( 448 dclrs => [ qw(lred lgreen lblue lyellow lpurple lbrown cyan 449 lorange marine dyellow red green yellow blue 450 lgray dbrown purple orange pink gold)] 451 ) unless ( exists $s->{dclrs} ); 452 453 return _rgb( $s->{dclrs}[ $_[0] % (1+$#{$s->{dclrs}}) -1 ] ); 454 } 455 456 # DEBUGGING 457 # data_dump obsolete now, use Data::Dumper 458 459 sub die_abstract() 460 { 461 my $s = shift; 462 my $msg = shift; 463 # ABSTRACT 464 die 465 "Subclass (" . 466 ref($s) . 467 ") not implemented correctly: " . 468 (defined($msg) ? $msg : "unknown error"); 469 } 470 471 # Return the gif contents 472 473 sub gifdata() 474 { 475 my $s = shift; 476 477 return $s->{graph}->gif; 478 } 479 480} # End of package GIFgraph 481 482$GIFgraph::prog_name; 483 484__END__ 485 486=head1 NAME 487 488GIFgraph - Graph Plotting Module for Perl 5 489 490=head1 SYNOPSIS 491 492use GIFgraph::moduleName; 493 494=head1 DESCRIPTION 495 496B<GIFgraph> is a I<perl5> module to create and display GIF output 497for a graph. 498The following classes for graphs with axes are defined: 499 500=over 4 501 502=item C<GIFgraph::lines> 503 504Create a line chart. 505 506=item C<GIFgraph::bars> 507 508Create a bar chart. 509 510=item C<GIFgraph::points> 511 512Create an chart, displaying the data as points. 513 514=item C<GIFgraph::linespoints> 515 516Combination of lines and points. 517 518=item C<GIFgraph::area> 519 520Create a graph, representing the data as areas under a line. 521 522=item C<GIFgraph::mixed> 523 524Create a mixed type graph, any combination of the above. At the moment 525this is fairly limited. Some of the options that can be used with some 526of the individual graph types won't work very well. Multiple bar 527graphs in a mixed graph won't display very nicely. 528 529=back 530 531Additional types: 532 533=over 4 534 535=item C<GIFgraph::pie> 536 537Create a pie chart. 538 539=back 540 541=head1 EXAMPLES 542 543See the samples directory in the distribution. 544 545=head1 USAGE 546 547Fill an array of arrays with the x values and the values of the data 548sets. Make sure that every array is the same size, otherwise 549I<GIFgraph> will complain and refuse to compile the graph. 550 551 @data = ( 552 ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], 553 [ 1, 2, 5, 6, 3, 1.5, 1, 3, 4] 554 [ sort { $a <=> $b } (1, 2, 5, 6, 3, 1.5, 1, 3, 4) ] 555 ); 556 557If you don't have a value for a point in a certain dataset, you can 558use B<undef>, and I<GIFgraph> will skip that point. 559 560Create a new I<GIFgraph> object by calling the I<new> operator on the 561graph type you want to create (I<chart> is I<bars, lines, points, 562linespoints> or I<pie>). 563 564 $my_graph = new GIFgraph::chart( ); 565 566Set the graph options. 567 568 $my_graph->set( 569 x_label => 'X Label', 570 y_label => 'Y label', 571 title => 'Some simple graph', 572 y_max_value => 8, 573 y_tick_number => 8, 574 y_label_skip => 2 575 ); 576 577Output the graph 578 579 $my_graph->plot_to_gif( "sample01.gif", \@data ); 580 581=head1 METHODS AND FUNCTIONS 582 583=head2 Methods for all graphs 584 585=over 4 586 587=item new GIFgraph::chart([width,height]) 588 589Create a new object $graph with optional width and heigth. 590Default width = 400, default height = 300. I<chart> is either 591I<bars, lines, points, linespoints, area> or I<pie>. 592 593=item set_text_clr( I<colour name> ) 594 595Set the colour of the text. This will set the colour of the titles, 596labels, and axis labels to I<colour name>. Also see the options 597I<textclr>, I<labelclr> and I<axislabelclr>. 598 599=item set_title_font( I<fontname> ) 600 601Set the font that will be used for the title of the chart. Possible 602choices are defined in L<GD>. 603B<NB.> If you want to use this function, you'll 604need to use L<GD>. At some point I'll rewrite this, so you can give this a 605number from 1 to 4, or a string like 'large' or 'small'. On the other 606hand, I might not, if Thomas Boutell decides to support more fonts. 607 608=item plot( I<\@data> ) 609 610Plot the chart, and return the GIF data. 611 612=item plot_to_gif( F<filename>, I<\@data> ) 613 614Plot the chart, and write the GIF data to I<filename>. 615 616=item set( key1 => value1, key2 => value2 .... ) 617 618Set chart options. See OPTIONS section. 619 620=back 621 622=head2 Methods for Pie charts 623 624=over 4 625 626=item set_label_font( I<fontname> ) 627 628=item set_value_font( I<fontname> ) 629 630Set the font that will be used for the label of the pie or the 631values on the pie. Possible choices are defined in L<GD>. 632See also I<set_title_font>. 633 634=back 635 636 637=head2 Methods for charts with axes. 638 639=over 4 640 641=item set_x_label_font ( I<font name> ) 642 643=item set_y_label_font ( I<font name> ) 644 645=item set_x_axis_font ( I<font name> ) 646 647=item set_y_axis_font ( I<font name> ) 648 649Set the font for the x and y axis label, and for the x and y axis 650value labels. 651See also I<set_title_font>. 652 653=back 654 655 656=head1 OPTIONS 657 658=head2 Options for all graphs 659 660=over 4 661 662=item gifx, gify 663 664The width and height of the gif file in pixels 665Default: 400 x 300. 666B<NB> At the moment, these are read-only options. If you want to set 667the size of a graph, you will have to do that with the I<new> method. 668 669=item t_margin, b_margin, l_margin, r_margin 670 671Top, bottom, left and right margin of the GIF. These margins will be 672left blank. 673Default: 0 for all. 674 675=item logo 676 677Name of a logo file. This should be a GIF file. 678Default: no logo. 679 680=item logo_resize, logo_position 681 682Factor to resize the logo by, and the position on the canvas of the 683logo. Possible values for logo_position are 'LL', 'LR', 'UL', and 684'UR'. (lower and upper left and right). 685Default: 'LR'. 686 687=item transparent 688 689If set to a true value, the produced GIF will have the background 690colour marked as transparent (see also option I<bgclr>). Default: 1. 691 692=item interlaced 693 694If set to a true value, the produced GIF will be interlaced. 695Default: 1. 696 697=item bgclr, fgclr, textclr, labelclr, axislabelclr, accentclr 698 699Background, foreground, text, label, axis label and accent colours. 700 701=item dclrs (short for datacolours) 702 703This controls the colours for the bars, lines, markers, or pie slices. 704This should be a reference to an array of colour names as defined in 705L<GIFgraph::colour> (C<S<perldoc GIFgraph::colour>> for the names available). 706 707 $graph->set( dclrs => [ qw(green pink blue cyan) ] ); 708 709The first (fifth, ninth) data set will be green, the next pink, etc. 710Default: [ qw(lred lgreen lblue lyellow lpurple cyan lorange) ] 711 712=back 713 714=head2 Options for graphs with axes. 715 716options for I<bars>, I<lines>, I<points>, I<linespoints> and 717I<area> charts. 718 719=over 4 720 721=item long_ticks, tick_length 722 723If I<long_ticks> is a true value, ticks will be drawn the same length 724as the axes. Otherwise ticks will be drawn with length 725I<tick_length>. if I<tick_length> is negative, the ticks will be drawn 726outside the axes. Default: long_ticks = 0, tick_length = 4. 727 728=item x_ticks 729 730If I<x_ticks> is a true value, ticks will be drawm for the x axis. 731These ticks are subject to the values of I<long_ticks> and 732I<tick_length>. Default: 1. 733 734=item y_tick_number 735 736Number of ticks to print for the Y axis. Use this, together with 737I<y_label_skip> to control the look of ticks on the y axis. 738Default: 5. 739 740=item y_number_format 741 742This can be either a string, or a reference to a subroutine. If it is 743a string, it will be taken to be the first argument to an sprintf, 744with the value as the second argument: 745 746 $label = sprintf( $s->{y_number_format, $value ); 747 748If it is a code reference, it will be executed with the value as the 749argument: 750 751 $label = &{$s->{y_number_format}}($value); 752 753This can be useful, for example, if you want to reformat your values 754in currency, with the - sign in the right spot. Something like: 755 756 sub y_format 757 { 758 my $value = shift; 759 my $ret; 760 761 if ($value >= 0) 762 { 763 $ret = sprintf("\$%d", $value * $refit); 764 } 765 else 766 { 767 $ret = sprintf("-\$%d", abs($value) * $refit); 768 } 769 770 return $ret; 771 } 772 773 $my_graph->set( 'y_number_format' => \&y_format ); 774 775(Yes, I know this can be much shorter and more concise) 776 777Default: undef. 778 779=item x_label_skip, y_label_skip 780 781Print every I<x_label_skip>th number under the tick on the x axis, and 782every I<y_label_skip>th number next to the tick on the y axis. 783Default: 1 for both. 784 785=item x_all_ticks 786 787Force a print of all the x ticks, even if x_label_skip is set to a value 788Default: 0. 789 790=item x_label_position 791 792Controls the position of the X axis label (title). The value for this 793should be between 0 and 1, where 0 means aligned to the left, 1 means 794aligned to the right, and 1/2 means centered. 795Default: 3/4 796 797=item y_label_position 798 799Controls the position of both Y axis labels (titles). The value for 800this should be between 0 and 1, where 0 means aligned to the bottom, 1 801means aligned to the top, and 1/2 means centered. 802Default: 1/2 803 804=item x_labels_vertical 805 806If set to a true value, the X axis labels will be printed vertically. 807This can be handy in case these labels get very long. 808Default: 0. 809 810=item x_plot_values, y_plot_values 811 812If set to a true value, the values of the ticks on the x or y axes 813will be plotted next to the tick. Also see I<x_label_skip, 814y_label_skip>. Default: 1 for both. 815 816=item box_axis 817 818Draw the axes as a box, if true. 819Default: 1. 820 821=item two_axes 822 823Use two separate axes for the first and second data set. The first 824data set will be set against the left axis, the second against the 825right axis. If this is set to a true value, trying to use anything 826else than 2 datasets will generate an error. Default: 0. 827 828=item zero_axis 829 830If set to a true value, the axis for y values of 0 will always be 831drawn. This might be useful in case your graph contains negative 832values, but you want it to be clear where the zero value is. (see also 833I<zero_axis_only> and I<box_axes>). 834Default: 0. 835 836=item zero_axis_only 837 838If set to a true value, the zero axis will be drawn (see 839I<zero_axis>), and no axis at the bottom of the graph will be drawn. 840The labels for X values will be placed on the zero exis. 841Default: 0. 842 843=item y_max_value, y_min_value 844 845Maximum and minimum value displayed on the y axis. If two_axes is a 846true value, then y1_min_value, y1_max_value (for the left axis), 847and y2_min_value, y2_max_value (for the right axis) take precedence 848over these. 849 850The range (y_min_value..y_max_value) has to include all the values of 851the data points, or I<GIFgraph> will die with a message. 852 853For bar and area graphs, the range (y_min_value..y_max_value) has to 854include 0. If it doesn't, the values will be adapted before attempting 855to draw the graph. 856 857Default: Computed from data sets. 858 859=item axis_space 860 861This space will be left blank between the axes and the text. 862Default: 4. 863 864=item overwrite 865 866If set to 0, bars of different data sets will be drawn next to each 867other. If set to 1, they will be drawn in front of each other. If set 868to 2 they will be drawn on top of each other. 869Default: 0. 870 871If you have negative values in your data sets, setting overwrite to 2 872might produce odd results. Of course, the graph itself would be quite 873meaningless, because overwrite = 2 is meant to show some cumulative 874effect. 875 876=back 877 878=head2 Options for graphs with a numerical X axis 879 880First of all: GIFgraph does B<not> support numerical x axis the way it 881should. Data for X axes should be equally spaced. That understood: 882There is some support to make the printing of graphs with numerical X 883axis values a bit better, thanks to Scott Prahl. If the option 884C<x_tick_number> is set to a defined value, GIFgraph will attempt to 885treat the X data as numerical. 886 887Extra options are: 888 889=over 4 890 891=item x_tick_number 892 893If set to I<'auto'>, GIFgraph will attempt to format the X axis in a 894nice way, based on the actual X values. If set to a number, that's the 895number of ticks you will get. If set to undef, GIFgraph will treat X 896data as labels. 897Default: undef. 898 899=item x_min_value, x_max_value 900 901The minimum and maximum value to use for the X axis. 902Default: computed. 903 904=item x_number_format 905 906See y_number_format 907 908=item x_label_skip 909 910See y_label_skip 911 912=back 913 914 915=head2 Options for graphs with bars 916 917=over 4 918 919=item bar_spacing 920 921Number of pixels to leave open between bars. This works well in most 922cases, but on some platforms, a value of 1 will be rounded off to 0. 923Default: 0 924 925=back 926 927=head2 Options for graphs with lines 928 929=over 4 930 931=item line_types 932 933Which line types to use for I<lines> and I<linespoints> graphs. This 934should be a reference to an array of numbers: 935 936 $graph->set( line_types => [3, 2, 4] ); 937 938Available line types are 1: solid, 2: dashed, 3: dotted, 4: 939dot-dashed. 940 941Default: [1] (always use solid) 942 943=item line_type_scale 944 945Controls the length of the dashes in the line types. default: 6. 946 947=item line_width 948 949The width of the line used in I<lines> and I<linespoints> graphs, in pixels. 950Default: 1. 951 952=back 953 954=head2 Options for graphs with points 955 956=over 4 957 958=item markers 959 960This controls the order of markers in I<points> and I<linespoints> 961graphs. This should be a reference to an array of numbers: 962 963 $graph->set( markers => [3, 5, 6] ); 964 965Available markers are: 1: filled square, 2: open square, 3: horizontal 966cross, 4: diagonal cross, 5: filled diamond, 6: open diamond, 7: 967filled circle, 8: open circle. 968 969Default: [1,2,3,4,5,6,7,8] 970 971=item marker_size 972 973The size of the markers used in I<points> and I<linespoints> graphs, 974in pixels. Default: 4. 975 976=back 977 978=head2 Options for mixed graphs 979 980=over 4 981 982=item types 983 984A reference to an array with graph types, in the same order as the 985data sets. Possible values are: 986 987 $graph->set( types => [qw(lines bars points area linespoints)] ); 988 $graph->set( types => ['lines', undef, undef, 'bars'] ); 989 990values that are undefined or unknown will be set to C<default_type>. 991 992Default: all set to C<default_type> 993 994=item default_type 995 996The type of graph to draw for data sets that either have no type set, 997or that have an unknown type set. 998 999Default: lines 1000 1001=back 1002 1003=head2 Graph legends (axestype graphs only) 1004 1005At the moment legend support is minimal. 1006 1007B<Methods> 1008 1009=over 4 1010 1011=item set_legend( I<@legend_keys> ); 1012 1013Sets the keys for the legend. The elements of @legend_keys correspond 1014to the data sets as provided to I<plot()> or I<plot_to_gif()>. 1015 1016If a key is I<undef> or an empty string, the legend entry will be skipped. 1017 1018=item set_legend_font( I<font name> ); 1019 1020Sets the font for the legend text (see also I<set_title_font>). 1021Default: GD::gdTinyFont. 1022 1023=back 1024 1025B<Options> 1026 1027=over 4 1028 1029=item legend_placement 1030 1031Where to put the legend. This should be a two letter key of the form: 1032'B[LCR]|R[TCB]'. The first letter sigifies the placement (I<B>ottom or 1033I<R>ight), and the second letter signifies the alignment (I<L>eft, 1034I<R>ight, I<C>enter, I<T>op, or I<B>ottom). 1035Default: 'BC' 1036 1037If the legend is placed at the bottom, some calculations will be made 1038to ensure that there is some 'intelligent' wrapping going on. if the 1039legend is placed at the right, all entries will be placed below each 1040other. 1041 1042=item legend_spacing 1043 1044The number of pixels to place around a legend item, and between a 1045legend 'marker' and the text. 1046Default: 4 1047 1048=item legend_marker_width, legend_marker_height 1049 1050The width and height of a legend 'marker' in pixels. 1051Defaults: 12, 8 1052 1053=item lg_cols 1054 1055If you, for some reason, need to force the legend at the bottom to 1056have a specific number of columns, you can use this. 1057Default: computed 1058 1059=back 1060 1061 1062=head2 Options for pie graphs 1063 1064=over 4 1065 1066=item 3d 1067 1068If set to a true value, the pie chart will be drawn with a 3d look. 1069Default: 1. 1070 1071=item pie_height 1072 1073The thickness of the pie when I<3d> is true. 1074Default: 0.1 x GIF y size. 1075 1076=item start_angle 1077 1078The angle at which the first data slice will be displayed, with 0 degrees 1079being "6 o'clock". 1080Default: 0. 1081 1082=back 1083 1084=head1 NOTES 1085 1086All references to colours in the options for this module have been 1087shortened to clr. The main reason for this was that I didn't want to 1088support two spellings for the same word ('colour' and 'color') 1089 1090Wherever a colour is required, a colour name should be used from the 1091package L<GIFgraph::colour>. C<S<perldoc GIFgraph::colour>> should give 1092you the documentation for that module, containing all valid colour 1093names. I will probably change this to read the systems rgb.txt file if 1094it is available. 1095 1096Wherever a font name is required, a font from L<GD> should be used. 1097 1098=head1 AUTHOR 1099 1100Martien Verbruggen 1101 1102=head2 Contact info 1103 1104email: mgjv@comdyn.com.au 1105 1106=head2 Copyright 1107 1108Copyright (C) 1995-1998 Martien Verbruggen. 1109All rights reserved. This package is free software; you can redistribute it 1110and/or modify it under the same terms as Perl itself. 1111 1112=cut 1113 1114# WWW: L<http://www.tcp.chem.tue.nl/~tgtcmv/> 1115