File: | blib/lib/SVG/Sparkline/RangeArea.pm |
Coverage: | 94.1% |
line | stmt | bran | cond | sub | time | code |
---|---|---|---|---|---|---|
1 | package SVG::Sparkline::RangeArea; | |||||
2 | ||||||
3 | 3 3 3 | 16 4 134 | use warnings; | |||
4 | 3 3 3 | 13 4 75 | use strict; | |||
5 | 3 3 3 | 14 4 238 | use Carp; | |||
6 | 3 3 3 | 13 4 68 | use SVG; | |||
7 | 3 3 3 | 6498 4 54 | use SVG::Sparkline::Utils; | |||
8 | ||||||
9 | 3 3 3 | 114 6 1072 | use 5.008000; | |||
10 | our $VERSION = 0.35; | |||||
11 | ||||||
12 | # aliases to make calling shorter. | |||||
13 | *_f = *SVG::Sparkline::Utils::format_f; | |||||
14 | ||||||
15 | sub valid_param { | |||||
16 | 0 0 | 0 0 | return scalar grep { $_[1] eq $_ } qw/xrange yrange/; | |||
17 | } | |||||
18 | ||||||
19 | sub make | |||||
20 | { | |||||
21 | 21 | 21 | my ($class, $args) = @_; | |||
22 | # validate parameters | |||||
23 | 21 | 236 | SVG::Sparkline::Utils::validate_array_param( $args, 'values' ); | |||
24 | 81 | 168 | croak "'values' must be an array of pairs.\n" | |||
25 | 17 85 17 | 11 211 20 | if grep { 'ARRAY' ne ref $_ || 2 != @{$_} } @{$args->{values}}; | |||
26 | 81 | 66 | my $valdesc = SVG::Sparkline::Utils::summarize_xy_values( | |||
27 | 16 16 81 16 | 10 16 258 14 | [ (map { $_->[0] } @{$args->{values}}), (reverse map { $_->[1] } @{$args->{values}}) ] | |||
28 | ); | |||||
29 | 16 16 | 17 16 | $valdesc->{xrange} = $#{$args->{values}}; | |||
30 | 16 16 | 11 15 | $valdesc->{xmax} = $#{$args->{values}}; | |||
31 | 16 | 9 | my $off = $valdesc->{xrange}; | |||
32 | 16 16 16 | 19 19 27 | foreach my $v (@{$valdesc->{vals}}[($off+1) .. $#{$valdesc->{vals}}]) | |||
33 | { | |||||
34 | 81 | 58 | $v->[0] = $off--; | |||
35 | } | |||||
36 | ||||||
37 | 16 | 203 | SVG::Sparkline::Utils::calculate_xscale( $args, $valdesc->{xrange} ); | |||
38 | 16 | 187 | SVG::Sparkline::Utils::calculate_yscale_and_offset( $args, $valdesc->{yrange}, $valdesc->{offset} ); | |||
39 | 16 | 191 | my $svg = SVG::Sparkline::Utils::make_svg( $args ); | |||
40 | ||||||
41 | 16 | 188 | my $points = SVG::Sparkline::Utils::xypairs_to_points_str( | |||
42 | $valdesc->{vals}, $args->{xscale}, $args->{yscale} | |||||
43 | ); | |||||
44 | 16 | 145 | $svg->polygon( fill=>$args->{color}, points=>$points, stroke=>'none' ); | |||
45 | ||||||
46 | 16 | 664 | if( exists $args->{mark} ) | |||
47 | { | |||||
48 | 5 | 9 | _make_marks( $svg, | |||
49 | xscale=>$args->{xscale}, yscale=>$args->{yscale}, | |||||
50 | values=>$args->{values}, mark=>$args->{mark}, | |||||
51 | base=>$valdesc->{base} | |||||
52 | ); | |||||
53 | } | |||||
54 | ||||||
55 | 16 | 200 | return $svg; | |||
56 | } | |||||
57 | ||||||
58 | sub _make_marks | |||||
59 | { | |||||
60 | 5 | 9 | my ($svg, %args) = @_; | |||
61 | ||||||
62 | 5 5 | 3 7 | my @marks = @{$args{mark}}; | |||
63 | 5 | 7 | while(@marks) | |||
64 | { | |||||
65 | 5 | 5 | my ($index,$color) = splice( @marks, 0, 2 ); | |||
66 | 5 | 59 | $index = SVG::Sparkline::Utils::range_mark_to_index( 'RangeArea', $index, $args{values} ); | |||
67 | 5 | 9 | _make_mark( $svg, %args, index=>$index, color=>$color ); | |||
68 | } | |||||
69 | 5 | 5 | return; | |||
70 | } | |||||
71 | ||||||
72 | sub _make_mark | |||||
73 | { | |||||
74 | 5 | 10 | my ($svg, %args) = @_; | |||
75 | 5 | 5 | my $index = $args{index}; | |||
76 | 5 5 | 3 7 | my ($lo, $hi) = @{$args{values}->[$index]}; | |||
77 | 5 | 58 | my $y = _f( ($lo-$args{base}) * $args{yscale} ); | |||
78 | 5 | 57 | my $yh = _f( ($hi-$args{base}) * $args{yscale} ); | |||
79 | 5 | 55 | my $x = _f($index * $args{xscale}); | |||
80 | ||||||
81 | 5 | 11 | if(abs($hi-$lo) <= 0.01) | |||
82 | { | |||||
83 | 0 | 0 | $svg->circle( cx=>$x, cy=>$y, r=>1, fill=>$args{color}, stroke=>'none' ); | |||
84 | } | |||||
85 | else | |||||
86 | { | |||||
87 | 5 | 41 | $svg->line( x1=>$x, y1=>$y, x2=>$x, y2=>$yh, | |||
88 | fill=>'none', stroke=>$args{color}, 'stroke-width'=>1 | |||||
89 | ); | |||||
90 | } | |||||
91 | 5 | 250 | return; | |||
92 | } | |||||
93 | ||||||
94 | 1; # Magic true value required at end of module |