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 29     29   97 use strict;
  29         36  
  29         673  
11 29     29   83 use warnings;
  29         29  
  29         522  
12 29     29   81 use Carp;
  29         25  
  29         1342  
13 29     29   11445 use Convert::Color;
  29         426150  
  29         977  
14 29     29   869 use Text::Sass::Expr;
  29         30  
  29         543  
15 29     29   12700 use POSIX qw();
  29         125738  
  29         632  
16 29     29   127 use Readonly;
  29         27  
  29         36747  
17              
18             our $VERSION = q[1.0.4];
19             Readonly::Scalar my $PERC => 100;
20              
21             sub _color {
22 25     25   27 my ($self, $color) = @_;
23              
24 25         121 $color =~ s/[#](.)(.)(.)(\b)/#${1}${1}${2}${2}${3}${3}$4/smxgi;
25 25         58 $color = Text::Sass::Expr->units($color);
26              
27 25 50       55 if ($color->[1] eq q[#]) {
28 25         125 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   20 my ($self, $value) = @_;
35              
36 16         46 $value = Text::Sass::Expr->units($value);
37              
38 16 50       36 if ($value->[1] eq q[%]) {
    0          
39 16         47 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 1239 my ($self, $r, $g, $b) = @_;
53              
54 1         10 my $cc = Convert::Color->new( "rgb8:$r,$g,$b" );
55              
56 1         9738 return q[#].$cc->as_rgb8->hex;
57             }
58              
59             # TODO: rgba
60              
61             sub red {
62 1     1 1 427 my ($self, $color) = @_;
63 1         3 return $self->_color($color)->as_rgb8->red;
64             }
65              
66             sub green {
67 1     1 1 393 my ($self, $color) = @_;
68 1         3 return $self->_color($color)->as_rgb8->green;
69             }
70              
71             sub blue {
72 1     1 1 380 my ($self, $color) = @_;
73 1         2 return $self->_color($color)->as_rgb8->blue;
74             }
75              
76             sub mix {
77 2     2 1 750 my ($self, $c1, $c2, $w) = @_;
78              
79             # TODO: Weight not supported
80 2   100     9 $w ||= '50%';
81              
82 2         5 $c1 = $self->_color($c1);
83 2         54 $c2 = $self->_color($c2);
84 2         45 $w = $self->_value($w);
85 2         3 my $w2 = 1-$w;
86              
87 2         6 my $r = int(($c1->as_rgb8->red * $w) + ($c2->as_rgb8->red * $w2)) ;
88 2         37 my $g = int(($c1->as_rgb8->green * $w) + ($c2->as_rgb8->green * $w2)) ;
89 2         33 my $b = int(($c1->as_rgb8->blue * $w) + ($c2->as_rgb8->blue * $w2)) ;
90              
91 2         39 return q[#].Convert::Color->new("rgb8:$r,$g,$b")->hex;
92             }
93              
94             #########
95             # HSL functions
96             #
97             sub hsl {
98 1     1 1 369 my ($self, $h, $s, $l) = @_;
99              
100 1         3 $s = $self->_value($s);
101 1         3 $l = $self->_value($l);
102 1         16 my $cc = Convert::Color->new( "hsl:$h,$s,$l" );
103              
104 1         32 return q[#].$cc->as_rgb8->hex;
105             }
106              
107             # TODO: hsla
108              
109             sub hue {
110 1     1 1 466 my ($self, $color) = @_;
111 1         3 return $self->_color($color)->as_hsl->hue;
112             }
113              
114             sub saturation {
115 1     1 1 459 my ($self, $color) = @_;
116 1         3 return $self->_color($color)->as_hsl->saturation;
117             }
118              
119             sub lightness {
120 1     1 1 417 my ($self, $color) = @_;
121 1         3 return $self->_color($color)->as_hsl->lightness;
122             }
123              
124             sub adjust_hue {
125 3     3 1 468 my ($self, $color, $value) = @_;
126              
127 3         7 my $cc = $self->_color($color);
128 3         77 my $hsl = $cc->as_hsl;
129 3         136 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         102 return q[#].$new_hsl->as_rgb8->hex;
135             }
136              
137             sub lighten {
138 1     1 1 394 my ($self, $color, $value) = @_;
139              
140 1         6 $value = $self->_value($value);
141 1         2 my $cc = $self->_color($color);
142 1         27 my $hsl = $cc->as_hsl;
143 1         48 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         36 return q[#].$new_hsl->as_rgb8->hex;
149             }
150              
151             sub darken {
152 7     7 1 807 my ($self, $color, $value) = @_;
153              
154 7         16 $value = $self->_value($value);
155 7         19 my $cc = $self->_color($color);
156 7         39984 my $hsl = $cc->as_hsl;
157 7         463 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         326 return q[#].$new_hsl->as_rgb8->hex;
163             }
164              
165             sub saturate {
166 1     1 1 396 my ($self, $color, $value) = @_;
167              
168 1         3 $value = $self->_value($value);
169 1         2 my $cc = $self->_color($color);
170 1         27 my $hsl = $cc->as_hsl;
171 1         47 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         37 return q[#].$new_hsl->as_rgb8->hex;
177             }
178              
179             sub desaturate {
180 3     3 1 521 my ($self, $color, $value) = @_;
181              
182 3         7 $value = $self->_value($value);
183 3         6 my $cc = $self->_color($color);
184 3         77 my $hsl = $cc->as_hsl;
185 3         137 my $sat = ($hsl->saturation-$value);
186              
187 3 100       11 if ($sat < 0) {
188 2         2 $sat = 0;
189             }
190              
191 3         5 my $new_hsl = Convert::Color->new( sprintf q[hsl:%s,%s,%s],
192             $hsl->hue,
193             $sat,
194             $hsl->lightness );
195              
196 3         101 return q[#].$new_hsl->as_rgb8->hex;
197             }
198              
199             sub grayscale {
200 1     1 1 401 my ($self, $color) = @_;
201              
202 1         4 return $self->desaturate($color, "$PERC%");
203             }
204              
205             sub complement {
206 1     1 1 406 my ($self, $color) = @_;
207              
208 1         6 Readonly::Scalar my $COMP_DEGREES => 180;
209 1         46 return $self->adjust_hue($color, $COMP_DEGREES);
210             }
211              
212             #########
213             # STRING Functions
214             #
215             sub unquote {
216 2     2 1 407 my ($self, $str) = @_;
217              
218 2         8 $str =~ s/^\"(.*)\"/$1/xms;
219 2         2 $str =~ s/^\'(.*)\'/$1/xms;
220              
221 2         6 return $str;
222             }
223              
224             sub quote {
225 4     4 1 5 my ($self, $str) = @_;
226              
227 4 100       13 if ($str =~ /^\"(.*)\"/xms) {
228 1         3 return $str;
229             }
230              
231 3 50       8 if ($str =~ /^\'(.*)\'/xms) {
232 0         0 return $str;
233             }
234              
235 3         12 return qq["$str"];
236             }
237              
238             # NUMBER functions
239              
240             sub percentage {
241 1     1 1 344 my ($self, $num) = @_;
242              
243 1         6 return ($num * $PERC) . q[%];
244             }
245              
246             sub round {
247 2     2 1 3 my ($self, $str) = @_;
248              
249 2         7 my $num = Text::Sass::Expr->units($str);
250 2         15 return sprintf q[%.0f%s], $num->[0], $num->[1];
251             }
252              
253             sub ceil {
254 2     2 1 3 my ($self, $str) = @_;
255              
256 2         6 my $num = Text::Sass::Expr->units($str);
257 2         31 return POSIX::ceil($num->[0]).$num->[1];
258             }
259              
260             sub floor {
261 3     3 1 5 my ($self, $str) = @_;
262              
263 3         8 my $num = Text::Sass::Expr->units($str);
264 3         40 return POSIX::floor($num->[0]).$num->[1];
265             }
266              
267             sub abs { ## no critic (Homonym)
268 2     2 1 496 my ($self, $str) = @_;
269 2         5 my $num = Text::Sass::Expr->units($str);
270              
271 2         32 return POSIX::abs($num->[0]).$num->[1];
272             }
273              
274             #########
275             # Introspective functions
276             #
277             sub unit {
278 3     3 1 340 my ($self, $str) = @_;
279              
280 3         9 my $num = Text::Sass::Expr->units($str);
281 3         13 return q["].$num->[1].q["];
282             }
283              
284             sub unitless {
285 2     2 1 3 my ($self, $str) = @_;
286              
287 2         6 my $num = Text::Sass::Expr->units($str);
288 2 100       10 return $num->[1] ? 0 : 1;
289             }
290              
291             1;
292              
293             __END__