File Coverage

lib/Template/Colour.pm
Criterion Covered Total %
statement 58 71 81.6
branch 24 32 75.0
condition 12 28 42.8
subroutine 13 17 76.4
pod 3 12 25.0
total 110 160 68.7


line stmt bran cond sub pod time code
1             package Template::Colour;
2              
3             use Template::Colour::Class
4 3         34 debug => 0,
5             base => 'Badger::Base',
6             constants => 'HASH SCHEME WHITE BLACK',
7             utils => 'is_object',
8             import => 'class',
9             messages => {
10             bad_param => 'invalid %s parameter(s): %s',
11             no_param => 'missing %s colour parameter: %s',
12 3     3   305324 };
  3         7  
13              
14 3     3   4308 use Template::Colour::RGB;
  3         10  
  3         117  
15 3     3   1833 use Template::Colour::HSV;
  3         9  
  3         113  
16 3     3   1036 use POSIX 'floor';
  3         8084  
  3         45  
17              
18             our $VERSION = 0.05;
19             our @SCHEME = qw(
20             black darkest darker dark mid light lighter lightest white
21             pale wash dull bold bright
22             );
23             our $SPACES = {
24             RGB => 'Template::Colour::RGB',
25             HSV => 'Template::Colour::HSV',
26             };
27              
28             class->methods(
29             # create methods for each of the scheme variants
30             map {
31             my $name = $_; # lexical copy for closure
32             $_ => sub {
33 6     6   160 shift->scheme->{ $name };
34             }
35             }
36             @SCHEME
37             );
38              
39              
40             sub new {
41 33     33 1 61 my $class = shift;
42 33         37 my ($config, $space);
43              
44 33 100       68 if (@_ == 1) {
    100          
    50          
    50          
45             # single argument is either an existing colour object which we copy...
46 28 100 66     124 return $_[0]->copy()
47             if is_object(ref $class || $class, $_[0]);
48              
49             # ... or a hash ref of named parameters...
50             # e.g { rgb => '#rrggbb' }, { rgb => [r, g, b] }, hsv => [h, s, v] }
51             # ... or a single RGB argument
52             # e.g. [r, g, b], '#rrggbb'
53 26 100       171 $config = ref $_[0] eq HASH ? shift : { rgb => shift };
54             }
55             elsif (@_ == 2) {
56             # two arguments are (colour-space => $value),
57             # e.g. (rgb => '#rrggbb'), (rgb => [r, g, b]), (hsv => [h, s, v])
58 3         8 $config = { @_ };
59             }
60             elsif (@_ == 3) {
61             # three arguments are (r, g, b)
62 0         0 $config->{ rgb } = [ @_ ];
63             }
64             elsif (@_) {
65             # four or more arguments are named parameters
66 2         8 $config = { @_ };
67             }
68             else {
69             # How much more black can this be? The answer is none. None more black.
70 0         0 $config = { rgb => [0, 0, 0] };
71             }
72            
73 31 100 66     127 if ($space = $config->{ rgb } || $config->{ RGB }) {
    100 66        
    100          
74             # explicit RGB specification (rgb => ...)
75 28         66 return $class->RGB($space);
76             }
77             elsif ($space = $config->{ hsv } || $config->{ HSV }) {
78             # explicit HSV specification (hsv => ...)
79 1         4 return $class->HSV($space);
80             }
81             elsif (exists $config->{ hue }) {
82             # implicit HSV specification (hue => $h, ...)
83 1         3 return $class->HSV($config);
84             }
85             else {
86             # if we don't get an explicit RGB or HSV colour space then we
87             # default to RGB to handle the (red => $r, green => $g, blue => $b) case
88 1         5 return $class->RGB($config);
89             }
90             }
91              
92             sub RGB {
93 80     80 1 293 my $self = shift;
94 80         279 return $self->class->hash_value( SPACES => 'RGB' )->new(@_);
95             }
96              
97             sub HSV {
98 43     43 1 268 my $self = shift;
99 43         126 return $self->class->hash_value( SPACES => 'HSV' )->new(@_);
100             }
101              
102             sub copy {
103             # should be redefined by subclasses
104 0     0 0 0 return $_[0];
105             }
106              
107             sub adjust {
108 0     0 0 0 my $self = shift;
109 0         0 return $self->not_implemented();
110             }
111              
112             sub range {
113 0     0 0 0 my $self = shift;
114 0         0 return $self->not_implemented();
115             }
116              
117             sub tints {
118 14     14 0 16 my $self = shift;
119 14   50     26 my $steps = shift || 4;
120 14 50 33     76 return $self->range($steps, @_ && $_[0] ? @_ : WHITE);
121             }
122              
123             sub shades {
124 7     7 0 104 my $self = shift;
125 7   50     18 my $steps = shift || 4;
126 7 50 33     36 my @black = @_ && $_[0] ? @_ : BLACK;
127 7         27 return $self->range($steps, @black);
128             }
129              
130             sub scheme {
131 7     7 0 19 my $self = shift;
132              
133             # return the cached scheme if we have one and no args are defined
134 7 50 33     22 return $self->[SCHEME]
135             if $self->[SCHEME]
136             && ! @_;
137              
138 7 50 33     24 my $args = @_ && ref $_[0] eq HASH ? shift : { @_ };
139 7         44 my $shades = $self->shades(4, $args->{ black }); # black to col
140 7         34 my $tints = $self->tints(4, $args->{ white }); # col to white
141 7         30 my $washes = $tints->[3]->tints(3, $args->{ white }); # pale washes
142 7         13 my $scheme = { };
143              
144             # remove the base colour and white from washes
145 7         9 shift(@$washes);
146 7         8 pop(@$washes);
147            
148             # remove base colour from shades to avoid duplication with same in tints
149 7         11 shift(@$shades);
150              
151 7         24 @$scheme{ @SCHEME } = (
152             # black, darkest, darker, dark
153             reverse(@$shades),
154             # mid light lighter lightest white
155             @$tints,
156             # pale, wash
157             @$washes,
158             # dull
159             $self->copy->hsv->adjust(sat => '-10%', value => '-10%'),
160             # bold
161             $self->copy->hsv->adjust(sat => '+10%', value => '-10%'),
162             # bright
163             $self->copy->hsv->adjust(sat => '+10%', value => '+10%'),
164             );
165 7         53 return $scheme;
166             }
167              
168             sub variations {
169 0     0 0 0 my $self = shift;
170 0 0 0     0 my $args = @_ && ref $_[0] eq HASH ? shift : { @_ };
171 0         0 my $scheme = { };
172 0         0 while (my($name, $values) = each %$args) {
173 0         0 $scheme->{ $name } = $self->copy->update($values);
174             }
175 0         0 return $scheme;
176             }
177              
178             #------------------------------------------------------------------------
179             # min($r, $g, $b)
180             #
181             # Returns minimum value from arguments, used for colour space conversion.
182             #------------------------------------------------------------------------
183              
184             sub min {
185 33     33 0 38 my $self = shift;
186 33         34 my $min = shift;
187 33         59 foreach my $v (@_) {
188 66 100       157 $min = $v if $v < $min;
189             }
190 33         77 return $min;
191             }
192              
193              
194             #------------------------------------------------------------------------
195             # max($r, $g, $b)
196             #
197             # Returns maximum value from arguments, used for colour space conversion.
198             #------------------------------------------------------------------------
199              
200             sub max {
201 33     33 0 43 my $self = shift;
202 33         32 my $max = shift;
203 33         45 foreach my $v (@_) {
204 66 100       134 $max = $v if $v > $max;
205             }
206 33         71 return $max;
207             }
208              
209              
210             1;
211              
212             __END__