File Coverage

blib/lib/Text/Sass/Functions.pm
Criterion Covered Total %
statement 126 130 96.9
branch 9 14 64.2
condition 2 2 100.0
subroutine 34 34 100.0
pod 25 25 100.0
total 196 205 95.6


line stmt bran cond sub pod time code
1             # -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*-
2             # vim:ts=8:sw=2:et:sta:sts=2
3             #########
4             # Author: bolav
5             # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $
6             # Id: $Id: Functions.pm 71 2012-09-12 08:42:30Z zerojinx $
7             # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/lib/Text/Sass/Functions.pm $
8             #
9             package Text::Sass::Functions;
10 28     28   138 use strict;
  28         52  
  28         781  
11 28     28   179 use warnings;
  28         45  
  28         734  
12 28     28   132 use Carp;
  28         46  
  28         1705  
13 28     28   21330 use Convert::Color;
  28         646926  
  28         2256  
14 28     28   1265 use Text::Sass::Expr;
  28         1163  
  28         708  
15 28     28   22847 use POSIX qw();
  28         200298  
  28         762  
16 28     28   188 use Readonly;
  28         47  
  28         54549  
17              
18             our $VERSION = q[1.0.3];
19             Readonly::Scalar my $PERC => 100;
20              
21             sub _color {
22 25     25   47 my ($self, $color) = @_;
23              
24 25         175 $color =~ s/[#](.)(.)(.)(\b)/#${1}${1}${2}${2}${3}${3}$4/smxgi;
25 25         85 $color = Text::Sass::Expr->units($color);
26              
27 25 50       82 if ($color->[1] eq q[#]) {
28 25         171 return Convert::Color->new(q[rgb8:].$color->[0]->[0].q[,].$color->[0]->[1].q[,].$color->[0]->[2]);
29             }
30 0         0 croak 'not a color '.$color;
31             }
32              
33             sub _value {
34 16     16   36 my ($self, $value) = @_;
35              
36 16         73 $value = Text::Sass::Expr->units($value);
37              
38 16 50       54 if ($value->[1] eq q[%]) {
    0          
39 16         62 return $value->[0] / $PERC;
40              
41             } elsif ($value->[1] eq q[]) {
42 0         0 return $value->[0];
43             }
44              
45 0         0 croak 'Unknown unit '.$value->[1].' for value';
46             }
47              
48             #########
49             # RGB Functions
50             #
51             sub rgb {
52 1     1 1 1721 my ($self, $r, $g, $b) = @_;
53              
54 1         14 my $cc = Convert::Color->new( "rgb8:$r,$g,$b" );
55              
56 1         16282 return q[#].$cc->as_rgb8->hex;
57             }
58              
59             # TODO: rgba
60              
61             sub red {
62 1     1 1 626 my ($self, $color) = @_;
63 1         5 return $self->_color($color)->as_rgb8->red;
64             }
65              
66             sub green {
67 1     1 1 537 my ($self, $color) = @_;
68 1         5 return $self->_color($color)->as_rgb8->green;
69             }
70              
71             sub blue {
72 1     1 1 538 my ($self, $color) = @_;
73 1         4 return $self->_color($color)->as_rgb8->blue;
74             }
75              
76             sub mix {
77 2     2 1 1150 my ($self, $c1, $c2, $w) = @_;
78              
79             # TODO: Weight not supported
80 2   100     11 $w ||= '50%';
81              
82 2         5 $c1 = $self->_color($c1);
83 2         79 $c2 = $self->_color($c2);
84 2         73 $w = $self->_value($w);
85 2         4 my $w2 = 1-$w;
86              
87 2         6 my $r = int(($c1->as_rgb8->red * $w) + ($c2->as_rgb8->red * $w2)) ;
88 2         61 my $g = int(($c1->as_rgb8->green * $w) + ($c2->as_rgb8->green * $w2)) ;
89 2         55 my $b = int(($c1->as_rgb8->blue * $w) + ($c2->as_rgb8->blue * $w2)) ;
90              
91 2         60 return q[#].Convert::Color->new("rgb8:$r,$g,$b")->hex;
92             }
93              
94             #########
95             # HSL functions
96             #
97             sub hsl {
98 1     1 1 530 my ($self, $h, $s, $l) = @_;
99              
100 1         9 $s = $self->_value($s);
101 1         4 $l = $self->_value($l);
102 1         19 my $cc = Convert::Color->new( "hsl:$h,$s,$l" );
103              
104 1         47 return q[#].$cc->as_rgb8->hex;
105             }
106              
107             # TODO: hsla
108              
109             sub hue {
110 1     1 1 596 my ($self, $color) = @_;
111 1         5 return $self->_color($color)->as_hsl->hue;
112             }
113              
114             sub saturation {
115 1     1 1 616 my ($self, $color) = @_;
116 1         4 return $self->_color($color)->as_hsl->saturation;
117             }
118              
119             sub lightness {
120 1     1 1 590 my ($self, $color) = @_;
121 1         4 return $self->_color($color)->as_hsl->lightness;
122             }
123              
124             sub adjust_hue {
125 3     3 1 680 my ($self, $color, $value) = @_;
126              
127 3         9 my $cc = $self->_color($color);
128 3         115 my $hsl = $cc->as_hsl;
129 3         230 my $new_hsl = Convert::Color->new( sprintf q[hsl:%s,%s,%s],
130             $hsl->hue+$value,
131             $hsl->saturation,
132             $hsl->lightness );
133              
134 3         143 return q[#].$new_hsl->as_rgb8->hex;
135             }
136              
137             sub lighten {
138 1     1 1 611 my ($self, $color, $value) = @_;
139              
140 1         4 $value = $self->_value($value);
141 1         4 my $cc = $self->_color($color);
142 1         39 my $hsl = $cc->as_hsl;
143 1         74 my $new_hsl = Convert::Color->new( sprintf q[hsl:%s,%s,%s],
144             $hsl->hue,
145             $hsl->saturation,
146             $hsl->lightness+$value );
147              
148 1         51 return q[#].$new_hsl->as_rgb8->hex;
149             }
150              
151             sub darken {
152 7     7 1 1168 my ($self, $color, $value) = @_;
153              
154 7         34 $value = $self->_value($value);
155 7         31 my $cc = $self->_color($color);
156 7         71721 my $hsl = $cc->as_hsl;
157 7         679 my $new_hsl = Convert::Color->new( sprintf q[hsl:%s,%s,%s],
158             $hsl->hue,
159             $hsl->saturation,
160             $hsl->lightness-$value );
161              
162 7         504 return q[#].$new_hsl->as_rgb8->hex;
163             }
164              
165             sub saturate {
166 1     1 1 566 my ($self, $color, $value) = @_;
167              
168 1         4 $value = $self->_value($value);
169 1         4 my $cc = $self->_color($color);
170 1         40 my $hsl = $cc->as_hsl;
171 1         73 my $new_hsl = Convert::Color->new( sprintf q[hsl:%s,%s,%s],
172             $hsl->hue,
173             $hsl->saturation+$value,
174             $hsl->lightness );
175              
176 1         52 return q[#].$new_hsl->as_rgb8->hex;
177             }
178              
179             sub desaturate {
180 3     3 1 654 my ($self, $color, $value) = @_;
181              
182 3         9 $value = $self->_value($value);
183 3         10 my $cc = $self->_color($color);
184 3         114 my $hsl = $cc->as_hsl;
185 3         240 my $sat = ($hsl->saturation-$value);
186              
187 3 100       16 if ($sat < 0) {
188 2         5 $sat = 0;
189             }
190              
191 3         10 my $new_hsl = Convert::Color->new( sprintf q[hsl:%s,%s,%s],
192             $hsl->hue,
193             $sat,
194             $hsl->lightness );
195              
196 3         143 return q[#].$new_hsl->as_rgb8->hex;
197             }
198              
199             sub grayscale {
200 1     1 1 579 my ($self, $color) = @_;
201              
202 1         5 return $self->desaturate($color, "$PERC%");
203             }
204              
205             sub complement {
206 1     1 1 583 my ($self, $color) = @_;
207              
208 1         6 Readonly::Scalar my $COMP_DEGREES => 180;
209 1         32 return $self->adjust_hue($color, $COMP_DEGREES);
210             }
211              
212             #########
213             # STRING Functions
214             #
215             sub unquote {
216 2     2 1 567 my ($self, $str) = @_;
217              
218 2         36 $str =~ s/^\"(.*)\"/$1/xms;
219 2         3 $str =~ s/^\'(.*)\'/$1/xms;
220              
221 2         10 return $str;
222             }
223              
224             sub quote {
225 4     4 1 8 my ($self, $str) = @_;
226              
227 4 100       20 if ($str =~ /^\"(.*)\"/xms) {
228 1         5 return $str;
229             }
230              
231 3 50       11 if ($str =~ /^\'(.*)\'/xms) {
232 0         0 return $str;
233             }
234              
235 3         13 return qq["$str"];
236             }
237              
238             # NUMBER functions
239              
240             sub percentage {
241 1     1 1 543 my ($self, $num) = @_;
242              
243 1         6 return ($num * $PERC) . q[%];
244             }
245              
246             sub round {
247 2     2 1 5 my ($self, $str) = @_;
248              
249 2         9 my $num = Text::Sass::Expr->units($str);
250 2         19 return sprintf q[%.0f%s], $num->[0], $num->[1];
251             }
252              
253             sub ceil {
254 2     2 1 5 my ($self, $str) = @_;
255              
256 2         7 my $num = Text::Sass::Expr->units($str);
257 2         37 return POSIX::ceil($num->[0]).$num->[1];
258             }
259              
260             sub floor {
261 3     3 1 8 my ($self, $str) = @_;
262              
263 3         10 my $num = Text::Sass::Expr->units($str);
264 3         54 return POSIX::floor($num->[0]).$num->[1];
265             }
266              
267             sub abs { ## no critic (Homonym)
268 2     2 1 679 my ($self, $str) = @_;
269 2         9 my $num = Text::Sass::Expr->units($str);
270              
271 2         33 return POSIX::abs($num->[0]).$num->[1];
272             }
273              
274             #########
275             # Introspective functions
276             #
277             sub unit {
278 3     3 1 486 my ($self, $str) = @_;
279              
280 3         11 my $num = Text::Sass::Expr->units($str);
281 3         24 return q["].$num->[1].q["];
282             }
283              
284             sub unitless {
285 2     2 1 6 my ($self, $str) = @_;
286              
287 2         7 my $num = Text::Sass::Expr->units($str);
288 2 100       13 return $num->[1] ? 0 : 1;
289             }
290              
291             1;
292              
293             __END__