6 Imager::Graph - Perl extension for producing Graphs using the Imager library.
10 use Imager::Graph::SubClass;
11 my $chart = Imager::Graph::SubClass->new;
12 my $img = $chart->draw(data=>..., ...)
17 Imager::Graph provides style information to its base classes. It
18 defines the colors, text display information and fills based on both
19 built-in styles and modifications supplied by the user to the draw()
22 For best results you need a version of Imager after 0.38. At the time
23 of writing this is only available via CVS:
25 cvs -d :pserver:anoncvs@cvs.imager.perl.org:/u02/cvsroot login
26 cvs -d :pserver:anoncvs@cvs.imager.perl.org:/u02/cvsroot co Imager
28 This provides extra file format support, fountain (gradient), hatch
29 and image fills, and masked images.
36 use vars qw($VERSION);
37 use Imager qw(:handy);
42 my ($im_version) = ($Imager::VERSION =~ /(\d\.[\d_]+)/);
43 if ($im_version > 0.38) {
45 require 'Imager/Fountain.pm';
48 # the maximum recursion depth in determining a color, fill or number
49 use constant MAX_DEPTH => 10;
51 my $NUM_RE = '(?:[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]\d+?)?)';
55 This is a simple constructor. No parameters required.
65 Returns an error message. Only value if the draw() method returns false.
75 Creates a new image, draws the chart onto that image and returns it.
77 Typically you will need to supply a C<data> parameter in the format
78 required by that particular graph, and if your graph will use any
79 text, a C<font> parameter
81 You can also supply many different parameters which control the way
82 the graph looks. These are supplied as keyword, value pairs, where
83 the value can be a hashref containing sub values.
85 The C<style> parameter will selects a basic color set, and possibly
86 sets other related parameters. See L</"STYLES">.
88 my $img = $graph->draw(data=>\@data,
89 title=>{ text=>"Hello, World!",
93 When referring to a single sub-value this documentation will refer to
94 'title.color' rather than 'the color element of title'.
96 Returns the graph image on success, or false on failure.
102 The currently defined styles are:
108 a light red background with no outlines. Uses primary colors for the
109 data fills. This style is compatible with all versions of Imager.
111 Graphs drawn using this style should save well as a gif, even though
112 some graphs may perform a slight blur.
114 This is the default style.
118 designed for monochrome output, such as most laser printers, this uses
119 hatched fills for the data, and no colors. The returned image is a
120 one channel image (which can be overridden with the C<channels>
123 You can also override the colors used by all components for background
124 or drawing by supplying C<fg> and/or C<bg> parameters. ie. if you
125 supply C<<fg=>'FF0000', channels=>3>> then the hash fills and anything
126 else will be drawn in red. Another use might be to set a transparent
127 background, by supplying C<<bg=>'00000000', channels=>4>>.
129 This style outlines the legend if present and outlines the hashed fills.
131 This and following styles require versions of Imager after 0.38.
135 designed as a "pretty" style this uses linear fountain fills for the
136 background and data fills, and adds a drop shadow.
138 You can override the value used for text and outlines by setting the
143 also designed as a "pretty" style this uses radial fountain fills for
144 the data and a linear blue to green fill for the background.
150 Each graph type has a number of features. These are used to add
151 various items that are displayed in the graph area. Some common
158 adds a box containing boxes filled with the data filess, with
159 the labels provided to the draw method. The legend will only be
160 displayed if both the legend feature is enabled and labels are
165 labels each data fill, usually by including text inside the data fill.
166 If the text does not fit in the fill, they could be displayed in some
167 other form, eg. as callouts in a pie graph. There usually isn't much
168 point in including both labels and a legend.
172 a simple drop shadow is shown behind some of the graph elements.
176 Each graph also has features specific to that graph.
178 =head1 COMMON PARAMETERS
180 When referring to a single sub-value this documentation will refer to
181 'title.color' rather than 'the color element of title'.
183 Normally, except for the font parameter, these are controlled by
184 styles, but these are the style parameters I'd mostly likely expect
191 the Imager font object used to draw text on the chart.
195 the background fill for the graph. Default depends on the style.
199 the base size of the graph image. Default: 256
203 the width of the graph image. Default: 1.5 * size (384)
207 the height of the graph image. Default: size (256)
211 the number of channels in the image. Default: 3 (the 'mono' style
216 the color used for drawing lines, such as outlines or callouts.
217 Default depends on the current style. Set to undef to remove the
218 outline from a style.
222 the text used for a graph title. Default: no title. Note: this is
223 the same as the title=>{ text => ... } field.
229 horizontal alignment of the title in the graph, one of 'left',
230 'center' or 'right'. Default: center
234 vertical alignment of the title, one of 'top', 'center' or 'right'.
235 Default: top. It's probably a bad idea to set this to 'center' unless
236 you have a very short title.
242 This contains basic defaults used in drawing text.
248 the default color used for all text, defaults to the fg color.
252 the base size used for text, also used to scale many graph elements.
261 In most cases you will want to use just the styles, but you may want
262 to exert more control over the way your chart looks. This section
263 describes the options you can use to control the way your chart looks.
265 Hopefully you don't need to read this.
271 The background of the graph.
277 Used to define basic background and foreground colors for the graph.
278 The bg color may be used for the background of the graph, and is used
279 as a default for the background of hatcheed fills. The fg is used as
280 the default for line and text colors.
284 The default font used by the graph. Normally you should supply this
285 if your graph as any text.
289 The default line color.
293 defaults for drawing text. Other textual graph elements will inherit
294 or modify these values.
300 default text color, defaults to the I<fg> color.
304 default text size. Default: 14. This is used to scale many graph
305 elements, including padding and leader sizes. Other text elements
306 will either use or scale this value.
310 default font object. Inherited from I<font>, which should have been
311 supplied by the caller.
317 If you supply a scalar value for this element, it will be stored in
320 Defines the text, font and layout information for the title.
326 The color of the title, inherited from I<text.color>.
330 The font object used for the title, inherited from I<text.font>.
334 size of the title text. Default: double I<text.size>
340 The horizontal and vertical alignment of the title.
346 defines attributes of the graph legend, if present.
356 text attributes for the labels used in the legend.
360 the width and height of the color patch in the legend. Defaults to
361 90% of the legend text size.
365 the minimum gap between patches in pixels. Defaults to 30% of the
370 the color of the border drawn around each patch. Inherited from I<line>.
376 the horizontal and vertical alignment of the legend within the graph.
377 Defaults to 'right' and 'top'.
381 the gap between the legend patches and text and the outside of it's
382 box, or to the legend border, if any.
386 the gap between the border and the outside of the legend's box. This
387 is only used if the I<legend.border> attribute is defined.
391 the background fill for the legend. Default: none
395 the border color of the legend. Default: none (no border is drawn
402 defines attributes for graph callouts, if any are present. eg. if the
403 pie graph cannot fit the label into the pie graph segement it will
404 present it as a callout.
414 the text attributes of the callout label. Inherited from I<text>.
418 the color of the callout lines. Inherited from I<line>
424 the length of the leader on the inside and the outside of the fill,
425 usually at some angle. Both default to the size of the callout text.
429 the length of the horizontal portion of the leader. Default:
434 the gap between the callout leader and the callout text. Defaults to
435 30% of the text callout size.
441 defines attributes for labels drawn into the data areas of a graph.
451 The text attributes of the labels. Inherited from I<text>.
457 the attributes of the graph's drop shadow
463 the fill used for the drop shadow. Default: '404040' (dark gray)
467 the offset of the drop shadow. A convenience value inherited by offx
468 and offy. Default: 40% of I<text.size>.
474 the horizontal and vertical offsets of the drop shadow. Both
475 inherited from I<dropshadow.off>.
479 the filter description passed to Imager's filter method to blur the
480 drop shadow. Default: an 11 element convolution filter.
486 describes the lines drawn around filled data areas, such as the
487 segments of a pie chart.
493 the line color of the outlines, inherited from I<line>.
499 a reference to an array containing fills for each data item.
501 You can mix fill types, ie. using a simple color for the first item, a
502 hatched fill for the second and a fountain fill for the next.
506 =head1 HOW VALUES WORK
508 Internally rather than specifying literal color, fill, or font objects
509 or literal sizes for each element, Imager::Graph uses a number of
510 special values to inherit or modify values taken from other graph
513 =head2 Specifying colors
515 You can specify colors by either supplying an Imager::Color object, by
516 supplying lookup of another color, or by supplying a single value that
517 Imager::Color::new can use as an initializer. The most obvious is
518 just a 6 or 8 digit hex value representing the red, green, blue and
519 optionally alpha channels of the image.
521 You can lookup another color by using the lookup() "function", for
522 example if you give a color as "lookup(fg)" then Imager::Graph will
523 look for the fg element in the current style (or as overridden by
524 you.) This is used internally by Imager::Graph to set up the
525 relationships between the colors of various elements, for example the
526 default style information contains:
533 color=>'lookup(text.color)',
537 So by setting the I<fg> color, you also set the default text color,
538 since each text element uses lookup(text.color) as its value.
540 =head2 Specifying fills
542 Fills can be used for the graph background color, the background color
543 for the legend block and for the fills used for each data element.
545 You can specify a fill as a L<color value|Specifying colors> or as a
546 general fill, see L<Imager::Fill> for details. To use a general fill
547 you need a version of Imager after 0.38.
549 You don't need (or usually want) to call Imager::Fill::new yourself,
550 since the various fill functions will call it for you, and
551 Imager::Graph provides some hooks to make them more useful.
557 with hatched fills, if you don't supply a 'fg' or 'bg' parameter,
558 Imager::Graph will supply the current graph fg and bg colors.
562 with fountain fill, you can supply the xa_ratio, ya_ratio, xb_ratio
563 and yb_ratio parameters, and they will be scaled in the fill area to
564 define the fountain fills xa, ya, xb and yb parameters.
568 As with colors, you can use lookup(name) or lookup(name1.name2) to
569 have one element to inherit the fill of another.
571 =head2 Specifying numbers
573 You can specify various numbers, usually representing the size of
574 something, commonly text, but sometimes the length of a line or the
577 You can use the same lookup mechanism as with colors and fills, but
578 you can also scale values. For example, 'scale(0.5,text.size)' will
579 return half the size of the normal text size.
581 As with colors, this is used internally to scale graph elements based
582 on the base text size. If you change the base text size then other
583 graph elements will scale as well.
585 =head2 Specifying other elements
587 Other elements, such as fonts, or parameters for a filter, can also
588 use the lookup(name) mechanism.
590 =head1 INTERNAL METHODS
592 Only useful if you need to fix bugs, add features or create a new
604 color => 'lookup(fg)',
605 font => 'lookup(font)',
609 color => 'lookup(text.color)',
610 font => 'lookup(text.font)',
613 size => 'scale(text.size,2.0)',
616 color => 'lookup(text.color)',
617 font => 'lookup(text.font)',
618 size => 'lookup(text.size)',
619 patchsize => 'scale(legend.size,0.9)',
620 patchgap => 'scale(legend.patchsize,0.3)',
621 patchborder => 'lookup(line)',
624 padding => 'scale(legend.size,0.3)',
625 outsidepadding => 'scale(legend.padding,0.4)',
628 color => 'lookup(text.color)',
629 font => 'lookup(text.font)',
630 size => 'lookup(text.size)',
631 line => 'lookup(line)',
632 inside => 'lookup(callout.size)',
633 outside => 'lookup(callout.size)',
634 leadlen => 'scale(0.8,callout.size)',
635 gap => 'scale(callout.size,0.3)',
638 font => 'lookup(text.font)',
639 size => 'lookup(text.size)',
640 color => 'lookup(text.color)',
641 hpad => 'lookup(label.pad)',
642 vpad => 'lookup(label.pad)',
643 pad => 'scale(label.size,0.2)',
644 pcformat => sub { sprintf "%s (%.0f%%)", $_[0], $_[1] },
645 pconlyformat => sub { sprintf "%.1f%%", $_[0] },
649 off => 'scale(0.4,text.size)',
650 offx => 'lookup(dropshadow.off)',
651 offy => 'lookup(dropshadow.off)',
652 filter => { type=>'conv',
653 # this needs a fairly heavy blur
654 coef=>[0.1, 0.2, 0.4, 0.6, 0.7, 0.9, 1.2,
655 0.9, 0.7, 0.6, 0.4, 0.2, 0.1 ] },
658 line =>'lookup(line)',
661 width=>'scale(1.5,size)',
662 height=>'lookup(size)',
665 =item _error($message)
667 Sets the error field of the object and returns an empty list or undef,
668 depending on context. Should be used for error handling, since it may
669 provide some user hooks at some point.
674 my ($self, $error) = @_;
676 $self->{_errstr} = $error;
684 Returns the style defaults, such as the relationships between line
685 color and text color.
687 Intended to be over-ridden by base classes to provide graph specific
696 my $def_style = 'primary_red';
704 qw(FF0000 00FF00 0000FF C0C000 00C0C0 FF00FF)
710 patchborder=>'000000'
723 { hatch=>'stipple3' },
724 { hatch=>'stipple2' },
729 features=>{ outline=>1 },
741 { fountain=>'linear',
742 xa_ratio=>0.13, ya_ratio=>0.13, xb_ratio=>0.87, yb_ratio=>0.87,
744 segments => Imager::Fountain->simple(positions=>[0, 1],
745 colors=>[ NC('FFC0C0'), NC('FF0000') ]),
747 { fountain=>'linear',
748 xa_ratio=>0, ya_ratio=>0, xb_ratio=>1.0, yb_ratio=>1.0,
749 segments => Imager::Fountain->simple(positions=>[0, 1],
750 colors=>[ NC('C0FFC0'), NC('00FF00') ]),
752 { fountain=>'linear',
753 xa_ratio=>0, ya_ratio=>0, xb_ratio=>1.0, yb_ratio=>1.0,
754 segments => Imager::Fountain->simple(positions=>[0, 1],
755 colors=>[ NC('C0C0FF'), NC('0000FF') ]),
757 { fountain=>'linear',
758 xa_ratio=>0, ya_ratio=>0, xb_ratio=>1.0, yb_ratio=>1.0,
759 segments => Imager::Fountain->simple(positions=>[0, 1],
760 colors=>[ NC('FFFFC0'), NC('FFFF00') ]),
762 { fountain=>'linear',
763 xa_ratio=>0, ya_ratio=>0, xb_ratio=>1.0, yb_ratio=>1.0,
764 segments => Imager::Fountain->simple(positions=>[0, 1],
765 colors=>[ NC('C0FFFF'), NC('00FFFF') ]),
767 { fountain=>'linear',
768 xa_ratio=>0, ya_ratio=>0, xb_ratio=>1.0, yb_ratio=>1.0,
769 segments => Imager::Fountain->simple(positions=>[0, 1],
770 colors=>[ NC('FFC0FF'), NC('FF00FF') ]),
773 back=>{ fountain=>'linear',
774 xa_ratio=>0, ya_ratio=>0,
775 xb_ratio=>1.0, yb_ratio=>1.0,
776 segments=>Imager::Fountain->simple
778 colors=>[ NC('6060FF'), NC('60FF60') ]) },
781 features=>{ dropshadow=>1 },
787 { fountain=>'radial',
788 xa_ratio=>0.5, ya_ratio=>0.5, xb_ratio=>1.0, yb_ratio=>0.5,
789 segments => Imager::Fountain->simple(positions=>[0, 1],
790 colors=>[ NC('FF8080'), NC('FF0000') ]),
792 { fountain=>'radial',
793 xa_ratio=>0.5, ya_ratio=>0.5, xb_ratio=>1.0, yb_ratio=>0.5,
794 segments => Imager::Fountain->simple(positions=>[0, 1],
795 colors=>[ NC('80FF80'), NC('00FF00') ]),
797 { fountain=>'radial',
798 xa_ratio=>0.5, ya_ratio=>0.5, xb_ratio=>1.0, yb_ratio=>0.5,
799 segments => Imager::Fountain->simple(positions=>[0, 1],
800 colors=>[ NC('808080FF'), NC('0000FF') ]),
802 { fountain=>'radial',
803 xa_ratio=>0.5, ya_ratio=>0.5, xb_ratio=>1.0, yb_ratio=>0.5,
804 segments => Imager::Fountain->simple(positions=>[0, 1],
805 colors=>[ NC('FFFF80'), NC('FFFF00') ]),
807 { fountain=>'radial',
808 xa_ratio=>0.5, ya_ratio=>0.5, xb_ratio=>1.0, yb_ratio=>0.5,
809 segments => Imager::Fountain->simple(positions=>[0, 1],
810 colors=>[ NC('80FFFF'), NC('00FFFF') ]),
812 { fountain=>'radial',
813 xa_ratio=>0.5, ya_ratio=>0.5, xb_ratio=>1.0, yb_ratio=>0.5,
814 segments => Imager::Fountain->simple(positions=>[0, 1],
815 colors=>[ NC('FF80FF'), NC('FF00FF') ]),
818 back=>{ fountain=>'linear',
819 xa_ratio=>0, ya_ratio=>0,
820 xb_ratio=>1.0, yb_ratio=>1.0,
821 segments=>Imager::Fountain->simple
823 colors=>[ NC('6060FF'), NC('60FF60') ]) },
829 =item $self->_style_setup(\%opts)
831 Uses the values from %opts to build a customized hash describing the
832 way the graph should be drawn.
837 my ($self, $opts) = @_;
838 my $style_defs = $self->_style_defs;
840 $style = $styles{$opts->{style}} if $opts->{style};
841 $style ||= $styles{$def_style};
843 my @search_list = ( $style_defs, $style, $opts);
846 my @composite = $self->_composite();
848 @composite{@composite} = @composite;
850 for my $src (@search_list) {
851 for my $key (keys %$src) {
852 if ($composite{$key}) {
853 $work{$key} = {} unless exists $work{$key};
854 if (ref $src->{$key}) {
855 # some keys have sub values, especially text
856 @{$work{$key}}{keys %{$src->{$key}}} = values %{$src->{$key}};
859 # assume it's the text for a title or something
860 $work{$key}{text} = $src->{$key};
864 $work{$key} = $src->{$key};
869 # features are handled specially
870 $work{features} = {};
871 for my $src (@search_list) {
872 if ($src->{features}) {
873 if (ref $src->{features}) {
874 if (ref($src->{features}) =~ /ARRAY/) {
875 # just set those features
876 for my $feature (@{$src->{features}}) {
877 $work{features}{$feature} = 1;
880 elsif (ref($src->{features}) =~ /HASH/) {
881 if ($src->{features}{reset}) {
882 $work{features} = {}; # only the ones the user specifies
884 @{$work{features}}{keys %{$src->{features}}} =
885 values(%{$src->{features}});
889 # just set that single feature
890 $work{features}{$src->{features}} = 1;
895 #print Dumper(\%work);
897 $self->{_style} = \%work;
900 =item $self->_get_thing($name)
902 Retrieve some general 'thing'.
904 Supports the 'lookup(foo)' mechanism.
909 my ($self, $name, @depth) = @_;
913 if ($name =~ /^(\w+)\.(\w+)$/) {
914 $what = $self->{_style}{$1}{$2};
917 $what = $self->{_style}{$name};
924 elsif ($what =~ /^lookup\((\w+(?:\.\w+)?)\)$/) {
926 or return $self->_error("too many levels of recursion in lookup(@depth)");
927 return $self->_get_thing($1, @depth);
934 =item $self->_get_number($name)
936 Retrieves a number from the style. The value in the style can be the
937 number, or one of two functions:
941 =item lookup(newname)
943 Recursively looks up I<newname> in the style.
945 =item scale(value1,value2)
947 Each value can be a number or a name. Names are recursively looks up
948 in the style and the product is returned.
954 my ($self, $name, @depth) = @_;
958 if ($name =~ /^(\w+)\.(\w+)$/) {
959 $what = $self->{_style}{$1}{$2};
962 $what = $self->{_style}{$name};
965 return $self->_error("$name is undef (@depth)");
968 if ($what =~ /CODE/) {
969 $what = $what->($self, $name);
973 if ($what =~ /^lookup\(([\w.]+)\)$/) {
975 or return $self->_error("too many levels of recursion in lookup (@depth)");
976 return $self->_get_number($1, @depth);
978 elsif ($what =~ /^scale\(
979 ((?:[a-z][\w.]*)|$NUM_RE)
981 ((?:[a-z][\w.]*)|$NUM_RE)\)$/x) {
982 my ($left, $right) = ($1, $2);
983 unless ($left =~ /^$NUM_RE$/) {
985 or return $self->_error("too many levels of recursion in scale (@depth)");
986 $left = $self->_get_number($left, @depth);
988 unless ($right =~ /^$NUM_RE$/) {
990 or return $self->_error("too many levels of recursion in scale (@depth)");
991 $right = $self->_get_number($right, @depth);
993 return $left * $right;
1001 =item _get_color($name)
1003 Returns a color object of the given name from the style hash.
1005 Uses Imager::Color->new to translate normal scalars into color objects.
1007 Allows the lookup(name) mechanism.
1012 my ($self, $name, @depth) = @_;
1014 push(@depth, $name);
1016 if ($name =~ /^(\w+)\.(\w+)$/) {
1017 $what = $self->{_style}{$1}{$2};
1020 $what = $self->{_style}{$name};
1024 or return $self->_error("$name was undefined (@depth)");
1026 unless (ref $what) {
1027 if ($what =~ /^lookup\((\w+(?:\.\w+)?)\)$/) {
1028 @depth < MAX_DEPTH or
1029 return $self->_error("too many levels of recursion in lookup (@depth)");
1031 return $self->_get_color($1, @depth);
1033 $what = Imager::Color->new($what);
1039 =item _translate_fill($what, $box)
1041 Given the value of a fill, either attempts to convert it into a fill
1042 list (one of C<<color=>$color_value, filled=>1>> or C<<fill=>{ fill
1043 parameters }>>), or to lookup another fill that is referred to with
1044 the 'lookup(name)' mechanism.
1046 This function does the fg and bg initialization for hatched fills, and
1047 translation of *_ratio for fountain fills (using the $box parameter).
1051 sub _translate_fill {
1052 my ($self, $what, $box, @depth) = @_;
1055 if (UNIVERSAL::isa($what, "Imager::Color")) {
1056 return ( color=>Imager::Color->new($what), filled=>1 );
1060 if ($what->{hatch}) {
1063 $work{fg} = $self->_get_color('fg')
1067 $work{bg} = $self->_get_color('bg')
1070 return ( fill=>\%work );
1072 elsif ($what->{fountain}) {
1074 for my $key (qw(xa ya xb yb)) {
1075 if (exists $work{"${key}_ratio"}) {
1077 $work{$key} = $box->[0] + $work{"${key}_ratio"}
1078 * ($box->[2] - $box->[0]);
1081 $work{$key} = $box->[1] + $work{"${key}_ratio"}
1082 * ($box->[3] - $box->[1]);
1086 return ( fill=>\%work );
1089 return ( fill=> $what );
1094 if ($what =~ /^lookup\((\w+(?:\.\w+)?)\)$/) {
1095 return $self->_get_fill($1, $box, @depth);
1098 # assumed to be an Imager::Color single value
1099 return ( color=>Imager::Color->new($what), filled=>1 );
1104 =item _data_fill($index, $box)
1106 Retrieves the fill parameters for a data area fill.
1111 my ($self, $index, $box) = @_;
1113 my $fills = $self->{_style}{fills};
1114 return $self->_translate_fill($fills->[$index % @$fills], $box,
1118 =item _get_fill($index, $box)
1120 Retrieves fill parameters for a named fill.
1125 my ($self, $name, $box, @depth) = @_;
1127 push(@depth, $name);
1129 if ($name =~ /^(\w+)\.(\w+)$/) {
1130 $what = $self->{_style}{$1}{$2};
1133 $what = $self->{_style}{$name};
1137 or return $self->_error("no fill $name found");
1139 return $self->_translate_fill($what, $box, @depth);
1144 Builds the image object for the graph and fills it with the background
1152 my ($width, $height) = (256, 256);
1154 $width = $self->_get_number('width');
1155 $height = $self->_get_number('height');
1156 my $channels = $self->{_style}{channels};
1160 my $img = Imager->new(xsize=>$width, ysize=>$height, channels=>$channels);
1162 $img->box($self->_get_fill('back', [ 0, 0, $width-1, $height-1]));
1168 my ($self, $name) = @_;
1172 if ($self->{_style}{$name}) {
1173 %work = %{$self->{_style}{$name}};
1176 %work = %{$self->{_style}{text}};
1179 or return $self->_error("$name has no font parameter");
1181 $work{font} = $self->_get_thing("$name.font")
1182 or return $self->_error("invalid font");
1183 UNIVERSAL::isa($work{font}, "Imager::Font")
1184 or return $self->_error("$name.font is not a font");
1185 if ($work{color} && !ref $work{color}) {
1186 $work{color} = $self->_get_color("$name.color")
1189 $work{size} = $self->_get_number("$name.size");
1190 $work{sizew} = $self->_get_number("$name.sizew")
1197 my ($self, $text, $name) = @_;
1199 my %text_info = $self->_text_style($name);
1201 my @bbox = $text_info{font}->bounding_box(%text_info, string=>$text,
1208 my ($self, $box, $chart_box, $name) = @_;
1210 my $halign = $self->{_style}{$name}{halign}
1211 or $self->_error("no halign for $name");
1212 my $valign = $self->{_style}{$name}{valign};
1214 if ($halign eq 'right') {
1215 $box->[0] += $chart_box->[2] - $box->[2];
1217 elsif ($halign eq 'left') {
1218 $box->[0] = $chart_box->[0];
1220 elsif ($halign eq 'center' || $halign eq 'centre') {
1221 $box->[0] = ($chart_box->[0] + $chart_box->[2] - $box->[2])/2;
1224 return $self->_error("invalid halign $halign for $name");
1227 if ($valign eq 'top') {
1228 $box->[1] = $chart_box->[1];
1230 elsif ($valign eq 'bottom') {
1231 $box->[1] = $chart_box->[3] - $box->[3];
1233 elsif ($valign eq 'center' || $valign eq 'centre') {
1234 $box->[1] = ($chart_box->[1] + $chart_box->[3] - $box->[3])/2;
1237 return $self->_error("invalid valign $valign for $name");
1239 $box->[2] += $box->[0];
1240 $box->[3] += $box->[1];
1244 my ($self, $chart_box, $object_box) = @_;
1248 if ($object_box->[0] - $chart_box->[0]
1249 < $chart_box->[2] - $object_box->[2]) {
1250 $areax = ($object_box->[2] - $chart_box->[0])
1251 * ($chart_box->[3] - $chart_box->[1]);
1254 $areax = ($chart_box->[2] - $object_box->[0])
1255 * ($chart_box->[3] - $chart_box->[1]);
1258 if ($object_box->[1] - $chart_box->[1]
1259 < $chart_box->[3] - $object_box->[3]) {
1260 $areay = ($object_box->[3] - $chart_box->[1])
1261 * ($chart_box->[2] - $chart_box->[0]);
1264 $areay = ($chart_box->[3] - $object_box->[1])
1265 * ($chart_box->[2] - $chart_box->[0]);
1268 if ($areay < $areax) {
1269 if ($object_box->[1] - $chart_box->[1]
1270 < $chart_box->[3] - $object_box->[3]) {
1271 $chart_box->[1] = $object_box->[3];
1274 $chart_box->[3] = $object_box->[1];
1278 if ($object_box->[0] - $chart_box->[0]
1279 < $chart_box->[2] - $object_box->[2]) {
1280 $chart_box->[0] = $object_box->[2];
1283 $chart_box->[2] = $object_box->[0];
1289 my ($self, $img, $labels, $chart_box) = @_;
1291 defined(my $padding = $self->_get_number('legend.padding'))
1293 my $patchsize = $self->_get_number('legend.patchsize')
1295 defined(my $gap = $self->_get_number('legend.patchgap'))
1297 my $minrowsize = $patchsize + $gap;
1298 my ($width, $height) = (0,0);
1300 for my $label (@$labels) {
1301 my @box = $self->_text_bbox($label, 'legend');
1302 push(@sizes, \@box);
1303 $width = $box[2] if $box[2] > $width;
1304 if ($minrowsize > $box[3]) {
1305 $height += $minrowsize;
1312 $width + $patchsize + $padding * 2 + $gap,
1313 $height + $padding * 2 - $gap);
1314 my $outsidepadding = 0;
1315 if ($self->{_style}{legend}{border}) {
1316 defined($outsidepadding = $self->_get_number('legend.outsidepadding'))
1318 $box[2] += 2 * $outsidepadding;
1319 $box[3] += 2 * $outsidepadding;
1321 $self->_align_box(\@box, $chart_box, 'legend')
1323 if ($self->{_style}{legend}{fill}) {
1324 $img->box(xmin=>$box[0]+$outsidepadding,
1325 ymin=>$box[1]+$outsidepadding,
1326 xmax=>$box[2]-$outsidepadding,
1327 ymax=>$box[3]-$outsidepadding,
1328 $self->_get_fill('legend.fill', \@box));
1330 $box[0] += $outsidepadding;
1331 $box[1] += $outsidepadding;
1332 $box[2] -= $outsidepadding;
1333 $box[3] -= $outsidepadding;
1334 my $ypos = $box[1] + $padding;
1335 my $patchpos = $box[0]+$padding;
1336 my $textpos = $patchpos + $patchsize + $gap;
1337 my %text_info = $self->_text_style('legend')
1340 if ($self->{_style}{legend}{patchborder}) {
1341 $patchborder = $self->_get_color('legend.patchborder')
1345 for my $label (@$labels) {
1346 my @patchbox = ( $patchpos - $patchsize/2, $ypos - $patchsize/2,
1347 $patchpos + $patchsize * 3 / 2, $ypos + $patchsize*3/2 );
1348 my @fill = $self->_data_fill($dataindex, \@patchbox)
1350 $img->box(xmin=>$patchpos, ymin=>$ypos, xmax=>$patchpos + $patchsize,
1351 ymax=>$ypos + $patchsize, @fill);
1352 if ($self->{_style}{legend}{patchborder}) {
1353 $img->box(xmin=>$patchpos, ymin=>$ypos, xmax=>$patchpos + $patchsize,
1354 ymax=>$ypos + $patchsize,
1355 color=>$patchborder);
1357 $img->string(%text_info, x=>$textpos, 'y'=>$ypos + $patchsize,
1360 my $step = $patchsize + $gap;
1361 if ($minrowsize < $sizes[$dataindex][3]) {
1362 $ypos += $sizes[$dataindex][3];
1365 $ypos += $minrowsize;
1369 if ($self->{_style}{legend}{border}) {
1370 my $border_color = $self->_get_color('legend.border')
1372 $img->box(xmin=>$box[0], ymin=>$box[1], xmax=>$box[2], ymax=>$box[3],
1373 color=>$border_color);
1375 $self->_remove_box($chart_box, \@box);
1380 my ($self, $img, $chart_box) = @_;
1382 my $title = $self->{_style}{title}{text};
1383 my @box = $self->_text_bbox($title, 'title');
1386 $self->_align_box(\@box, $chart_box, 'title');
1387 my %text_info = $self->_text_style('title');
1388 $img->string(%text_info, x=>$box[0], 'y'=>$box[3] + $yoff, text=>$title);
1389 $self->_remove_box($chart_box, \@box);
1394 my ($self, $box) = @_;
1396 if ($box->[2] - $box->[0] > $box->[3] - $box->[1]) {
1397 return $box->[3] - $box->[1];
1400 return $box->[2] - $box->[0];
1406 Returns a list of style fields that are stored as composites, and
1407 should be merged instead of just being replaced.
1412 qw(title legend text label dropshadow outline callout);
1415 sub _filter_region {
1416 my ($self, $img, $left, $top, $right, $bottom, $filter) = @_;
1418 unless (ref $filter) {
1420 $filter = $self->_get_thing($name)
1423 or return $self->_error("no type for filter $name");
1426 $left > 0 or $left = 0;
1427 $top > 0 or $top = 0;
1429 # newer versions of Imager let you work on just part of an image
1430 if ($img->can('masked') && !$self->{_style}{features}{_debugblur}) {
1431 my $masked = $img->masked(left=>$left, top=>$top,
1432 right=>$right, bottom=>$bottom);
1433 $masked->filter(%$filter);
1436 # for older versions of Imager
1437 my $subset = $img->crop(left=>$left, top=>$top,
1438 right=>$right, bottom=>$bottom);
1439 $subset->filter(%$filter);
1440 $img->paste(left=>$left, top=>$top, img=>$subset);
1451 Imager::Graph::Pie(3), Imager(3), perl(1).
1455 Tony Cook <tony@develop-help.com>
1459 Imager::Graph is licensed under the same terms as perl itself.
1463 Addi for producing a cool imaging module. :)