File Coverage

blib/lib/SMIL/Layout.pm
Criterion Covered Total %
statement 44 124 35.4
branch 10 86 11.6
condition 2 57 3.5
subroutine 7 11 63.6
pod 0 6 0.0
total 63 284 22.1


line stmt bran cond sub pod time code
1             package SMIL::Layout;
2              
3             my $debug = 1;
4              
5             $VERSION = "0.898";
6              
7 1     1   7 use SMIL::XMLContainer;
  1         2  
  1         31  
8 1     1   677 use SMIL::RootLayout;
  1         3  
  1         31  
9 1     1   1217 use SMIL::Region;
  1         4  
  1         35  
10 1     1   6 use SMIL::SystemSwitches;
  1         2  
  1         241  
11              
12             @ISA = qw( SMIL::XMLContainer );
13              
14 1     1   7 use Carp;
  1         2  
  1         2545  
15             my $regions = "regions";
16             my $module_defined_src = "sm-src";
17             my $module_defined_align = "sm-align";
18             my $left_offset = "sm-left-offset";
19             my $top_offset = "sm-top-offset";
20             my $switch_target = "switch-target";
21             my @rootLayoutAttributes = ( 'height', 'width', 'background-color' );
22             my @layoutAttributes = @systemSwitchAttributes;
23              
24             my $CENTER = 'center';
25             my $LEFT = 'left';
26             my $RIGHT = 'right';
27              
28             my $root_layout = "root-layout";
29              
30             sub getRootHeight {
31 0     0 0 0 my $self = shift;
32 0         0 my $rl = $self->getContentObjectByName( $root_layout );
33 0 0       0 return $rl ? $rl->getRootHeight() : 0;
34             }
35              
36             sub getRootWidth {
37 0     0 0 0 my $self = shift;
38 0         0 my $rl = $self->getContentObjectByName( $root_layout );
39 0 0       0 return $rl ? $rl->getRootWidth() : 0;
40             }
41              
42             sub init {
43 1     1 0 3 my $self = shift;
44 1         8 $self->SUPER::init( "layout" );
45 1         4 my %hash = @_;
46              
47 1 50       6 if( $hash{ $switch_target } ) {
48 0         0 $self->setAttributes( $hash{ $switch_target } =>
49             $hash{ $hash{ $switch_target } } );
50             }
51              
52 1         12 my %layoutAttrs = $self->createValidAttributes( { %hash },
53             [ @layoutAttributes ] );
54              
55 1         11 $self->setAttributes( %layoutAttrs );
56              
57             # Grab height and width from the hash if we don't have root-layout
58 1         2 my %rootLayoutAttrs;
59 1 50       5 if( !$hash{ root_layout } ) {
60 1         17 %rootLayoutAttrs =
61             $self->createValidAttributes( { %hash },
62             [@rootLayoutAttributes] );
63             }
64             else {
65 0         0 my $rl_hash = $hash{ root_layout };
66 0         0 %rootLayoutAttrs =
67             $self->createValidAttributes( { %$rl_hash },
68             [@rootLayoutAttributes] );
69             }
70              
71 1         21 $self->{$root_layout} = new SMIL::RootLayout;
72 1         9 $self->{$root_layout}->setAttributes( %rootLayoutAttrs );
73 1         10 $self->setTagContents( $root_layout => $self->{$root_layout} );
74             }
75              
76             my $name = 'name';
77             my $id = "id";
78             my @regionAttributes = ( $id, 'top', 'left', 'height', 'width', "fit",
79             'z-index', 'background-color', );
80              
81             sub process_for_size {
82 0     0 0 0 my $type = shift;
83 0         0 my $content = shift;
84 0         0 my( $height, $width );
85              
86 0 0 0     0 if( $type =~ /gif/i || $content =~ /^GIF/ ) {
    0 0        
    0 0        
    0          
87 0 0       0 my $string = $1 if $content =~ /GIF.{3}(.{4})/;
88 0         0 @stuff = unpack "SS", $string;
89 0         0 $height = $stuff[ 1 ];
90 0         0 $width = $stuff[ 0 ];
91             }
92             elsif( $type =~ /jpe?g/i ) {
93 0         0 warn "JPEG images unsupported for region dimension calculation.";
94             }
95             elsif( $type eq "rt" || $type =~ /rn-realtext/ ) {
96 0 0       0 ( $height, $width ) = ( $1, $2 )
97             if $content =~ /]*height="(\d*)"[^>]*?width="(\d*)"/;
98 0 0 0     0 ( $height, $width ) = ( $2, $1 )
      0        
99             if ( !$height and !$width ) and
100             $content =~ /]*width="(\d*)"[^>]*?height="(\d*)"/;
101 0 0 0     0 die "Couldn't find height and width in RealText file."
102             unless $height and $width;
103             }
104             elsif( $type eq "rp" || $type =~ /rn-realpix/ ) {
105 0 0       0 ( $height, $width ) = ( $1, $2 )
106             if $content =~ /]*height="(\d*)"[^>]*?width="(\d*)"/;
107 0 0 0     0 ( $height, $width ) = ( $2, $1 )
      0        
