File Coverage

lib/CSS/SpriteBuilder.pm
Criterion Covered Total %
statement 58 142 40.8
branch 7 50 14.0
condition n/a
subroutine 10 14 71.4
pod 6 6 100.0
total 81 212 38.2


line stmt bran cond sub pod time code
1             package CSS::SpriteBuilder;
2              
3 4     4   27755 use strict;
  4         8  
  4         152  
4 4     4   21 use warnings;
  4         7  
  4         122  
5 4     4   20 use File::Spec;
  4         12  
  4         122  
6 4     4   20 use Scalar::Util qw(openhandle);
  4         7  
  4         429  
7 4     4   1733 use CSS::SpriteBuilder::Constants;
  4         8  
  4         378  
8 4     4   1812 use CSS::SpriteBuilder::Sprite;
  4         11  
  4         6976  
9              
10             our $VERSION = '0.03';
11              
12             sub new {
13 3     3 1 2287 my ($class, @args) = @_;
14              
15 3         52 my $self = bless {
16             source_dir => undef,
17             output_dir => undef,
18              
19             image_quality => DEF_IMAGE_QUALITY,
20             max_image_size => DEF_MAX_IMAGE_SIZE,
21             max_image_width => DEF_MAX_IMAGE_WIDTH,
22             max_image_height => DEF_MAX_IMAGE_HEIGHT,
23             max_sprite_width => DEF_MAX_SPRITE_WIDTH,
24             max_sprite_height => DEF_MAX_SPRITE_HEIGHT,
25             margin => DEF_MARGIN,
26             transparent_color => undef,
27             is_background => 0,
28             layout => DEF_LAYOUT,
29             css_selector_prefix => DEF_CSS_SELECTOR_PREFIX,
30             css_url_prefix => '',
31             is_add_timestamp => 1,
32              
33             _sprites => {},
34              
35             @args,
36             }, $class;
37              
38 3         15 return $self;
39             }
40              
41             sub build {
42 3     3 1 32 my ($self, %args) = @_;
43              
44 3         5 my $sprites;
45 3 50       13 if ( my $config = delete $args{config} ) {
46 0         0 $sprites = $self->_parse_xml_config($config);
47             }
48             else {
49 3         8 $sprites = delete $args{sprites};
50             }
51              
52 3         6 foreach my $sprite_opts (@$sprites) {
53 3         7 my $images = delete $sprite_opts->{images};
54 3 50       23 my $output_file = $self->{output_dir}
55             ? File::Spec->catfile( $self->{output_dir}, delete $sprite_opts->{file} )
56             : delete $sprite_opts->{file}
57             ;
58              
59 42         79 my $sprite = CSS::SpriteBuilder::Sprite->new(
60 3         7 ( map { $_ => $self->{$_} } grep { exists $self->{$_} } @{ SPRITE_OPTS() } ),
  42         71  
  3         9  
61             %$sprite_opts,
62             source_images => $images,
63             target_file => $output_file,
64             );
65              
66 3         15 my $sprites = $sprite->build();
67 3         6 $self->{_sprites} = {%{ $self->{_sprites} }, %$sprites};
  3         58  
68             }
69              
70 3         11 return $self->{_sprites};
71             }
72              
73             sub get_sprites_info {
74 0     0 1 0 my ($self) = @_;
75 0         0 return $self->{_sprites};
76             }
77              
78             sub write_css {
79 1     1 1 539 my ($self, $filename) = @_;
80              
81 1         2 my ($fh, $str);
82              
83 1 50       3 if ($filename) {
84 0 0       0 if ( openhandle($filename) ) {
85 0         0 $fh = $filename;
86             }
87             else {
88 0 0       0 open($fh, '>', $filename) or die "Can't to open file '$filename'!";
89             }
90             }
91             else {
92 1         6 $str = '';
93 1 50   1   32 open($fh, '>', \$str) or die "Can't to create file handle!";
  1         10  
  1         2  
  1         6  
94             }
95              
96 1         1277 while (my ($sprite_image, $images) = each %{ $self->{_sprites} }) {
  2         12  
97 1         3 my @selectors = map { $_->{selector} } @$images;
  1         4  
98 1         8 print $fh sprintf(
99             "%s{background-image: url('%s') !important;}\n",
100             join(',', @selectors),
101             $sprite_image,
102             );
103              
104 1         2 foreach my $image_info (@$images) {
105 1         6 print $fh sprintf(
106             "%s{background-position:%dpx %dpx !important;",
107             $image_info->{selector},
108             -$image_info->{x},
109             -$image_info->{y},
110             );
111              
112 1 50       3 if ( $image_info->{repeat} ne 'no' ) {
113 0         0 print $fh sprintf(
114             "background-repeat:repeat-%s;",
115             $image_info->{repeat},
116             );
117             }
118              
119 1 50       4 unless ( $image_info->{is_background} ) {
120 1         4 print $fh sprintf(
121             "width:%dpx;height:%dpx;",
122             $image_info->{width},
123             $image_info->{height},
124             );
125             }
126              
127 1         4 print $fh "}\n";
128             }
129             }
130              
131 1 50       4 unless ($filename) {
132 1         3 close $fh;
133 1         4 return $str;
134             }
135              
136 0         0 return;
137             }
138              
139             sub write_xml {
140 0     0 1 0 my ($self, $filename) = @_;
141              
142 0         0 eval "require XML::LibXML";
143 0 0       0 die "XML::LibXML module is required!" if $@;
144              
145 0         0 my $dom = XML::LibXML::Document->new();
146 0         0 my $root_el = $dom->createElement('root');
147 0         0 $dom->setDocumentElement($root_el);
148              
149 0         0 while (my ($sprite_image, $images) = each %{ $self->{_sprites} }) {
  0         0  
150 0         0 my $sprite_el = $dom->createElement('sprite');
151 0         0 $root_el->appendChild($sprite_el);
152 0         0 $sprite_el->setAttribute('src', $sprite_image);
153              
154 0         0 foreach my $image (@$images) {
155 0         0 my $image_el = $dom->createElement('image');
156 0         0 $sprite_el->appendChild($image_el);
157 0         0 while (my ($key, $value) = each %$image) {
158 0         0 $image_el->setAttribute($key, $value);
159             }
160             }
161             }
162              
163 0 0       0 if ($filename) {
164 0 0       0 if ( openhandle($filename) ) {
165 0         0 return $dom->toFH($filename, 2);
166             }
167             else {
168 0         0 return $dom->toFile($filename, 2);
169             }
170             }
171              
172 0         0 return $dom->toString(2);
173             }
174              
175             sub write_html {
176 0     0 1 0 my ($self, $filename) = @_;
177              
178 0         0 my ($fh, $str);
179              
180 0 0       0 if ($filename) {
181 0 0       0 if ( openhandle($filename) ) {
182 0         0 $fh = $filename;
183             }
184             else {
185 0 0       0 open($fh, '>', $filename) or die "Can't to open file '$filename'!";
186             }
187             }
188             else {
189 0         0 $str = '';
190 0 0       0 open($fh, '>', \$str) or die "Can't to create file handle!";
191             }
192              
193 0         0 print $fh <
194            
195            
196            
197             CSS::SpriteBuilder generated page
198            
227            
228            
229            
230            

CSS::SpriteBuilder generated page

231            
232            
233            
234             Image
235             CSS selector
236             Sprite
237             Pos
238            
239            
240            
241             HTML
242              
243 0         0 while (my ($sprite_image, $images) = each %{ $self->{_sprites} }) {
  0         0  
244 0         0 for (my $i = 0; $i < scalar @$images; $i++) {
245 0         0 my $image_info = $images->[$i];
246 0         0 my $selector = $image_info->{selector};
247              
248 0 0       0 my $rule = $selector =~ /^#/
249             ? 'class="spr" id="'. substr($selector, 1) .'"'
250             : 'class="spr '. substr($selector, 1) .'"'
251             ;
252              
253 0 0       0 if ($image_info->{repeat} eq 'x') {
    0          
254 0         0 $rule .= ' style="width:'. $image_info->{width} * 3 .'px;"';
255             }
256             elsif ($image_info->{repeat} eq 'y') {
257 0         0 $rule .= ' style="height:'. $image_info->{height} * 3 .'px;"';
258             }
259              
260 0         0 print $fh <
261            
262            
263              
264             $image_info->{image}
265             $image_info->{width} x $image_info->{height} (repeat-$image_info->{repeat})
266            
267             $selector
268             HTML
269 0 0       0 if ($i == 0) {
270 0         0 my $rowspan = scalar @$images;
271 0         0 print $fh <
272            
273            
274             $sprite_image
275            
276             HTML
277             }
278              
279 0         0 print $fh <
280             $image_info->{x} x $image_info->{y}
281            
282             HTML
283             }
284             }
285              
286 0         0 print $fh <
287            
288            
289            
290            
291            
292             HTML
293              
294 0 0       0 unless ($filename) {
295 0         0 close $fh;
296 0         0 return $str;
297             }
298              
299 0         0 return;
300             }
301              
302             sub _parse_xml_config {
303 0     0   0 my ($self, $filename) = @_;
304              
305 0         0 eval "require XML::LibXML";
306 0 0       0 die "XML::LibXML module is required!" if $@;
307              
308 0         0 my $xml_parser = XML::LibXML->new();
309              
310 0         0 my $dom;
311 0 0       0 if ( openhandle($filename) ) {
    0          
312 0         0 $dom = $xml_parser->parse_fh($filename);
313             }
314             elsif ( $filename =~ /^
315 0         0 $dom = $xml_parser->parse_string($filename);
316             }
317             else {
318 0         0 $dom = $xml_parser->parse_file($filename);
319             }
320              
321 0         0 my %global_opts = (
322 0         0 ( map { $_ => $self->{$_} } grep { exists $self->{$_} } @{ SPRITE_OPTS() } ),
  0         0  
  0         0  
323 0         0 ( map { $_->nodeName() => $_->textContent() } $dom->findnodes("/root/global_opts/*") ),
324             );
325              
326 0         0 my @sprites;
327 0         0 foreach my $sprite_node ( $dom->findnodes("/root/sprites/sprite") ) {
328 0         0 my %sprite_opts = (
329             %global_opts,
330 0         0 map { $_->nodeName() => $_->textContent() } $sprite_node->findnodes("@*"),
331             );
332              
333 0         0 my @images = map +{
334 0         0 ( map { $_ => $sprite_opts{$_} } grep { exists $sprite_opts{$_} } @{ IMAGE_OPTS() } ),
  0         0  
  0         0  
335 0         0 ( map { $_->nodeName() => $_->textContent() } $_->findnodes("@*") ),
336             }, $sprite_node->findnodes('image');
337              
338 0         0 push @sprites, {
339             %sprite_opts,
340             images => \@images,
341             };
342             }
343              
344 0 0       0 return wantarray ? @sprites : \@sprites;
345             }
346              
347             1;
348             __END__