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