108             if ( !$height and !$width ) and
109             $content =~ /]*width="(\d*)"[^>]*?height="(\d*)"/;
110 0 0 0     0 die "Couldn't find height and width in RealText file."
111             unless $height and $width;
112             }
113              
114 0         0 return( $height, $width );
115             }
116              
117             sub getRegion
118             {
119 0     0 0 0 my $self;
120 0         0 $self = shift;
121 0         0 my $region_name;
122 0         0 $region_name = shift;
123 0         0 my $the_regions;
124 0         0 $the_regions = $self->getContentObjectByName( $regions );
125 0 0 0     0 if( !( $the_regions && @$the_regions ) ) {
126 0         0 $the_regions = [];
127 0         0 $self->setTagContents( $regions => $the_regions );
128             }
129 0         0 my $return_region;
130 0 0 0     0 if( $the_regions and @{$the_regions} ) {
  0         0  
131 0         0 foreach my $the_region ( @{$the_regions} ) {
  0         0  
132 0 0 0     0 if( $the_region and
      0        
133             ( $region_name eq $the_region->getAttributeValue( 'id' )
134             or $region_name eq $the_region->getAttributeValue( 'name' ) ) ) {
135 0         0 $return_region = $the_region;
136             }
137             }
138             }
139 0         0 return $return_region;
140             }
141              
142             sub addRegion {
143 2     2 0 5 my $self = shift;
144 2         10 my %hash = @_;
145              
146             # Now, set up the new SMIL::region
147            
148             # If they used "name" instead of "id" fix that
149 2 50       9 $hash{ $id } = $hash{ $name } if $hash{ $name };
150            
151             # If they specified the src inside the region, then
152             # figure out the dimensions from the src file
153 2 50       13 if( $hash{ $module_defined_src } ) {
154 0         0 my $ref = $hash{ $module_defined_src };
155 0         0 my $content;
156             my $type;
157            
158             # If a http ref, if we have LWP installed use it to
159             # get the image and determine the dimensions
160 0 0       0 if( $ref =~ /^http/ ) {
161 0         0 eval 'use LWP::Simple;';
162 0         0 my $lwp_installed = !$@;
163            
164 0 0       0 if( $lwp_installed ) {
165 0         0 $content = LWP::Simple::get $ref;
166            
167             # Also, get the type if possible
168 0         0 $type = head( $ref );
169             }
170             else {
171 0         0 die "LWP not installed.\nYou may not use http sources" .
172             " in your region definitions.\nSmil.pm cannot " .
173             "connect and determine file size without LWP\n";
174             }
175             }
176             else {
177             # Ok, hope it is local to the script.
178 0 0       0 if( open FILE, $ref ) {
179 0         0 binmode FILE;
180 0         0 undef $/;
181 0         0 $content = ;
182 0         0 close FILE;
183             }
184             else {
185 0         0 die "Couldn't find the file $ref.\n" .
186             "Make sure that $ref is relative to the script.\n" .
187             "Using src to define a region does not set the\n".
188             "src for the SMIL file but is used to " .
189             "determine\nfile size.\n";
190             }
191            
192             # Determine the type from the extension
193 0 0       0 $type = "\L$1" if $ref =~ /\.(\w*)$/;
194             }
195            
196 0 0       0 if( $content ) {
197             # Figure out what the size is
198 0         0 ( $height, $width ) = process_for_size( $type, $content );
199            
200 0 0 0     0 if( $height && $width ) {
201             # Always respect what users set.
202 0 0       0 $hash{ height } = $height unless defined( $hash{ height } );
203 0 0       0 $hash{ width } = $width unless defined( $hash{ width } );
204             }
205             }
206             }
207            
208             # Now, if we have some formatting in the "sm-align" attribute
209             # figure out the top or left.
210 2 50       6 if( $hash{ $module_defined_align } ) {
211             # Get the root layout object
212 0         0 my $ht = $self->getRootHeight();
213 0         0 my $wh = $self->getRootWidth();
214            
215             # Calculate the top and left unless they are set already
216             die "Need height to calculate alignment."
217 0 0       0 unless defined( $hash{ height } );
218 0 0 0     0 if( 'middle' eq $hash{ $module_defined_align } and
219             !defined( $hash{ top } ) ) {
220             # Figure out where to put this item
221             # Get the total size / 2 minus the item size / 2
222 0         0 $hash{ top } = int( ( $ht / 2 ) - ( $hash{ height } / 2 ) );
223             }
224            
225             die "Need width to calculate alignment. "
226 0 0       0 unless defined( $hash{ width } );
227 0 0       0 if( !defined( $hash{ left } ) ) {
228 0 0       0 if( $hash{ $module_defined_align } =~ /center/i ) {
    0          
    0          
229             # Get the total size / 2 minus the item size / 2
230 0         0 $hash{ left } = int( ( $wh / 2 ) - ( $hash{ width } / 2 ) );
231             }
232             elsif( $hash{ $module_defined_align } =~ /right/i ) {
233             # Get the width - size of the element
234 0         0 $hash{ left } = $wh - $hash{ width };
235             }
236             elsif( $hash{ $module_defined_align } =~ /left/i ) {
237             # easy enough...
238 0         0 $hash{ left } = 0;
239             }
240             }
241              
242 0 0 0     0 if( defined( $hash{ left } ) && defined( $hash{ $left_offset } ) ) {
243 0         0 $hash{ left } += $hash{ $left_offset };
244             }
245            
246 0 0 0     0 if( defined( $hash{ top } ) && defined( $hash{ $top_offset } ) ) {
247 0         0 $hash{ top } += $hash{ $top_offset };
248             }
249             }
250            
251 2         20 my %attrs = $self->createValidAttributes( { %hash },
252             [@regionAttributes] );
253 2         11 $ZERO_STRING = "ZERO_STRING";
254 2         14 my $region = new SMIL::Region;
255 2         165 $region->setAttributes( %attrs );
256 2 50       8 $region->setAttribute( 'top' => $ZERO_STRING ) unless $hash{ 'top' };
257 2 50       91 $region->setAttribute( 'left' => $ZERO_STRING ) unless $hash{ 'left' };
258            
259 2         12 my $current_regions = $self->getContentObjectByName( $regions );
260            
261 2 100 66     14 if( !( $current_regions && @$current_regions ) ) {
262 1         2 $current_regions = [];
263             }
264            
265             # If error checking is set to true, check to see if the new
266             # region has the same name as a previously existing region
267 2 50       6 if( $check_errors ) {
268 0         0 foreach $reg ( @$current_regions ) {
269 0 0 0     0 croak "Region \"" . $attrs{ $id } .
270             "\" has the same name as another existing region"
271             if $attrs{ $id } &&
272             $reg->getAttribute( $id ) eq $attrs{ $id };
273             }
274             }
275            
276 2         3 push @$current_regions, $region;
277 2         7 $self->setTagContents( $regions => $current_regions );
278             }
279              
280              
281              
282              
283              
284