File Coverage

blib/lib/Text/Sass/Functions.pm
Criterion Covered Total %
statement 131 135 97.0
branch 10 16 62.5
condition 2 2 100.0
subroutine 35 35 100.0
pod 26 26 100.0
total 204 214 95.3


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 24     24   120 use strict;
  24         38  
  24         678  
11 24     24   114 use warnings;
  24         38  
  24         584  
12 24     24   113 use Carp;
  24         38  
  24         1326  
13 24     24   18001 use Convert::Color;
  24         543951  
  24         927  
14 24     24   2301 use Text::Sass::Expr;
  24         1126  
  24         1624  
15 24     24   20502 use POSIX qw();
  24         174103  
  24         653  
16 24     24   152 use Readonly;
  24         44  
  24         48012  
17              
18             our $VERSION = q[1.0.0];
19             Readonly::Scalar my $PERC => 100;
20              
21             sub new {
22 133     133 1 788 my ($class, $ref) = @_;
23              
24 133 50       326 if(!$ref) {
25 133         218 $ref = {};
26             }
27              
28 133         227 bless $ref, $class;
29 133         339 return $ref;
30             }
31              
32             sub _color {
33 22     22   36 my ($self, $color) = @_;
34              
35 22         137 $color =~ s/[#](.)(.)(.)(\b)/#${1}${1}${2}${2}${3}${3}$4/smxgi;
36 22         80 $color = Text::Sass::Expr->units($color);
37              
38 22 50       80 if ($color->[1] eq q[#]) {
39 22         137 return Convert::Color->new(q[rgb8:].$color->[0]->[0].q[,].$color->[0]->[1].q[,].$color->[0]->[2]);
40             }
41 0         0 croak 'not a color '.$color;
42             }
43              
44             sub _value {
45 13     13   25 my ($self, $value) = @_;
46              
47 13         53 $value = Text::Sass::Expr->units($value);
48              
49 13 50       41 if ($value->[1] eq q[%]) {
    0          
50 13         54 return $value->[0] / $PERC;
51              
52             } elsif ($value->[1] eq q[]) {
53 0         0 return $value->[0];
54             }
55              
56 0         0 croak 'Unknown unit '.$value->[1].' for value';
57             }
58              
59             #########
60             # RGB Functions
61             #
62             sub rgb {
63 1     1 1 564 my ($self, $r, $g, $b) = @_;
64              
65 1         12 my $cc = Convert::Color->new( "rgb8:$r,$g,$b" );
66              
67 1         51472 return q[#].$cc->as_rgb8->hex;
68             }
69              
70             # TODO: rgba
71              
72             sub red {
73 1     1 1 555 my ($self, $color) = @_;
74 1         5 return $self->_color($color)->as_rgb8->red;
75             }
76              
77             sub green {
78 1     1 1 401 my ($self, $color) = @_;
79 1         5 return $self->_color($color)->as_rgb8->green;
80             }
81              
82             sub blue {
83 1     1 1 403 my ($self, $color) = @_;
84 1         3 return $self->_color($color)->as_rgb8->blue;
85             }
86              
87             sub mix {
88 2     2 1 918 my ($self, $c1, $c2, $w) = @_;
89              
90             # TODO: Weight not supported
91 2   100     11 $w ||= '50%';
92              
93 2         6 $c1 = $self->_color($c1);
94 2         78 $c2 = $self->_color($c2);
95 2         73 $w = $self->_value($w);
96 2         6 my $w2 = 1-$w;
97              
98 2         6 my $r = int(($c1->as_rgb8->red * $w) + ($c2->as_rgb8->red * $w2)) ;
99 2         64 my $g = int(($c1->as_rgb8->green * $w) + ($c2->as_rgb8->green * $w2)) ;
100 2         57 my $b = int(($c1->as_rgb8->blue * $w) + ($c2->as_rgb8->blue * $w2)) ;
101              
102 2         60 return q[#].Convert::Color->new("rgb8:$r,$g,$b")->hex;
103             }
104              
105             #########
106             # HSL functions
107             #
108             sub hsl {
109 1     1 1 422 my ($self, $h, $s, $l) = @_;
110              
111 1         3 $s = $self->_value($s);
112 1         4 $l = $self->_value($l);
113 1         23 my $cc = Convert::Color->new( "hsl:$h,$s,$l" );
114              
115 1         56 return q[#].$cc->as_rgb8->hex;
116             }
117              
118             # TODO: hsla
119              
120             sub hue {
121 1     1 1 512 my ($self, $color) = @_;
122 1         4 return $self->_color($color)->as_hsl->hue;
123             }
124              
125             sub saturation {
126 1     1 1 510 my ($self, $color) = @_;
127 1         11 return $self->_color($color)->as_hsl->saturation;
128             }
129              
130             sub lightness {
131 1     1 1 483 my ($self, $color) = @_;
132 1         4 return $self->_color($color)->as_hsl->lightness;
133             }
134              
135             sub adjust_hue {
136 3     3 1 644 my ($self, $color, $value) = @_;
137              
138 3         9 my $cc = $self->_color($color);
139 3         117 my $hsl = $cc->as_hsl;
140 3         225 my $new_hsl = Convert::Color->new( sprintf q[hsl:%s,%s,%s],
141             $hsl->hue+$value,
142             $hsl->saturation,
143             $hsl->lightness );
144              
145 3         144 return q[#].$new_hsl->as_rgb8->hex;
146             }
147              
148             sub lighten {
149 1     1 1 452 my ($self, $color, $value) = @_;
150              
151 1         4 $value = $self->_value($value);
152 1         4 my $cc = $self->_color($color);
153 1         40 my $hsl = $cc->as_hsl;
154 1         72 my $new_hsl = Convert::Color->new( sprintf q[hsl:%s,%s,%s],
155             $hsl->hue,
156             $hsl->saturation,
157             $hsl->lightness+$value );
158              
159 1         64 return q[#].$new_hsl->as_rgb8->hex;
160             }
161              
162             sub darken {
163 4     4 1 956 my ($self, $color, $value) = @_;
164              
165 4         14 $value = $self->_value($value);
166 4         12 my $cc = $self->_color($color);
167 4         31857 my $hsl = $cc->as_hsl;
168 4         377 my $new_hsl = Convert::Color->new( sprintf q[hsl:%s,%s,%s],
169             $hsl->hue,
170             $hsl->saturation,
171             $hsl->lightness-$value );
172              
173 4         253 return q[#].$new_hsl->as_rgb8->hex;
174             }
175              
176             sub saturate {
177 1     1 1 455 my ($self, $color, $value) = @_;
178              
179 1         3 $value = $self->_value($value);
180 1         3 my $cc = $self->_color($color);
181 1         41 my $hsl = $cc->as_hsl;
182 1         92 my $new_hsl = Convert::Color->new( sprintf q[hsl:%s,%s,%s],
183             $hsl->hue,
184             $hsl->saturation+$value,
185             $hsl->lightness );
186              
187 1         54 return q[#].$new_hsl->as_rgb8->hex;
188             }
189              
190             sub desaturate {
191 3     3 1 545 my ($self, $color, $value) = @_;
192              
193 3         9 $value = $self->_value($value);
194 3         8 my $cc = $self->_color($color);
195 3         114 my $hsl = $cc->as_hsl;
196 3         215 my $sat = ($hsl->saturation-$value);
197              
198 3 100       17 if ($sat < 0) {
199 2         3 $sat = 0;
200             }
201              
202 3         10 my $new_hsl = Convert::Color->new( sprintf q[hsl:%s,%s,%s],
203             $hsl->hue,
204             $sat,
205             $hsl->lightness );
206              
207 3         139 return q[#].$new_hsl->as_rgb8->hex;
208             }
209              
210             sub grayscale {
211 1     1 1 519 my ($self, $color) = @_;
212              
213 1         6 return $self->desaturate($color, "$PERC%");
214             }
215              
216             sub complement {
217 1     1 1 489 my ($self, $color) = @_;
218              
219 1         8 Readonly::Scalar my $COMP_DEGREES => 180;
220 1         30 return $self->adjust_hue($color, $COMP_DEGREES);
221             }
222              
223             #########
224             # STRING Functions
225             #
226             sub unquote {
227 2     2 1 477 my ($self, $str) = @_;
228              
229 2         7 $str =~ s/^\"(.*)\"/$1/xms;
230 2         5 $str =~ s/^\'(.*)\'/$1/xms;
231              
232 2         9 return $str;
233             }
234              
235             sub quote {
236 2     2 1 6 my ($self, $str) = @_;
237              
238 2 100       11 if ($str =~ /^\"(.*)\"/xms) {
239 1         6 return $str;
240             }
241              
242 1 50       5 if ($str =~ /^\'(.*)\'/xms) {
243 0         0 return $str;
244             }
245              
246 1         5 return qq["$str"];
247             }
248              
249             # NUMBER functions
250              
251             sub percentage {
252 1     1 1 365 my ($self, $num) = @_;
253              
254 1         5 return ($num * $PERC) . q[%];
255             }
256              
257              
258             sub round {
259 2     2 1 4 my ($self, $str) = @_;
260              
261 2         8 my $num = Text::Sass::Expr->units($str);
262 2         18 return sprintf q[%.0f%s], $num->[0], $num->[1];
263             }
264              
265             sub ceil {
266 2     2 1 6 my ($self, $str) = @_;
267              
268 2         8 my $num = Text::Sass::Expr->units($str);
269 2         40 return POSIX::ceil($num->[0]).$num->[1];
270             }
271              
272             sub floor {
273 2     2 1 4 my ($self, $str) = @_;
274              
275 2         8 my $num = Text::Sass::Expr->units($str);
276 2         23 return POSIX::floor($num->[0]).$num->[1];
277             }
278              
279             sub abs { ## no critic (Homonym)
280 2     2 1 582 my ($self, $str) = @_;
281 2         8 my $num = Text::Sass::Expr->units($str);
282              
283 2         32 return POSIX::abs($num->[0]).$num->[1];
284             }
285              
286             #########
287             # Introspective functions
288             #
289             sub unit {
290 3     3 1 370 my ($self, $str) = @_;
291              
292 3         10 my $num = Text::Sass::Expr->units($str);
293 3         17 return q["].$num->[1].q["];
294             }
295              
296             sub unitless {
297 2     2 1 6 my ($self, $str) = @_;
298              
299 2         7 my $num = Text::Sass::Expr->units($str);
300 2 100       14 return $num->[1] ? 0 : 1;
301             }
302              
303             1;
304              
305             __END__