remove code for older (ancient) versions of Imager
[imager-graph.git] / Graph.pm
CommitLineData
35574351 1package Imager::Graph;
54ada35d 2require 5.005;
35574351
TC
3
4=head1 NAME
5
6Imager::Graph - Perl extension for producing Graphs using the Imager library.
7
8=head1 SYNOPSIS
9
2eac77fc 10 use Imager::Graph::Sub_class;
11 my $chart = Imager::Graph::Sub_class->new;
81453d28 12 my $img = $chart->draw(data=> \@data, ...)
35574351 13 or die $chart->error;
1509eee7 14 $img->write(file => 'image.png');
35574351
TC
15
16=head1 DESCRIPTION
17
18Imager::Graph provides style information to its base classes. It
19defines the colors, text display information and fills based on both
20built-in styles and modifications supplied by the user to the draw()
21method.
22
35574351
TC
23=over
24
25=cut
26
27use strict;
28use vars qw($VERSION);
29use Imager qw(:handy);
bb0de914 30use Imager::Fountain;
35574351 31
aac2cfef 32$VERSION = '0.07';
35574351 33
35574351
TC
34# the maximum recursion depth in determining a color, fill or number
35use constant MAX_DEPTH => 10;
36
37my $NUM_RE = '(?:[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]\d+?)?)';
38
39=item new
40
41This is a simple constructor. No parameters required.
42
43=cut
44
45sub new {
46 bless {}, $_[0];
47}
48
2eac77fc 49=item set_graph_size($size)
dfd889da 50
51Sets the size of the graph (in pixels) within the image. The size of the image defaults to 1.5 * $graph_size.
52
53=cut
54
2eac77fc 55sub set_graph_size {
56 $_[0]->{'custom_style'}->{'size'} = $_[1];
dfd889da 57}
58
2eac77fc 59=item set_image_width($width)
dfd889da 60
61Sets the width of the image in pixels.
62
63=cut
64
2eac77fc 65sub set_image_width {
66 $_[0]->{'custom_style'}->{'width'} = $_[1];
dfd889da 67}
68
2eac77fc 69=item set_image_height($height)
dfd889da 70
71Sets the height of the image in pixels.
72
73=cut
74
2eac77fc 75sub set_image_height {
76 $_[0]->{'custom_style'}->{'height'} = $_[1];
dfd889da 77}
78
2eac77fc 79=item add_data_series([8, 6, 7, 5, 3, 0, 9], 'Series Name');
dfd889da 80
81Adds a data series to the graph. For L<Imager::Graph::Pie>, only one data series can be added.
82
83=cut
84
2eac77fc 85sub add_data_series {
dfd889da 86 my $self = shift;
87 my $data_ref = shift;
88 my $series_name = shift;
89
90 my $graph_data = $self->{'graph_data'} || [];
91
92 push @$graph_data, { data => $data_ref, series_name => $series_name };
1509eee7 93 if (defined $series_name) {
94 push @{$self->{'labels'}}, $series_name;
95 }
dfd889da 96
97 $self->{'graph_data'} = $graph_data;
98 return;
99}
100
2eac77fc 101sub _get_data_series {
a17e870a
TC
102 my ($self, $opts) = @_;
103
104 # return the data supplied to draw() if any.
105 if ($opts->{data}) {
106 # one or multiple series?
107 my $data = $opts->{data};
108 if (@$data && ref $data->[0] && ref $data->[0] =~ /ARRAY/) {
109 return $data;
110 }
111 else {
112 return [ { data => $data } ];
113 }
114 }
115
116 return $self->{'graph_data'};
dfd889da 117}
118
2eac77fc 119=item set_labels(['label1', 'label2' ... ])
dfd889da 120
121Labels the specific data points. For line/bar graphs, this is the x-axis. For pie graphs, it is the label for the wedges.
122
123=cut
124
2eac77fc 125sub set_labels {
dfd889da 126 $_[0]->{'labels'} = $_[1];
127}
128
2eac77fc 129sub _get_labels {
a17e870a
TC
130 my ($self, $opts) = @_;
131
132 $opts->{labels}
133 and return $opts->{labels};
134
dfd889da 135 return $_[0]->{'labels'}
136}
137
2eac77fc 138=item set_title($title)
dfd889da 139
140Sets the title of the graph. Requires setting a font.
141
142=cut
143
2eac77fc 144sub set_title {
145 $_[0]->{'custom_style'}->{'title'}->{'text'} = $_[1];
dfd889da 146}
147
2eac77fc 148=item set_font($font)
dfd889da 149
150Sets the font to use for text. Takes an L<Imager::Font> object.
151
152=cut
153
2eac77fc 154sub set_font {
155 $_[0]->{'custom_style'}->{'font'} = $_[1];
dfd889da 156}
157
2eac77fc 158=item set_style($style_name)
dfd889da 159
160Sets the style to be used for the graph. Imager::Graph comes with several pre-defined styles: fount_lin (default), fount_rad, mono, primary_red, and primary.
161
162=cut
163
2eac77fc 164sub set_style {
dfd889da 165 $_[0]->{'style'} = $_[1];
166}
167
2eac77fc 168sub _get_style {
a17e870a
TC
169 my ($self, $opts) = @_;
170
171 $opts->{style}
172 and return $opts->{style};
173
174 return $self->{'style'};
dfd889da 175}
176
35574351
TC
177=item error
178
a22672ea 179Returns an error message. Only valid if the draw() method returns false.
35574351
TC
180
181=cut
182
183sub error {
184 $_[0]->{_errstr};
185}
186
187=item draw
188
189Creates a new image, draws the chart onto that image and returns it.
190
2eac77fc 191Optionally, instead of using the api methods to configure your chart,
192you can supply a C<data> parameter in the format
35574351
TC
193required by that particular graph, and if your graph will use any
194text, a C<font> parameter
195
196You can also supply many different parameters which control the way
197the graph looks. These are supplied as keyword, value pairs, where
198the value can be a hashref containing sub values.
199
200The C<style> parameter will selects a basic color set, and possibly
201sets other related parameters. See L</"STYLES">.
202
aaaa03e1 203 my $font = Imager::Font->new(file => 'ImUgly.ttf');
81453d28 204 my $img = $chart->draw(
205 data => \@data,
206 font => $font,
207 title => {
208 text => "Hello, World!",
209 size => 36,
210 color => 'FF0000'
211 }
212 );
35574351
TC
213
214When referring to a single sub-value this documentation will refer to
215'title.color' rather than 'the color element of title'.
216
217Returns the graph image on success, or false on failure.
218
219=back
220
221=head1 STYLES
222
223The currently defined styles are:
224
225=over
226
7b94e723
TC
227=item primary
228
229a light grey background with no outlines. Uses primary colors for the
230data fills.
231
35574351
TC
232=item primary_red
233
234a light red background with no outlines. Uses primary colors for the
7b94e723 235data fills.
35574351
TC
236
237Graphs drawn using this style should save well as a gif, even though
238some graphs may perform a slight blur.
239
7b94e723 240This was the default style, but the red was too loud.
35574351
TC
241
242=item mono
243
244designed for monochrome output, such as most laser printers, this uses
245hatched fills for the data, and no colors. The returned image is a
246one channel image (which can be overridden with the C<channels>
247parameter.)
248
249You can also override the colors used by all components for background
250or drawing by supplying C<fg> and/or C<bg> parameters. ie. if you
251supply C<<fg=>'FF0000', channels=>3>> then the hash fills and anything
252else will be drawn in red. Another use might be to set a transparent
253background, by supplying C<<bg=>'00000000', channels=>4>>.
254
255This style outlines the legend if present and outlines the hashed fills.
256
35574351
TC
257=item fount_lin
258
259designed as a "pretty" style this uses linear fountain fills for the
260background and data fills, and adds a drop shadow.
261
262You can override the value used for text and outlines by setting the
263C<fg> parameter.
264
81453d28 265This is the default style.
266
35574351
TC
267=item fount_rad
268
269also designed as a "pretty" style this uses radial fountain fills for
270the data and a linear blue to green fill for the background.
271
272=back
273
2eac77fc 274=head1 Style API
275
276To set or override styles, you can use the following methods:
277
278=over 4
279
280=item set_image_background
281
282=cut
283
284sub set_image_background {
285 $_[0]->{'custom_style'}->{'back'} = $_[1];
286}
287
288=item set_channels
289
290=cut
291
292sub set_channels {
293 $_[0]->{'custom_style'}->{'channels'} = $_[1];
294}
295
296=item set_line_color
297
298=cut
299
300sub set_line_color {
301 $_[0]->{'custom_style'}->{'line'} = $_[1];
302}
303
304=item set_title_font_size
305
306=cut
307
308sub set_title_font_size {
309 $_[0]->{'custom_style'}->{'title'}->{'size'} = $_[1];
310}
311
312=item set_title_font_color
313
314=cut
315
316sub set_title_font_color {
317 $_[0]->{'custom_style'}->{'title'}->{'color'} = $_[1];
318}
319
320=item set_title_horizontal_align
321
322=cut
323
324sub set_title_horizontal_align {
325 $_[0]->{'custom_style'}->{'title'}->{'halign'} = $_[1];
326}
327
328=item set_title_vertical_align
329
330=cut
331
332sub set_title_vertical_align {
333 $_[0]->{'custom_style'}->{'title'}->{'valign'} = $_[1];
334}
335
336=item set_text_font_color
337
338=cut
339
340sub set_text_font_color {
341 $_[0]->{'custom_style'}->{'text'}->{'color'} = $_[1];
342}
343
344=item set_text_font_size
345
346=cut
347
348sub set_text_font_size {
349 $_[0]->{'custom_style'}->{'text'}->{'size'} = $_[1];
350}
351
352=item set_graph_background_color
353
354=cut
355
356sub set_graph_background_color {
357 $_[0]->{'custom_style'}->{'bg'} = $_[1];
358}
359
360=item set_graph_foreground_color
361
362=cut
363
364sub set_graph_foreground_color {
365 $_[0]->{'custom_style'}->{'fg'} = $_[1];
366}
367
368=item set_legend_font_color
369
370=cut
371
372sub set_legend_font_color {
373 $_[0]->{'custom_style'}->{'legend'}->{'color'} = $_[1];
374}
375
376=item set_legend_font
377
378=cut
379
380sub set_legend_font {
381 $_[0]->{'custom_style'}->{'legend'}->{'font'} = $_[1];
382}
383
384=item set_legend_font_size
385
386=cut
387
388sub set_legend_font_size {
389 $_[0]->{'custom_style'}->{'legend'}->{'size'} = $_[1];
390}
391
392=item set_legend_patch_size
393
394=cut
395
396sub set_legend_patch_size {
397 $_[0]->{'custom_style'}->{'legend'}->{'patchsize'} = $_[1];
398}
399
400=item set_legend_patch_gap
401
402=cut
403
404sub set_legend_patch_gap {
405 $_[0]->{'custom_style'}->{'legend'}->{'patchgap'} = $_[1];
406}
407
408=item set_legend_horizontal_align
409
410=cut
411
412sub set_legend_horizontal_align {
413 $_[0]->{'custom_style'}->{'legend'}->{'halign'} = $_[1];
414}
415
416=item set_legend_vertical_align
417
418=cut
419
420sub set_legend_vertical_align {
421 $_[0]->{'custom_style'}->{'legend'}->{'valign'} = $_[1];
422}
423
424=item set_legend_padding
425
426=cut
427
428sub set_legend_padding {
429 $_[0]->{'custom_style'}->{'legend'}->{'padding'} = $_[1];
430}
431
432=item set_legend_outside_padding
433
434=cut
435
436sub set_legend_outside_padding {
437 $_[0]->{'custom_style'}->{'legend'}->{'outsidepadding'} = $_[1];
438}
439
440=item set_legend_fill
441
442=cut
443
444sub set_legend_fill {
445 $_[0]->{'custom_style'}->{'legend'}->{'fill'} = $_[1];
446}
447
448=item set_legend_border
449
450=cut
451
452sub set_legend_border {
453 $_[0]->{'custom_style'}->{'legend'}->{'border'} = $_[1];
454}
455
456=item set_legend_orientation
457
458=cut
459
460sub set_legend_orientation {
461 $_[0]->{'custom_style'}->{'legend'}->{'orientation'} = $_[1];
462}
463
464=item set_callout_font_color
465
466=cut
467
468sub set_callout_font_color {
469 $_[0]->{'custom_style'}->{'callout'}->{'color'} = $_[1];
470}
471
472=item set_callout_font
473
474=cut
475
476sub set_callout_font {
477 $_[0]->{'custom_style'}->{'callout'}->{'font'} = $_[1];
478}
479
480=item set_callout_font_size
481
482=cut
483
484sub set_callout_font_size {
485 $_[0]->{'custom_style'}->{'callout'}->{'size'} = $_[1];
486}
487
488=item set_callout_line_color
489
490=cut
491
492sub set_callout_line_color {
493 $_[0]->{'custom_style'}->{'callout'}->{'line'} = $_[1];
494}
495
496=item set_callout_leader_inside_length
497
498=cut
499
500sub set_callout_leader_inside_length {
501 $_[0]->{'custom_style'}->{'callout'}->{'inside'} = $_[1];
502}
503
504=item set_callout_leader_outside_length
505
506=cut
507
508sub set_callout_leader_outside_length {
509 $_[0]->{'custom_style'}->{'callout'}->{'outside'} = $_[1];
510}
511
512=item set_callout_leader_length
513
514=cut
515
516sub set_callout_leader_length {
517 $_[0]->{'custom_style'}->{'callout'}->{'leadlen'} = $_[1];
518}
519
520=item set_callout_gap
521
522=cut
523
524sub set_callout_gap {
525 $_[0]->{'custom_style'}->{'callout'}->{'gap'} = $_[1];
526}
527
528=item set_label_font_color
529
530=cut
531
532sub set_label_font_color {
533 $_[0]->{'custom_style'}->{'label'}->{'color'} = $_[1];
534}
535
536=item set_label_font
537
538=cut
539
540sub set_label_font {
541 $_[0]->{'custom_style'}->{'label'}->{'font'} = $_[1];
542}
543
544=item set_label_font_size
545
546=cut
547
548sub set_label_font_size {
549 $_[0]->{'custom_style'}->{'label'}->{'size'} = $_[1];
550}
551
552=item set_drop_shadow_fill_color
553
554=cut
555
556sub set_drop_shadow_fill_color {
557 $_[0]->{'custom_style'}->{'dropshadow'}->{'fill'} = $_[1];
558}
559
560=item set_drop_shadow_offset
561
562=cut
563
564sub set_drop_shadow_offset {
565 $_[0]->{'custom_style'}->{'dropshadow'}->{'off'} = $_[1];
566}
567
568=item set_drop_shadowXOffset
569
570=cut
571
572sub set_drop_shadowXOffset {
573 $_[0]->{'custom_style'}->{'dropshadow'}->{'offx'} = $_[1];
574}
575
576=item set_drop_shadowYOffset
577
578=cut
579
580sub set_drop_shadowYOffset {
581 $_[0]->{'custom_style'}->{'dropshadow'}->{'offy'} = $_[1];
582}
583
584=item set_drop_shadow_filter
585
586=cut
587
588sub set_drop_shadow_filter {
589 $_[0]->{'custom_style'}->{'dropshadow'}->{'filter'} = $_[1];
590}
591
592=item set_outline_color
593
594=cut
595
596sub set_outline_color {
597 $_[0]->{'custom_style'}->{'outline'}->{'line'} = $_[1];
598}
599
600=item set_data_area_fills
601
602=cut
603
604sub set_data_area_fills {
605 $_[0]->{'custom_style'}->{'fills'} = $_[1];
606}
607
608=item set_data_line_colors
609
610=cut
611
612sub set_data_line_colors {
613 $_[0]->{'custom_style'}->{'colors'} = $_[1];
614}
615
616=back
617
35574351
TC
618=head1 FEATURES
619
620Each graph type has a number of features. These are used to add
621various items that are displayed in the graph area. Some common
2eac77fc 622methods are:
623
624=over
625
626=item show_legend()
627
628adds a box containing boxes filled with the data filess, with
629the labels provided to the draw method. The legend will only be
630displayed if both the legend feature is enabled and labels are
631supplied.
632
633=cut
634
635sub show_legend {
636 $_[0]->{'custom_style'}->{'features'}->{'legend'} = 1;
637}
638
639=item show_outline()
640
641draws a border around the data areas.
642
643=cut
644
645sub show_outline {
646 $_[0]->{'custom_style'}->{'features'}->{'outline'} = 1;
647}
648
649=item show_labels()
650
651labels each data fill, usually by including text inside the data fill.
652If the text does not fit in the fill, they could be displayed in some
653other form, eg. as callouts in a pie graph. There usually isn't much
654point in including both labels and a legend.
655
656=cut
657
658sub show_labels {
659 $_[0]->{'custom_style'}->{'features'}->{'labels'} = 1;
660}
661
662=item show_drop_shadow()
663
664a simple drop shadow is shown behind some of the graph elements.
665
666=cut
667
668sub show_drop_shadow {
669 $_[0]->{'custom_style'}->{'features'}->{'dropshadow'} = 1;
670}
671
672=item reset_features()
673
674Unsets all of the features
675
676=cut
677
678sub reset_features {
679 $_[0]->{'custom_style'}->{'features'} = {};
680 $_[0]->{'custom_style'}->{'features'}->{'reset'} = 1;
681}
682
683=back
684
685Additionally, features can be set by passing them into the draw() method:
35574351
TC
686
687=over
688
689=item legend
690
691adds a box containing boxes filled with the data filess, with
692the labels provided to the draw method. The legend will only be
693displayed if both the legend feature is enabled and labels are
694supplied.
695
696=item labels
697
698labels each data fill, usually by including text inside the data fill.
699If the text does not fit in the fill, they could be displayed in some
700other form, eg. as callouts in a pie graph. There usually isn't much
701point in including both labels and a legend.
702
703=item dropshadow
704
705a simple drop shadow is shown behind some of the graph elements.
706
707=back
708
709Each graph also has features specific to that graph.
710
711=head1 COMMON PARAMETERS
712
713When referring to a single sub-value this documentation will refer to
714'title.color' rather than 'the color element of title'.
715
716Normally, except for the font parameter, these are controlled by
717styles, but these are the style parameters I'd mostly likely expect
718you want to use:
719
720=over
721
722=item font
723
724the Imager font object used to draw text on the chart.
725
726=item back
727
728the background fill for the graph. Default depends on the style.
729
730=item size
731
732the base size of the graph image. Default: 256
733
734=item width
735
736the width of the graph image. Default: 1.5 * size (384)
737
738=item height
739
740the height of the graph image. Default: size (256)
741
742=item channels
743
744the number of channels in the image. Default: 3 (the 'mono' style
745sets this to 1).
746
747=item line
748
749the color used for drawing lines, such as outlines or callouts.
750Default depends on the current style. Set to undef to remove the
751outline from a style.
752
753=item title
754
755the text used for a graph title. Default: no title. Note: this is
756the same as the title=>{ text => ... } field.
757
758=over
759
760=item halign
761
762horizontal alignment of the title in the graph, one of 'left',
763'center' or 'right'. Default: center
764
765=item valign
766
767vertical alignment of the title, one of 'top', 'center' or 'right'.
768Default: top. It's probably a bad idea to set this to 'center' unless
769you have a very short title.
770
771=back
772
773=item text
774
775This contains basic defaults used in drawing text.
776
777=over
778
779=item color
780
781the default color used for all text, defaults to the fg color.
782
783=item size
784
785the base size used for text, also used to scale many graph elements.
786Default: 14.
787
788=back
789
790=back
791
792=head1 BEYOND STYLES
793
794In most cases you will want to use just the styles, but you may want
795to exert more control over the way your chart looks. This section
796describes the options you can use to control the way your chart looks.
797
798Hopefully you don't need to read this.
799
800=over
801
802=item back
803
804The background of the graph.
805
806=item bg
807
808=item fg
809
810Used to define basic background and foreground colors for the graph.
811The bg color may be used for the background of the graph, and is used
812as a default for the background of hatcheed fills. The fg is used as
813the default for line and text colors.
814
815=item font
816
817The default font used by the graph. Normally you should supply this
818if your graph as any text.
819
820=item line
821
822The default line color.
823
824=item text
825
826defaults for drawing text. Other textual graph elements will inherit
827or modify these values.
828
829=over
830
831=item color
832
833default text color, defaults to the I<fg> color.
834
835=item size
836
837default text size. Default: 14. This is used to scale many graph
838elements, including padding and leader sizes. Other text elements
839will either use or scale this value.
840
841=item font
842
843default font object. Inherited from I<font>, which should have been
844supplied by the caller.
845
846=back
847
848=item title
849
850If you supply a scalar value for this element, it will be stored in
851the I<text> field.
852
853Defines the text, font and layout information for the title.
854
855=over
856
857=item color
858
859The color of the title, inherited from I<text.color>.
860
861=item font
862
863The font object used for the title, inherited from I<text.font>.
864
865=item size
866
867size of the title text. Default: double I<text.size>
868
869=item halign
870
871=item valign
872
873The horizontal and vertical alignment of the title.
874
875=back
876
877=item legend
878
879defines attributes of the graph legend, if present.
880
881=over
882
883=item color
884
885=item font
886
887=item size
888
889text attributes for the labels used in the legend.
890
891=item patchsize
892
893the width and height of the color patch in the legend. Defaults to
89490% of the legend text size.
895
896=item patchgap
897
898the minimum gap between patches in pixels. Defaults to 30% of the
899patchsize.
900
901=item patchborder
902
903the color of the border drawn around each patch. Inherited from I<line>.
904
905=item halign
906
907=item valign
908
909the horizontal and vertical alignment of the legend within the graph.
910Defaults to 'right' and 'top'.
911
912=item padding
913
914the gap between the legend patches and text and the outside of it's
915box, or to the legend border, if any.
916
917=item outsidepadding
918
919the gap between the border and the outside of the legend's box. This
920is only used if the I<legend.border> attribute is defined.
921
922=item fill
923
924the background fill for the legend. Default: none
925
926=item border
927
928the border color of the legend. Default: none (no border is drawn
929around the legend.)
930
33a928b7
TC
931=item orientation
932
933The orientation of the legend. If this is C<vertical> the the patches
934and labels are stacked on top of each other. If this is C<horizontal>
935the patchs and labels are word wrapped across the image. Default:
936vertical.
937
35574351
TC
938=back
939
33a928b7
TC
940For example to create a horizontal legend with borderless patches,
941darker than the background, you might do:
942
943 my $im = $chart->draw
944 (...,
945 legend =>
946 {
947 patchborder => undef,
948 orientation => 'horizontal',
949 fill => { solid => Imager::Color->new(0, 0, 0, 32), }
950 },
951 ...);
952
35574351
TC
953=item callout
954
955defines attributes for graph callouts, if any are present. eg. if the
956pie graph cannot fit the label into the pie graph segement it will
957present it as a callout.
958
959=over
960
961=item color
962
963=item font
964
965=item size
966
967the text attributes of the callout label. Inherited from I<text>.
968
969=item line
970
971the color of the callout lines. Inherited from I<line>
972
973=item inside
974
975=item outside
976
977the length of the leader on the inside and the outside of the fill,
978usually at some angle. Both default to the size of the callout text.
979
980=item leadlen
981
982the length of the horizontal portion of the leader. Default:
983I<callout.size>.
984
985=item gap
986
987the gap between the callout leader and the callout text. Defaults to
98830% of the text callout size.
989
990=back
991
992=item label
993
994defines attributes for labels drawn into the data areas of a graph.
995
996=over
997
998=item color
999
1000=item font
1001
1002=item size
1003
1004The text attributes of the labels. Inherited from I<text>.
1005
1006=back
1007
1008=item dropshadow
1009
1010the attributes of the graph's drop shadow
1011
1012=over
1013
1014=item fill
1015
1016the fill used for the drop shadow. Default: '404040' (dark gray)
1017
1018=item off
1019
1020the offset of the drop shadow. A convenience value inherited by offx
1021and offy. Default: 40% of I<text.size>.
1022
1023=item offx
1024
1025=item offy
1026
1027the horizontal and vertical offsets of the drop shadow. Both
1028inherited from I<dropshadow.off>.
1029
1030=item filter
1031
1032the filter description passed to Imager's filter method to blur the
1033drop shadow. Default: an 11 element convolution filter.
1034
1035=back
1036
1037=item outline
1038
1039describes the lines drawn around filled data areas, such as the
1040segments of a pie chart.
1041
1042=over
1043
1044=item line
1045
1046the line color of the outlines, inherited from I<line>.
1047
1048=back
1049
1050=item fills
1051
1052a reference to an array containing fills for each data item.
1053
1054You can mix fill types, ie. using a simple color for the first item, a
1055hatched fill for the second and a fountain fill for the next.
1056
1057=back
1058
1059=head1 HOW VALUES WORK
1060
1061Internally rather than specifying literal color, fill, or font objects
1062or literal sizes for each element, Imager::Graph uses a number of
1063special values to inherit or modify values taken from other graph
1064element names.
1065
1066=head2 Specifying colors
1067
1068You can specify colors by either supplying an Imager::Color object, by
1069supplying lookup of another color, or by supplying a single value that
1070Imager::Color::new can use as an initializer. The most obvious is
1071just a 6 or 8 digit hex value representing the red, green, blue and
1072optionally alpha channels of the image.
1073
1074You can lookup another color by using the lookup() "function", for
1075example if you give a color as "lookup(fg)" then Imager::Graph will
1076look for the fg element in the current style (or as overridden by
1077you.) This is used internally by Imager::Graph to set up the
1078relationships between the colors of various elements, for example the
1079default style information contains:
1080
1081 text=>{
d7fd5863 1082 color=>'lookup(fg)',
35574351
TC
1083 ...
1084 },
1085 legend =>{
d7fd5863 1086 color=>'lookup(text.color)',
35574351
TC
1087 ...
1088 },
1089
1090So by setting the I<fg> color, you also set the default text color,
1091since each text element uses lookup(text.color) as its value.
1092
1093=head2 Specifying fills
1094
1095Fills can be used for the graph background color, the background color
1096for the legend block and for the fills used for each data element.
1097
1098You can specify a fill as a L<color value|Specifying colors> or as a
33a928b7 1099general fill, see L<Imager::Fill> for details.
35574351
TC
1100
1101You don't need (or usually want) to call Imager::Fill::new yourself,
1102since the various fill functions will call it for you, and
1103Imager::Graph provides some hooks to make them more useful.
1104
1105=over
1106
1107=item *
1108
1109with hatched fills, if you don't supply a 'fg' or 'bg' parameter,
1110Imager::Graph will supply the current graph fg and bg colors.
1111
1112=item *
1113
1114with fountain fill, you can supply the xa_ratio, ya_ratio, xb_ratio
1115and yb_ratio parameters, and they will be scaled in the fill area to
1116define the fountain fills xa, ya, xb and yb parameters.
1117
1118=back
1119
1120As with colors, you can use lookup(name) or lookup(name1.name2) to
1121have one element to inherit the fill of another.
1122
33a928b7
TC
1123Imager::Graph defaults the fill combine value to C<'normal'>. This
1124doesn't apply to simple color fills.
1125
35574351
TC
1126=head2 Specifying numbers
1127
1128You can specify various numbers, usually representing the size of
1129something, commonly text, but sometimes the length of a line or the
1130size of a gap.
1131
1132You can use the same lookup mechanism as with colors and fills, but
1133you can also scale values. For example, 'scale(0.5,text.size)' will
1134return half the size of the normal text size.
1135
1136As with colors, this is used internally to scale graph elements based
1137on the base text size. If you change the base text size then other
1138graph elements will scale as well.
1139
1140=head2 Specifying other elements
1141
1142Other elements, such as fonts, or parameters for a filter, can also
1143use the lookup(name) mechanism.
1144
1145=head1 INTERNAL METHODS
1146
1147Only useful if you need to fix bugs, add features or create a new
1148graph class.
1149
1150=over
1151
1152=cut
1153
1154my %style_defs =
1155 (
1156 back=> 'lookup(bg)',
1157 line=> 'lookup(fg)',
49a35584 1158 aa => 1,
35574351 1159 text=>{
d7fd5863 1160 color => 'lookup(fg)',
35574351 1161 font => 'lookup(font)',
d7fd5863 1162 size => 14,
49a35584 1163 aa => 'lookup(aa)',
d7fd5863 1164 },
35574351 1165 title=>{
d7fd5863 1166 color => 'lookup(text.color)',
35574351 1167 font => 'lookup(text.font)',
d7fd5863
TC
1168 halign => 'center',
1169 valign => 'top',
1170 size => 'scale(text.size,2.0)',
49a35584 1171 aa => 'lookup(text.aa)',
d7fd5863 1172 },
35574351 1173 legend =>{
d7fd5863 1174 color => 'lookup(text.color)',
35574351 1175 font => 'lookup(text.font)',
49a35584 1176 aa => 'lookup(text.aa)',
d7fd5863
TC
1177 size => 'lookup(text.size)',
1178 patchsize => 'scale(legend.size,0.9)',
1179 patchgap => 'scale(legend.patchsize,0.3)',
1180 patchborder => 'lookup(line)',
1181 halign => 'right',
1182 valign => 'top',
1183 padding => 'scale(legend.size,0.3)',
1184 outsidepadding => 'scale(legend.padding,0.4)',
1185 },
35574351 1186 callout => {
d7fd5863 1187 color => 'lookup(text.color)',
35574351 1188 font => 'lookup(text.font)',
d7fd5863
TC
1189 size => 'lookup(text.size)',
1190 line => 'lookup(line)',
1191 inside => 'lookup(callout.size)',
1192 outside => 'lookup(callout.size)',
1193 leadlen => 'scale(0.8,callout.size)',
1194 gap => 'scale(callout.size,0.3)',
49a35584
TC
1195 aa => 'lookup(text.aa)',
1196 lineaa => 'lookup(lineaa)',
d7fd5863 1197 },
35574351
TC
1198 label => {
1199 font => 'lookup(text.font)',
d7fd5863
TC
1200 size => 'lookup(text.size)',
1201 color => 'lookup(text.color)',
35574351
TC
1202 hpad => 'lookup(label.pad)',
1203 vpad => 'lookup(label.pad)',
1204 pad => 'scale(label.size,0.2)',
1205 pcformat => sub { sprintf "%s (%.0f%%)", $_[0], $_[1] },
1206 pconlyformat => sub { sprintf "%.1f%%", $_[0] },
49a35584
TC
1207 aa => 'lookup(text.aa)',
1208 lineaa => 'lookup(lineaa)',
d7fd5863 1209 },
35574351 1210 dropshadow => {
320f5a49 1211 fill => { solid => Imager::Color->new(0, 0, 0, 96) },
35574351
TC
1212 off => 'scale(0.4,text.size)',
1213 offx => 'lookup(dropshadow.off)',
1214 offy => 'lookup(dropshadow.off)',
1215 filter => { type=>'conv',
1216 # this needs a fairly heavy blur
1217 coef=>[0.1, 0.2, 0.4, 0.6, 0.7, 0.9, 1.2,
1218 0.9, 0.7, 0.6, 0.4, 0.2, 0.1 ] },
1219 },
1a36ef75
TC
1220 # controls the outline of graph elements representing data, eg. pie
1221 # slices, bars or columns
35574351
TC
1222 outline => {
1223 line =>'lookup(line)',
49a35584 1224 lineaa => 'lookup(lineaa)',
35574351 1225 },
1a36ef75
TC
1226 # controls the outline and background of the data area of the chart
1227 graph =>
1228 {
1229 fill => "lookup(bg)",
1230 outline => "lookup(fg)",
1231 },
35574351
TC
1232 size=>256,
1233 width=>'scale(1.5,size)',
1234 height=>'lookup(size)',
49a35584
TC
1235
1236 # yes, the handling of fill and line AA is inconsistent, lack of
1237 # forethought, unfortunately
1238 fill => {
1239 aa => 'lookup(aa)',
1240 },
1241 lineaa => 'lookup(aa)',
35574351
TC
1242 );
1243
1244=item _error($message)
1245
1246Sets the error field of the object and returns an empty list or undef,
1247depending on context. Should be used for error handling, since it may
1248provide some user hooks at some point.
1249
f68db40f
TC
1250The intended usage is:
1251
1252 some action
1253 or return $self->_error("error description");
1254
1255You should almost always return the result of _error() or return
1256immediately afterwards.
1257
35574351
TC
1258=cut
1259
1260sub _error {
1261 my ($self, $error) = @_;
1262
1263 $self->{_errstr} = $error;
1264
1265 return;
1266}
1267
1268
1269=item _style_defs()
1270
1271Returns the style defaults, such as the relationships between line
1272color and text color.
1273
1274Intended to be over-ridden by base classes to provide graph specific
1275defaults.
1276
1277=cut
1278
1279sub _style_defs {
1280 \%style_defs;
1281}
1282
81453d28 1283# Let's make the default something that looks really good, so folks will be interested enough to customize the style.
1284my $def_style = 'fount_lin';
35574351
TC
1285
1286my %styles =
1287 (
7b94e723
TC
1288 primary =>
1289 {
1290 fills=>
1291 [
1292 qw(FF0000 00FF00 0000FF C0C000 00C0C0 FF00FF)
1293 ],
1294 fg=>'000000',
2eac77fc 1295 negative_bg=>'EEEEEE',
7b94e723
TC
1296 bg=>'E0E0E0',
1297 legend=>
1298 {
1299 #patchborder=>'000000'
1300 },
1301 },
35574351
TC
1302 primary_red =>
1303 {
1304 fills=>
1305 [
1306 qw(FF0000 00FF00 0000FF C0C000 00C0C0 FF00FF)
1307 ],
1308 fg=>'000000',
2eac77fc 1309 negative_bg=>'EEEEEE',
35574351
TC
1310 bg=>'C08080',
1311 legend=>
1312 {
1313 patchborder=>'000000'
1314 },
1315 },
1316 mono =>
1317 {
1318 fills=>
1319 [
1320 { hatch=>'slash2' },
1321 { hatch=>'slosh2' },
1322 { hatch=>'vline2' },
1323 { hatch=>'hline2' },
1324 { hatch=>'cross2' },
1325 { hatch=>'grid2' },
1326 { hatch=>'stipple3' },
1327 { hatch=>'stipple2' },
1328 ],
1329 channels=>1,
1330 bg=>'FFFFFF',
1331 fg=>'000000',
2eac77fc 1332 negative_bg=>'EEEEEE',
35574351
TC
1333 features=>{ outline=>1 },
1334 pie =>{
1335 blur=>undef,
1336 },
49a35584 1337 aa => 0,
35574351 1338 },
bb0de914 1339 fount_lin =>
35574351
TC
1340 {
1341 fills=>
1342 [
1343 { fountain=>'linear',
1344 xa_ratio=>0.13, ya_ratio=>0.13, xb_ratio=>0.87, yb_ratio=>0.87,
35574351 1345 segments => Imager::Fountain->simple(positions=>[0, 1],
d7fd5863 1346 colors=>[ NC('FFC0C0'), NC('FF0000') ]),
35574351
TC
1347 },
1348 { fountain=>'linear',
1349 xa_ratio=>0, ya_ratio=>0, xb_ratio=>1.0, yb_ratio=>1.0,
1350 segments => Imager::Fountain->simple(positions=>[0, 1],
d7fd5863 1351 colors=>[ NC('C0FFC0'), NC('00FF00') ]),
35574351
TC
1352 },
1353 { fountain=>'linear',
1354 xa_ratio=>0, ya_ratio=>0, xb_ratio=>1.0, yb_ratio=>1.0,
1355 segments => Imager::Fountain->simple(positions=>[0, 1],
d7fd5863 1356 colors=>[ NC('C0C0FF'), NC('0000FF') ]),
35574351
TC
1357 },
1358 { fountain=>'linear',
1359 xa_ratio=>0, ya_ratio=>0, xb_ratio=>1.0, yb_ratio=>1.0,
1360 segments => Imager::Fountain->simple(positions=>[0, 1],
d7fd5863 1361 colors=>[ NC('FFFFC0'), NC('FFFF00') ]),
35574351
TC
1362 },
1363 { fountain=>'linear',
1364 xa_ratio=>0, ya_ratio=>0, xb_ratio=>1.0, yb_ratio=>1.0,
1365 segments => Imager::Fountain->simple(positions=>[0, 1],
d7fd5863 1366 colors=>[ NC('C0FFFF'), NC('00FFFF') ]),
35574351
TC
1367 },
1368 { fountain=>'linear',
1369 xa_ratio=>0, ya_ratio=>0, xb_ratio=>1.0, yb_ratio=>1.0,
1370 segments => Imager::Fountain->simple(positions=>[0, 1],
d7fd5863 1371 colors=>[ NC('FFC0FF'), NC('FF00FF') ]),
35574351
TC
1372 },
1373 ],
dfd889da 1374 colors => [
1375 qw(FF0000 00FF00 0000FF C0C000 00C0C0 FF00FF)
1376 ],
8e140388
TC
1377 line_markers =>[
1378 { shape => 'circle', radius => 4 },
1379 { shape => 'square', radius => 4 },
1380 { shape => 'diamond', radius => 4 },
1381 { shape => 'triangle', radius => 4 },
1382 { shape => 'x', radius => 4 },
1383 { shape => 'plus', radius => 4 },
1384 ],
35574351
TC
1385 back=>{ fountain=>'linear',
1386 xa_ratio=>0, ya_ratio=>0,
1387 xb_ratio=>1.0, yb_ratio=>1.0,
1388 segments=>Imager::Fountain->simple
1389 ( positions=>[0, 1],
1390 colors=>[ NC('6060FF'), NC('60FF60') ]) },
1391 fg=>'000000',
2eac77fc 1392 negative_bg=>'EEEEEE',
35574351
TC
1393 bg=>'FFFFFF',
1394 features=>{ dropshadow=>1 },
bb0de914
TC
1395 },
1396 fount_rad =>
1397 {
35574351
TC
1398 fills=>
1399 [
1400 { fountain=>'radial',
1401 xa_ratio=>0.5, ya_ratio=>0.5, xb_ratio=>1.0, yb_ratio=>0.5,
1402 segments => Imager::Fountain->simple(positions=>[0, 1],
d7fd5863 1403 colors=>[ NC('FF8080'), NC('FF0000') ]),
35574351
TC
1404 },
1405 { fountain=>'radial',
1406 xa_ratio=>0.5, ya_ratio=>0.5, xb_ratio=>1.0, yb_ratio=>0.5,
1407 segments => Imager::Fountain->simple(positions=>[0, 1],
d7fd5863 1408 colors=>[ NC('80FF80'), NC('00FF00') ]),
35574351
TC
1409 },
1410 { fountain=>'radial',
1411 xa_ratio=>0.5, ya_ratio=>0.5, xb_ratio=>1.0, yb_ratio=>0.5,
1412 segments => Imager::Fountain->simple(positions=>[0, 1],
d7fd5863 1413 colors=>[ NC('808080FF'), NC('0000FF') ]),
35574351
TC
1414 },
1415 { fountain=>'radial',
1416 xa_ratio=>0.5, ya_ratio=>0.5, xb_ratio=>1.0, yb_ratio=>0.5,
1417 segments => Imager::Fountain->simple(positions=>[0, 1],
d7fd5863 1418 colors=>[ NC('FFFF80'), NC('FFFF00') ]),
35574351
TC
1419 },
1420 { fountain=>'radial',
1421 xa_ratio=>0.5, ya_ratio=>0.5, xb_ratio=>1.0, yb_ratio=>0.5,
1422 segments => Imager::Fountain->simple(positions=>[0, 1],
d7fd5863 1423 colors=>[ NC('80FFFF'), NC('00FFFF') ]),
35574351
TC
1424 },
1425 { fountain=>'radial',
1426 xa_ratio=>0.5, ya_ratio=>0.5, xb_ratio=>1.0, yb_ratio=>0.5,
1427 segments => Imager::Fountain->simple(positions=>[0, 1],
d7fd5863 1428 colors=>[ NC('FF80FF'), NC('FF00FF') ]),
35574351
TC
1429 },
1430 ],
dfd889da 1431 colors => [
1432 qw(FF0000 00FF00 0000FF C0C000 00C0C0 FF00FF)
1433 ],
35574351
TC
1434 back=>{ fountain=>'linear',
1435 xa_ratio=>0, ya_ratio=>0,
1436 xb_ratio=>1.0, yb_ratio=>1.0,
1437 segments=>Imager::Fountain->simple
1438 ( positions=>[0, 1],
1439 colors=>[ NC('6060FF'), NC('60FF60') ]) },
1440 fg=>'000000',
2eac77fc 1441 negative_bg=>'EEEEEE',
35574351 1442 bg=>'FFFFFF',
bb0de914
TC
1443 }
1444 );
35574351 1445
2eac77fc 1446$styles{'ocean'} = {
1447 fills => [
1448 {
1449 fountain =>'linear',
1450 xa_ratio => 0, ya_ratio=>0, xb_ratio=>1.0, yb_ratio=>1.0,
1451 segments => Imager::Fountain->simple(
1452 positions=>[0, 1],
7422650e 1453 colors=>[ NC('EFEDCF'), NC('E6E2AF') ]),
2eac77fc 1454 },
1455 {
1456 fountain =>'linear',
1457 xa_ratio => 0, ya_ratio=>0, xb_ratio=>1.0, yb_ratio=>1.0,
1458 segments => Imager::Fountain->simple(
1459 positions=>[0, 1],
7422650e 1460 colors=>[ NC('DCD7AB'), NC('A7A37E') ]),
2eac77fc 1461 },
1462 {
1463 fountain =>'linear',
1464 xa_ratio => 0, ya_ratio=>0, xb_ratio=>1.0, yb_ratio=>1.0,
1465 segments => Imager::Fountain->simple(
1466 positions=>[0, 1],
7422650e 1467 colors=>[ NC('B2E5D4'), NC('80B4A2') ]),
2eac77fc 1468 },
1469 {
1470 fountain =>'linear',
1471 xa_ratio => 0, ya_ratio=>0, xb_ratio=>1.0, yb_ratio=>1.0,
1472 segments => Imager::Fountain->simple(
1473 positions=>[0, 1],
7422650e 1474 colors=>[ NC('7aaab9'), NC('046380') ]),
2eac77fc 1475 },
1476 {
1477 fountain =>'linear',
1478 xa_ratio => 0, ya_ratio=>0, xb_ratio=>1.0, yb_ratio=>1.0,
1479 segments => Imager::Fountain->simple(
1480 positions=>[0, 1],
7422650e 1481 colors=>[ NC('c3b8e9'), NC('877EA7') ]),
2eac77fc 1482 },
1483 {
1484 fountain =>'linear',
1485 xa_ratio => 0, ya_ratio=>0, xb_ratio=>1.0, yb_ratio=>1.0,
1486 segments => Imager::Fountain->simple(
1487 positions=>[0, 1],
7422650e 1488 colors=>[ NC('A3DF9A'), NC('67A35E') ]),
2eac77fc 1489 },
1490 {
1491 fountain =>'linear',
1492 xa_ratio => 0, ya_ratio=>0, xb_ratio=>1.0, yb_ratio=>1.0,
1493 segments => Imager::Fountain->simple(
1494 positions=>[0, 1],
7422650e 1495 colors=>[ NC('E19C98'), NC('B4726F') ]),
2eac77fc 1496 },
1497 ],
1498 colors => [
1499 qw(E6E2AF A7A37E 80B4A2 046380 877EA7 67A35E B4726F)
1500 ],
1501 fg=>'000000',
1502 negative_bg=>'EEEEEE',
1503 bg=>'FFFFFF',
1504 features=>{ dropshadow=>1 },
1505
1506};
1507
7422650e 1508$styles{'ocean_flat'} = {
1509 fills=>
1510 [
1511 qw(E6E2AF A7A37E 80B4A2 046380 877EA7 67A35E B4726F)
1512 ],
1513 colors => [
1514 qw(E6E2AF A7A37E 80B4A2 046380 877EA7 67A35E B4726F)
1515 ],
1516 fg=>'000000',
1517 negative_bg=>'EEEEEE',
1518 bg=>'FFFFFF',
1519 features=>{ dropshadow=>1 },
1520
1521};
1522
1523
35574351
TC
1524=item $self->_style_setup(\%opts)
1525
1526Uses the values from %opts to build a customized hash describing the
1527way the graph should be drawn.
1528
1529=cut
1530
1531sub _style_setup {
1532 my ($self, $opts) = @_;
1533 my $style_defs = $self->_style_defs;
1534 my $style;
dfd889da 1535
2eac77fc 1536 my $pre_def_style = $self->_get_style($opts);
1537 my $api_style = $self->{'custom_style'} || {};
dfd889da 1538 $style = $styles{$pre_def_style} if $pre_def_style;
1539
35574351
TC
1540 $style ||= $styles{$def_style};
1541
2eac77fc 1542 my @search_list = ( $style_defs, $style, $api_style, $opts);
35574351
TC
1543 my %work;
1544
1545 my @composite = $self->_composite();
1546 my %composite;
1547 @composite{@composite} = @composite;
1548
1549 for my $src (@search_list) {
1550 for my $key (keys %$src) {
1551 if ($composite{$key}) {
1552 $work{$key} = {} unless exists $work{$key};
1553 if (ref $src->{$key}) {
1554 # some keys have sub values, especially text
1555 @{$work{$key}}{keys %{$src->{$key}}} = values %{$src->{$key}};
1556 }
1557 else {
1558 # assume it's the text for a title or something
1559 $work{$key}{text} = $src->{$key};
1560 }
1561 }
1562 else {
a17e870a
TC
1563 $work{$key} = $src->{$key}
1564 if defined $src->{$key}; # $opts with pmichauds new accessor handling
35574351
TC
1565 }
1566 }
1567 }
1568
1569 # features are handled specially
1a36ef75
TC
1570 my %features;
1571 $work{features} = \%features;
35574351
TC
1572 for my $src (@search_list) {
1573 if ($src->{features}) {
1574 if (ref $src->{features}) {
1575 if (ref($src->{features}) =~ /ARRAY/) {
1576 # just set those features
1577 for my $feature (@{$src->{features}}) {
1a36ef75
TC
1578 if ($feature =~ /^no(.+)$/) {
1579 delete $features{$1};
1580 }
1581 else {
1582 $features{$feature} = 1;
1583 }
35574351
TC
1584 }
1585 }
1586 elsif (ref($src->{features}) =~ /HASH/) {
1587 if ($src->{features}{reset}) {
1588 $work{features} = {}; # only the ones the user specifies
1589 }
1590 @{$work{features}}{keys %{$src->{features}}} =
1591 values(%{$src->{features}});
1592 }
1593 }
1594 else {
1595 # just set that single feature
1596 $work{features}{$src->{features}} = 1;
1597 }
1598 }
1599 }
35574351
TC
1600
1601 $self->{_style} = \%work;
1602}
1603
1604=item $self->_get_thing($name)
1605
1606Retrieve some general 'thing'.
1607
1608Supports the 'lookup(foo)' mechanism.
1609
f68db40f
TC
1610Returns an empty list on failure.
1611
35574351
TC
1612=cut
1613
1614sub _get_thing {
1615 my ($self, $name, @depth) = @_;
1616
1617 push(@depth, $name);
1618 my $what;
1619 if ($name =~ /^(\w+)\.(\w+)$/) {
1620 $what = $self->{_style}{$1}{$2};
1621 }
1622 else {
1623 $what = $self->{_style}{$name};
1624 }
1625 defined $what or
1626 return;
1627 if (ref $what) {
1628 return $what;
1629 }
1630 elsif ($what =~ /^lookup\((\w+(?:\.\w+)?)\)$/) {
1631 @depth < MAX_DEPTH
1632 or return $self->_error("too many levels of recursion in lookup(@depth)");
1633 return $self->_get_thing($1, @depth);
1634 }
1635 else {
1636 return $what;
1637 }
1638}
1639
1640=item $self->_get_number($name)
1641
1642Retrieves a number from the style. The value in the style can be the
1643number, or one of two functions:
1644
1645=over
1646
1647=item lookup(newname)
1648
1649Recursively looks up I<newname> in the style.
1650
1651=item scale(value1,value2)
1652
33a928b7 1653Each value can be a number or a name. Names are recursively looked up
35574351
TC
1654in the style and the product is returned.
1655
1656=back
1657
1658=cut
bb0de914 1659
35574351
TC
1660sub _get_number {
1661 my ($self, $name, @depth) = @_;
1662
1663 push(@depth, $name);
1664 my $what;
1665 if ($name =~ /^(\w+)\.(\w+)$/) {
1666 $what = $self->{_style}{$1}{$2};
1667 }
1668 else {
1669 $what = $self->{_style}{$name};
1670 }
1671 defined $what or
1672 return $self->_error("$name is undef (@depth)");
1673
1674 if (ref $what) {
1675 if ($what =~ /CODE/) {
1676 $what = $what->($self, $name);
1677 }
1678 }
1679 else {
1680 if ($what =~ /^lookup\(([\w.]+)\)$/) {
1681 @depth < MAX_DEPTH
d7fd5863 1682 or return $self->_error("too many levels of recursion in lookup (@depth)");
35574351
TC
1683 return $self->_get_number($1, @depth);
1684 }
1685 elsif ($what =~ /^scale\(
d7fd5863 1686 ((?:[a-z][\w.]*)|$NUM_RE)
35574351 1687 ,
d7fd5863 1688 ((?:[a-z][\w.]*)|$NUM_RE)\)$/x) {
35574351
TC
1689 my ($left, $right) = ($1, $2);
1690 unless ($left =~ /^$NUM_RE$/) {
d7fd5863
TC
1691 @depth < MAX_DEPTH
1692 or return $self->_error("too many levels of recursion in scale (@depth)");
1693 $left = $self->_get_number($left, @depth);
35574351
TC
1694 }
1695 unless ($right =~ /^$NUM_RE$/) {
d7fd5863
TC
1696 @depth < MAX_DEPTH
1697 or return $self->_error("too many levels of recursion in scale (@depth)");
1698 $right = $self->_get_number($right, @depth);
35574351
TC
1699 }
1700 return $left * $right;
1701 }
1702 else {
1703 return $what+0;
1704 }
1705 }
1706}
1707
379c5b02
TC
1708=item $self->_get_integer($name)
1709
1710Retrieves an integer from the style. This is a simple wrapper around
1711_get_number() that rounds the result to an integer.
1712
f68db40f
TC
1713Returns an empty list on failure.
1714
379c5b02
TC
1715=cut
1716
1717sub _get_integer {
1718 my ($self, $name, @depth) = @_;
1719
1720 my $number = $self->_get_number($name, @depth)
1721 or return;
1722
1723 return sprintf("%.0f", $number);
1724}
1725
35574351
TC
1726=item _get_color($name)
1727
1728Returns a color object of the given name from the style hash.
1729
1730Uses Imager::Color->new to translate normal scalars into color objects.
1731
1732Allows the lookup(name) mechanism.
1733
f68db40f
TC
1734Returns an empty list on failure.
1735
35574351
TC
1736=cut
1737
1738sub _get_color {
1739 my ($self, $name, @depth) = @_;
1740
1741 push(@depth, $name);
1742 my $what;
1743 if ($name =~ /^(\w+)\.(\w+)$/) {
1744 $what = $self->{_style}{$1}{$2};
1745 }
1746 else {
1747 $what = $self->{_style}{$name};
1748 }
1749
1750 defined($what)
1751 or return $self->_error("$name was undefined (@depth)");
1752
1753 unless (ref $what) {
1754 if ($what =~ /^lookup\((\w+(?:\.\w+)?)\)$/) {
1755 @depth < MAX_DEPTH or
d7fd5863 1756 return $self->_error("too many levels of recursion in lookup (@depth)");
35574351
TC
1757
1758 return $self->_get_color($1, @depth);
1759 }
1760 $what = Imager::Color->new($what);
1761 }
1762
1763 $what;
1764}
1765
1766=item _translate_fill($what, $box)
1767
1768Given the value of a fill, either attempts to convert it into a fill
1769list (one of C<<color=>$color_value, filled=>1>> or C<<fill=>{ fill
1770parameters }>>), or to lookup another fill that is referred to with
1771the 'lookup(name)' mechanism.
1772
1773This function does the fg and bg initialization for hatched fills, and
1774translation of *_ratio for fountain fills (using the $box parameter).
1775
f68db40f
TC
1776Returns an empty list on failure.
1777
35574351
TC
1778=cut
1779
1780sub _translate_fill {
1781 my ($self, $what, $box, @depth) = @_;
1782
1783 if (ref $what) {
1784 if (UNIVERSAL::isa($what, "Imager::Color")) {
1785 return ( color=>Imager::Color->new($what), filled=>1 );
1786 }
1787 else {
1788 # a general fill
33a928b7
TC
1789 # default to normal combine mode
1790 my %work = ( combine => 'normal', %$what );
35574351 1791 if ($what->{hatch}) {
d7fd5863
TC
1792 if (!$work{fg}) {
1793 $work{fg} = $self->_get_color('fg')
1794 or return;
1795 }
1796 if (!$work{bg}) {
1797 $work{bg} = $self->_get_color('bg')
1798 or return;
1799 }
1800 return ( fill=>\%work );
35574351
TC
1801 }
1802 elsif ($what->{fountain}) {
d7fd5863
TC
1803 for my $key (qw(xa ya xb yb)) {
1804 if (exists $work{"${key}_ratio"}) {
1805 if ($key =~ /^x/) {
1806 $work{$key} = $box->[0] + $work{"${key}_ratio"}
1807 * ($box->[2] - $box->[0]);
1808 }
1809 else {
1810 $work{$key} = $box->[1] + $work{"${key}_ratio"}
1811 * ($box->[3] - $box->[1]);
1812 }
1813 }
1814 }
1815 return ( fill=>\%work );
35574351
TC
1816 }
1817 else {
d7fd5863 1818 return ( fill=> \%work );
35574351
TC
1819 }
1820 }
1821 }
1822 else {
1823 if ($what =~ /^lookup\((\w+(?:\.\w+)?)\)$/) {
1824 return $self->_get_fill($1, $box, @depth);
1825 }
1826 else {
1827 # assumed to be an Imager::Color single value
1828 return ( color=>Imager::Color->new($what), filled=>1 );
1829 }
1830 }
1831}
1832
1833=item _data_fill($index, $box)
1834
1835Retrieves the fill parameters for a data area fill.
1836
1837=cut
1838
1839sub _data_fill {
1840 my ($self, $index, $box) = @_;
1841
1842 my $fills = $self->{_style}{fills};
1843 return $self->_translate_fill($fills->[$index % @$fills], $box,
1844 "data.$index");
1845}
1846
dfd889da 1847sub _data_color {
1848 my ($self, $index) = @_;
1849
1850 my $colors = $self->{'_style'}{'colors'} || [];
1851 my $fills = $self->{'_style'}{'fills'} || [];
1852
1853 # Try to just use a fill, so non-fountain styles don't need
1854 # to have a duplicated set of fills and colors
1855 my $fill = $fills->[$index % @$fills];
1856 if (!ref $fill) {
1857 return $fill;
1858 }
1859
1860 if (@$colors) {
1861 return $colors->[$index % @$colors] || '000000';
1862 }
1863 return '000000';
1864}
1865
35574351
TC
1866=item _get_fill($index, $box)
1867
1868Retrieves fill parameters for a named fill.
1869
1870=cut
1871
1872sub _get_fill {
1873 my ($self, $name, $box, @depth) = @_;
1874
1875 push(@depth, $name);
1876 my $what;
1877 if ($name =~ /^(\w+)\.(\w+)$/) {
1878 $what = $self->{_style}{$1}{$2};
1879 }
1880 else {
1881 $what = $self->{_style}{$name};
1882 }
1883
1884 defined($what)
1885 or return $self->_error("no fill $name found");
1886
1887 return $self->_translate_fill($what, $box, @depth);
1888}
1889
1890=item _make_img()
1891
1892Builds the image object for the graph and fills it with the background
1893fill.
1894
1895=cut
1896
1897sub _make_img {
1898 my ($self) = @_;
35574351 1899
81453d28 1900 my $width = $self->_get_number('width') || 256;
1901 my $height = $self->_get_number('height') || 256;
35574351
TC
1902 my $channels = $self->{_style}{channels};
1903
1904 $channels ||= 3;
1905
1906 my $img = Imager->new(xsize=>$width, ysize=>$height, channels=>$channels);
1907
1908 $img->box($self->_get_fill('back', [ 0, 0, $width-1, $height-1]));
1909
1910 $img;
1911}
1912
2eac77fc 1913sub _get_image {
1914 my $self = shift;
1915
1916 if (!$self->{'_image'}) {
1917 $self->{'_image'} = $self->_make_img();
1918 }
1919 return $self->{'_image'};
1920}
1921
f68db40f
TC
1922=item _text_style($name)
1923
1924Returns parameters suitable for calls to Imager::Font's bounding_box()
1925and draw() methods intended for use in defining text styles.
1926
1927Returns an empty list on failure.
1928
49a35584
TC
1929Returns the following attributes: font, color, size, aa, sizew
1930(optionally)
1931
f68db40f
TC
1932=cut
1933
35574351
TC
1934sub _text_style {
1935 my ($self, $name) = @_;
1936
1937 my %work;
1938
1939 if ($self->{_style}{$name}) {
1940 %work = %{$self->{_style}{$name}};
1941 }
1942 else {
1943 %work = %{$self->{_style}{text}};
1944 }
1945 $work{font}
5d622bb8 1946 or return $self->_error("$name has no font parameter");
35574351
TC
1947
1948 $work{font} = $self->_get_thing("$name.font")
5d622bb8 1949 or return $self->_error("No $name.font defined, either set $name.font or font to a font");
35574351
TC
1950 UNIVERSAL::isa($work{font}, "Imager::Font")
1951 or return $self->_error("$name.font is not a font");
1952 if ($work{color} && !ref $work{color}) {
1953 $work{color} = $self->_get_color("$name.color")
1954 or return;
1955 }
1956 $work{size} = $self->_get_number("$name.size");
1957 $work{sizew} = $self->_get_number("$name.sizew")
1958 if $work{sizew};
49a35584 1959 $work{aa} = $self->_get_number("$name.aa");
35574351
TC
1960
1961 %work;
1962}
1963
f68db40f
TC
1964=item _text_bbox($text, $name)
1965
1966Returns a bounding box for the specified $text as styled by $name.
1967
1968Returns an empty list on failure.
1969
1970=cut
1971
35574351
TC
1972sub _text_bbox {
1973 my ($self, $text, $name) = @_;
1974
5d622bb8
TC
1975 my %text_info = $self->_text_style($name)
1976 or return;
35574351
TC
1977
1978 my @bbox = $text_info{font}->bounding_box(%text_info, string=>$text,
d7fd5863 1979 canon=>1);
35574351
TC
1980
1981 return @bbox[0..3];
1982}
1983
49a35584
TC
1984=item _line_style($name)
1985
1986Return parameters suitable for calls to Imager's line(), polyline(),
1987and box() methods.
1988
1989For now this returns only color and aa parameters, but future releases
1990of Imager may support extra parameters.
1991
1992=cut
1993
1994sub _line_style {
1995 my ($self, $name) = @_;
1996
1997 my %line;
1998 $line{color} = $self->_get_color("$name.line")
1999 or return;
2000 $line{aa} = $self->_get_number("$name.lineaa");
2001 defined $line{aa} or $line{aa} = $self->_get_number("aa");
2002
2003 return %line;
2004}
2005
35574351
TC
2006sub _align_box {
2007 my ($self, $box, $chart_box, $name) = @_;
2008
2009 my $halign = $self->{_style}{$name}{halign}
2010 or $self->_error("no halign for $name");
2011 my $valign = $self->{_style}{$name}{valign};
2012
2013 if ($halign eq 'right') {
2014 $box->[0] += $chart_box->[2] - $box->[2];
2015 }
2016 elsif ($halign eq 'left') {
2017 $box->[0] = $chart_box->[0];
2018 }
2019 elsif ($halign eq 'center' || $halign eq 'centre') {
2020 $box->[0] = ($chart_box->[0] + $chart_box->[2] - $box->[2])/2;
2021 }
2022 else {
2023 return $self->_error("invalid halign $halign for $name");
2024 }
2025
2026 if ($valign eq 'top') {
2027 $box->[1] = $chart_box->[1];
2028 }
2029 elsif ($valign eq 'bottom') {
2030 $box->[1] = $chart_box->[3] - $box->[3];
2031 }
2032 elsif ($valign eq 'center' || $valign eq 'centre') {
2033 $box->[1] = ($chart_box->[1] + $chart_box->[3] - $box->[3])/2;
2034 }
2035 else {
2036 return $self->_error("invalid valign $valign for $name");
2037 }
2038 $box->[2] += $box->[0];
2039 $box->[3] += $box->[1];
2040}
2041
2042sub _remove_box {
2043 my ($self, $chart_box, $object_box) = @_;
2044
2045 my $areax;
2046 my $areay;
2047 if ($object_box->[0] - $chart_box->[0]
2048 < $chart_box->[2] - $object_box->[2]) {
2049 $areax = ($object_box->[2] - $chart_box->[0])
2050 * ($chart_box->[3] - $chart_box->[1]);
2051 }
2052 else {
2053 $areax = ($chart_box->[2] - $object_box->[0])
2054 * ($chart_box->[3] - $chart_box->[1]);
2055 }
2056
2057 if ($object_box->[1] - $chart_box->[1]
2058 < $chart_box->[3] - $object_box->[3]) {
2059 $areay = ($object_box->[3] - $chart_box->[1])
2060 * ($chart_box->[2] - $chart_box->[0]);
2061 }
2062 else {
2063 $areay = ($chart_box->[3] - $object_box->[1])
2064 * ($chart_box->[2] - $chart_box->[0]);
2065 }
2066
2067 if ($areay < $areax) {
2068 if ($object_box->[1] - $chart_box->[1]
d7fd5863 2069 < $chart_box->[3] - $object_box->[3]) {
35574351
TC
2070 $chart_box->[1] = $object_box->[3];
2071 }
2072 else {
2073 $chart_box->[3] = $object_box->[1];
2074 }
2075 }
2076 else {
2077 if ($object_box->[0] - $chart_box->[0]
d7fd5863 2078 < $chart_box->[2] - $object_box->[2]) {
35574351
TC
2079 $chart_box->[0] = $object_box->[2];
2080 }
2081 else {
2082 $chart_box->[2] = $object_box->[0];
2083 }
2084 }
2085}
2086
2087sub _draw_legend {
2088 my ($self, $img, $labels, $chart_box) = @_;
2089
33a928b7
TC
2090 my $orient = $self->_get_thing('legend.orientation');
2091 defined $orient or $orient = 'vertical';
2092
2093 if ($orient eq 'vertical') {
2094 return $self->_draw_legend_vertical($img, $labels, $chart_box);
2095 }
2096 elsif ($orient eq 'horizontal') {
2097 return $self->_draw_legend_horizontal($img, $labels, $chart_box);
2098 }
2099 else {
2100 return $self->_error("Unknown legend.orientation $orient");
2101 }
2102}
2103
2104sub _draw_legend_horizontal {
2105 my ($self, $img, $labels, $chart_box) = @_;
2106
2107 defined(my $padding = $self->_get_integer('legend.padding'))
2108 or return;
2109 my $patchsize = $self->_get_integer('legend.patchsize')
2110 or return;
2111 defined(my $gap = $self->_get_integer('legend.patchgap'))
2112 or return;
2113
2114 my $minrowsize = $patchsize + $gap;
2115 my ($width, $height) = (0,0);
2116 my $row_height = $minrowsize;
2117 my $pos = 0;
2118 my @sizes;
2119 my @offsets;
2120 for my $label (@$labels) {
5d622bb8
TC
2121 my @text_box = $self->_text_bbox($label, 'legend')
2122 or return;
33a928b7
TC
2123 push(@sizes, \@text_box);
2124 my $entry_width = $patchsize + $gap + $text_box[2];
2125 if ($pos == 0) {
2126 # never re-wrap the first entry
2127 push @offsets, [ 0, $height ];
2128 }
2129 else {
2130 if ($pos + $gap + $entry_width > $chart_box->[2]) {
d7fd5863
TC
2131 $pos = 0;
2132 $height += $row_height;
33a928b7
TC
2133 }
2134 push @offsets, [ $pos, $height ];
2135 }
2136 my $entry_right = $pos + $entry_width;
2137 $pos += $gap + $entry_width;
2138 $entry_right > $width and $width = $entry_right;
2139 if ($text_box[3] > $row_height) {
2140 $row_height = $text_box[3];
2141 }
2142 }
2143 $height += $row_height;
2144 my @box = ( 0, 0, $width + $padding * 2, $height + $padding * 2 );
2145 my $outsidepadding = 0;
2146 if ($self->{_style}{legend}{border}) {
2147 defined($outsidepadding = $self->_get_integer('legend.outsidepadding'))
2148 or return;
2149 $box[2] += 2 * $outsidepadding;
2150 $box[3] += 2 * $outsidepadding;
2151 }
2152 $self->_align_box(\@box, $chart_box, 'legend')
2153 or return;
2154 if ($self->{_style}{legend}{fill}) {
2155 $img->box(xmin=>$box[0]+$outsidepadding,
2156 ymin=>$box[1]+$outsidepadding,
2157 xmax=>$box[2]-$outsidepadding,
2158 ymax=>$box[3]-$outsidepadding,
d7fd5863 2159 $self->_get_fill('legend.fill', \@box));
33a928b7
TC
2160 }
2161 $box[0] += $outsidepadding;
2162 $box[1] += $outsidepadding;
2163 $box[2] -= $outsidepadding;
2164 $box[3] -= $outsidepadding;
2165 my %text_info = $self->_text_style('legend')
2166 or return;
2167 my $patchborder;
2168 if ($self->{_style}{legend}{patchborder}) {
2169 $patchborder = $self->_get_color('legend.patchborder')
2170 or return;
2171 }
2172
2173 my $dataindex = 0;
2174 for my $label (@$labels) {
2175 my ($left, $top) = @{$offsets[$dataindex]};
2176 $left += $box[0] + $padding;
2177 $top += $box[1] + $padding;
2178 my $textpos = $left + $patchsize + $gap;
2179 my @patchbox = ( $left, $top,
2180 $left + $patchsize, $top + $patchsize );
2181 my @fill = $self->_data_fill($dataindex, \@patchbox)
2182 or return;
2183 $img->box(xmin=>$left, ymin=>$top, xmax=>$left + $patchsize,
d7fd5863 2184 ymax=>$top + $patchsize, @fill);
33a928b7
TC
2185 if ($self->{_style}{legend}{patchborder}) {
2186 $img->box(xmin=>$left, ymin=>$top, xmax=>$left + $patchsize,
d7fd5863
TC
2187 ymax=>$top + $patchsize,
2188 color=>$patchborder);
33a928b7
TC
2189 }
2190 $img->string(%text_info, x=>$textpos, 'y'=>$top + $patchsize,
2191 text=>$label);
2192
2193 ++$dataindex;
2194 }
2195 if ($self->{_style}{legend}{border}) {
2196 my $border_color = $self->_get_color('legend.border')
2197 or return;
2198 $img->box(xmin=>$box[0], ymin=>$box[1], xmax=>$box[2], ymax=>$box[3],
d7fd5863 2199 color=>$border_color);
33a928b7
TC
2200 }
2201 $self->_remove_box($chart_box, \@box);
2202 1;
2203}
2204
2205sub _draw_legend_vertical {
2206 my ($self, $img, $labels, $chart_box) = @_;
2207
379c5b02 2208 defined(my $padding = $self->_get_integer('legend.padding'))
35574351 2209 or return;
379c5b02 2210 my $patchsize = $self->_get_integer('legend.patchsize')
35574351 2211 or return;
379c5b02 2212 defined(my $gap = $self->_get_integer('legend.patchgap'))
35574351
TC
2213 or return;
2214 my $minrowsize = $patchsize + $gap;
2215 my ($width, $height) = (0,0);
2216 my @sizes;
2217 for my $label (@$labels) {
5d622bb8
TC
2218 my @box = $self->_text_bbox($label, 'legend')
2219 or return;
35574351
TC
2220 push(@sizes, \@box);
2221 $width = $box[2] if $box[2] > $width;
2222 if ($minrowsize > $box[3]) {
2223 $height += $minrowsize;
2224 }
2225 else {
2226 $height += $box[3];
2227 }
2228 }
2229 my @box = (0, 0,
d7fd5863
TC
2230 $width + $patchsize + $padding * 2 + $gap,
2231 $height + $padding * 2 - $gap);
35574351
TC
2232 my $outsidepadding = 0;
2233 if ($self->{_style}{legend}{border}) {
33a928b7 2234 defined($outsidepadding = $self->_get_integer('legend.outsidepadding'))
35574351
TC
2235 or return;
2236 $box[2] += 2 * $outsidepadding;
2237 $box[3] += 2 * $outsidepadding;
2238 }
2239 $self->_align_box(\@box, $chart_box, 'legend')
2240 or return;
2241 if ($self->{_style}{legend}{fill}) {
2242 $img->box(xmin=>$box[0]+$outsidepadding,
2243 ymin=>$box[1]+$outsidepadding,
2244 xmax=>$box[2]-$outsidepadding,
2245 ymax=>$box[3]-$outsidepadding,
d7fd5863 2246 $self->_get_fill('legend.fill', \@box));
35574351
TC
2247 }
2248 $box[0] += $outsidepadding;
2249 $box[1] += $outsidepadding;
2250 $box[2] -= $outsidepadding;
2251 $box[3] -= $outsidepadding;
2252 my $ypos = $box[1] + $padding;
2253 my $patchpos = $box[0]+$padding;
2254 my $textpos = $patchpos + $patchsize + $gap;
2255 my %text_info = $self->_text_style('legend')
2256 or return;
2257 my $patchborder;
2258 if ($self->{_style}{legend}{patchborder}) {
2259 $patchborder = $self->_get_color('legend.patchborder')
2260 or return;
2261 }
2262 my $dataindex = 0;
2263 for my $label (@$labels) {
2264 my @patchbox = ( $patchpos - $patchsize/2, $ypos - $patchsize/2,
2265 $patchpos + $patchsize * 3 / 2, $ypos + $patchsize*3/2 );
2eac77fc 2266
2267 my @fill;
2268 if ($self->_draw_flat_legend()) {
2269 @fill = (color => $self->_data_color($dataindex), filled => 1);
2270 }
2271 else {
2272 @fill = $self->_data_fill($dataindex, \@patchbox)
2273 or return;
2274 }
35574351 2275 $img->box(xmin=>$patchpos, ymin=>$ypos, xmax=>$patchpos + $patchsize,
d7fd5863 2276 ymax=>$ypos + $patchsize, @fill);
35574351
TC
2277 if ($self->{_style}{legend}{patchborder}) {
2278 $img->box(xmin=>$patchpos, ymin=>$ypos, xmax=>$patchpos + $patchsize,
d7fd5863
TC
2279 ymax=>$ypos + $patchsize,
2280 color=>$patchborder);
35574351
TC
2281 }
2282 $img->string(%text_info, x=>$textpos, 'y'=>$ypos + $patchsize,
2283 text=>$label);
2284
2285 my $step = $patchsize + $gap;
2286 if ($minrowsize < $sizes[$dataindex][3]) {
2287 $ypos += $sizes[$dataindex][3];
2288 }
2289 else {
2290 $ypos += $minrowsize;
2291 }
2292 ++$dataindex;
2293 }
2294 if ($self->{_style}{legend}{border}) {
2295 my $border_color = $self->_get_color('legend.border')
2296 or return;
2297 $img->box(xmin=>$box[0], ymin=>$box[1], xmax=>$box[2], ymax=>$box[3],
d7fd5863 2298 color=>$border_color);
35574351
TC
2299 }
2300 $self->_remove_box($chart_box, \@box);
2301 1;
2302}
2303
2304sub _draw_title {
2305 my ($self, $img, $chart_box) = @_;
2306
2307 my $title = $self->{_style}{title}{text};
5d622bb8
TC
2308 my @box = $self->_text_bbox($title, 'title')
2309 or return;
35574351
TC
2310 my $yoff = $box[1];
2311 @box[0,1] = (0,0);
2312 $self->_align_box(\@box, $chart_box, 'title');
5d622bb8
TC
2313 my %text_info = $self->_text_style('title')
2314 or return;
35574351
TC
2315 $img->string(%text_info, x=>$box[0], 'y'=>$box[3] + $yoff, text=>$title);
2316 $self->_remove_box($chart_box, \@box);
2317 1;
2318}
2319
2320sub _small_extent {
2321 my ($self, $box) = @_;
2322
2323 if ($box->[2] - $box->[0] > $box->[3] - $box->[1]) {
2324 return $box->[3] - $box->[1];
2325 }
2326 else {
2327 return $box->[2] - $box->[0];
2328 }
2329}
2330
2eac77fc 2331sub _draw_flat_legend {
2332 return 0;
2333}
2334
35574351
TC
2335=item _composite()
2336
2337Returns a list of style fields that are stored as composites, and
2338should be merged instead of just being replaced.
2339
2340=cut
2341
2342sub _composite {
2343 qw(title legend text label dropshadow outline callout);
2344}
2345
2346sub _filter_region {
2347 my ($self, $img, $left, $top, $right, $bottom, $filter) = @_;
2348
2349 unless (ref $filter) {
2350 my $name = $filter;
2351 $filter = $self->_get_thing($name)
2352 or return;
2353 $filter->{type}
2354 or return $self->_error("no type for filter $name");
2355 }
2356
2357 $left > 0 or $left = 0;
2358 $top > 0 or $top = 0;
2359
ba203e3a
TC
2360 my $masked = $img->masked(left=>$left, top=>$top,
2361 right=>$right, bottom=>$bottom);
2362 $masked->filter(%$filter);
35574351
TC
2363}
2364
23651;
2366__END__
2367
2368=back
2369
2370=head1 SEE ALSO
2371
2372Imager::Graph::Pie(3), Imager(3), perl(1).
2373
2374=head1 AUTHOR
2375
2376Tony Cook <tony@develop-help.com>
2377
54ada35d
TC
2378=head1 LICENSE
2379
2380Imager::Graph is licensed under the same terms as perl itself.
2381
35574351
TC
2382=head1 BLAME
2383
2384Addi for producing a cool imaging module. :)
2385
2386=cut