File Coverage

blib/lib/SWF/Builder.pm
Criterion Covered Total %
statement 141 214 65.8
branch 5 14 35.7
condition 5 13 38.4
subroutine 33 53 62.2
pod 1 1 100.0
total 185 295 62.7


line stmt bran cond sub pod time code
1             package SWF::Builder;
2            
3 1     1   6695 use strict;
  1         3  
  1         38  
4            
5 1     1   935 use SWF::File;
  1         124717  
  1         31  
6 1     1   12 use SWF::Element;
  1         2  
  1         23  
7 1     1   631 use SWF::Builder::ExElement;
  1         3  
  1         75  
8 1     1   714 use SWF::Builder::Character;
  1         3  
  1         28  
9            
10 1     1   7 use Carp;
  1         1  
  1         285  
11            
12             our $VERSION = '0.16';
13             my $SFTAG = SWF::Element::Tag::ShowFrame->new;
14            
15             sub new {
16 1     1 1 105 my $class = shift;
17 1         11 my $self = bless {
18             _root =>
19             SWF::Builder::Movie::Root->new(@_)
20             }, $class;
21 1         3 $self;
22             }
23            
24             sub AUTOLOAD {
25 3     3   78 my $self = shift;
26 3         8 my $sub = $SWF::Builder::AUTOLOAD;
27            
28 3 50       11 return if $sub =~/::DESTROY$/;
29 3         17 $sub =~ s/.+:://;
30 3 50       29 croak "Can't locate object method \"$sub\" via package \"".ref($self).'" (perhaps you forgot to load "'.ref($self).'"?)' unless $self->{_root}->can($sub);
31 3         12 $self->{_root}->$sub(@_);
32             }
33            
34             sub DESTROY {
35 1     1   3682 my $r = shift->{_root};
36 1 50       11 $r->_destroy if defined $r;
37             }
38            
39             ####
40            
41             package SWF::Builder::Depth;
42 1     1   5 use Carp;
  1         1  
  1         306  
43            
44             sub new {
45 5     5   15 my ($class, $parent, $lower) = @_;
46 5         43 my $self = bless {
47             _parent => $parent,
48             _depth => SWF::Element::Depth->new,
49             }, $class;
50 5   66     93 $lower ||= $self;
51 5         13 $self->{_lower} = $lower;
52 5   66     26 $self->{_upper} = $lower->{_upper}||$lower;
53 5         12 $lower->{_upper} = $lower->{_upper}{_lower} = $self;
54 5         31 return $self;
55             }
56            
57             sub set_depth {
58 3     3   15 my ($self, $n) = @_;
59            
60 3         29 $self->{_depth}->configure($n);
61 3         124 $n+1;
62             }
63            
64             sub _destroy {
65 2     2   4 my $self = shift;
66 2         10 while(my $lower = $self->{_lower}) {
67 5         26 %$self = ();
68 5         20 $self = $lower;
69             }
70             }
71            
72            
73             ####
74            
75             package SWF::Builder::_FrameList;
76            
77             @SWF::Builder::_FrameList::ISA = qw/ SWF::Element::Array::TAGARRAY /;
78            
79             sub pack {
80 2     2   15 my ($self, $stream) = @_;
81            
82 2         6 for my $frame (@$self) {
83 2         6 for my $tag (@$frame) {
84 4         983 $tag->pack($stream);
85             }
86 2         2949 $SFTAG->pack($stream);
87             }
88 2         372 SWF::Element::Tag::End->new->pack($stream);
89             }
90            
91             ####
92            
93             package SWF::Builder::Movie;
94            
95 1     1   6 use Carp;
  1         1  
  1         59  
96 1     1   5 use SWF::Builder::ExElement;
  1         16  
  1         1046  
97            
98             sub new {
99 2     2   5 my $class = shift;
100            
101 2         28 my $self = bless {
102             _frame_list => SWF::Builder::_FrameList->new,
103             _streamsoundf => 0,
104             }, $class;
105 2         66 $self->{_depth_list} = SWF::Builder::Depth->new($self);
106            
107 2         6 $self;
108             }
109            
110             sub new_shape {
111 1     1   864 require SWF::Builder::Character::Shape;
112            
113 1         9 shift->_new_character(SWF::Builder::Character::Shape::Def->new);
114             }
115            
116             sub new_static_text {
117 1     1   1023 require SWF::Builder::Character::Text;
118            
119 1         10 shift->_new_character(SWF::Builder::Character::Text::Def->new(@_));
120             }
121            
122             *new_text = \&new_static_text;
123            
124             sub new_dynamic_text {
125 0     0   0 require SWF::Builder::Character::EditText;
126 0         0 my $s =shift;
127 0         0 my $q = SWF::Builder::Character::DynamicText->new(@_);
128 0         0 $s->_new_character($q);
129             }
130            
131            
132             sub new_edit_text {
133 0     0   0 require SWF::Builder::Character::EditText;
134            
135 0         0 shift->_new_character(SWF::Builder::Character::EditText::Def->new(@_));
136             }
137            
138            
139             sub new_html_text {
140 0     0   0 require SWF::Builder::Character::EditText;
141            
142 0         0 shift->_new_character(SWF::Builder::Character::HTMLText->new(@_));
143             }
144            
145             sub new_text_area {
146 0     0   0 require SWF::Builder::Character::EditText;
147            
148 0         0 shift->_new_character(SWF::Builder::Character::TextArea->new(@_));
149             }
150            
151             sub new_input_field {
152 0     0   0 require SWF::Builder::Character::EditText;
153            
154 0         0 shift->_new_character(SWF::Builder::Character::InputField->new(@_));
155             }
156            
157             sub new_password_field {
158 0     0   0 require SWF::Builder::Character::EditText;
159            
160 0         0 shift->_new_character(SWF::Builder::Character::PasswordField->new(@_));
161             }
162            
163             sub new_font {
164 1     1   792 require SWF::Builder::Character::Font;
165            
166 1         11 shift->_new_character(SWF::Builder::Character::Font::Def->new(@_));
167             }
168            
169             sub new_movie_clip {
170 1     1   696 require SWF::Builder::Character::MovieClip;
171            
172 1         10 shift->_new_character(SWF::Builder::Character::MovieClip::Def->new);
173             }
174            
175             *new_mc = \&new_movie_clip;
176            
177             sub new_gradient {
178 1     1   995 require SWF::Builder::Gradient;
179            
180 1         10 SWF::Builder::Gradient->new;
181             }
182            
183             sub new_jpeg {
184 0     0   0 require SWF::Builder::Character::Bitmap;
185            
186 0         0 my $self = shift;
187            
188 0 0       0 unshift @_, 'JPEGFile' if @_==1;
189 0         0 $self->_new_character(SWF::Builder::Character::Bitmap::JPEG->new(@_));
190             }
191            
192             sub new_bitmap {
193 0     0   0 require SWF::Builder::Character::Bitmap;
194            
195 0         0 my $self = shift;
196            
197 0         0 $self->_new_character(SWF::Builder::Character::Bitmap::Lossless->new(@_));
198             }
199            
200             sub new_sound {
201 0     0   0 require SWF::Builder::Character::Sound;
202            
203 0         0 my $self = shift;
204            
205 0         0 $self->_new_character(SWF::Builder::Character::Sound::Def->new(@_));
206             }
207            
208             sub import_asset {
209 0     0   0 my $self = shift;
210            
211 0         0 my $i = $self->_new_character(SWF::Builder::Character::Imported->new(@_));
212 0         0 $self->_depends($i, 1); # set 'depend' flag by force because imported assets may be used only by ActionScript.
213 0         0 $i;
214             }
215            
216             #sub shape_tween {
217             # require SWF::Builder::Character::MorphShape;
218             #
219             # my $self = shift;
220             #
221             # $self->_new_character(SWF::Builder::Character::MorphShape->shape_tween(@_));
222             #}
223            
224             sub _new_character {
225 4     4   10 my ($parent, $self) = @_;
226            
227 4         5 push @{$parent->{_root}{_character_IDs}}, $self->{ID};
  4         22  
228 4         6 push @{$parent->{_root}{_to_destroy}}, $self;
  4         10  
229 4         9 $self->{_parent} = $parent;
230 4         10 $self->{_root} = $parent->{_root};
231            
232 4         20 return $self;
233             }
234            
235            
236             sub frame_action {
237 0     0   0 require SWF::Builder::ActionScript;
238            
239 0         0 my ($self, $frame) = @_;
240            
241 0         0 my $tag = SWF::Element::Tag::DoAction->new;
242 0         0 push @{$self->{_frame_list}[$frame-1]}, $tag;
  0         0  
243 0         0 my $action = SWF::Builder::ActionScript->new(Version => $self->{_root}{_version});
244 0         0 $tag->Actions($action->{_actions});
245 0         0 return $action;
246             }
247            
248             sub frame_label {
249 0     0   0 my ($self, $frame, $label, $anchor) = @_;
250            
251 0         0 utf2bin($label);
252 0         0 push @{$self->{_frame_list}[$frame-1]}, SWF::Element::Tag::FrameLabel->new(Name => $label, NamedAnchorFlag => $anchor);
  0         0  
253             }
254            
255            
256             sub set_depth {
257 2     2   5 my $self = shift;
258 2         4 my $n = 1;
259 2         8 my $depth = $self->{_depth_list}{_upper};
260 2         11 while ($depth != $self->{_depth_list}) {
261 3         11 $n = $depth->set_depth($n);
262 3         13 $depth = $depth->{_upper};
263             }
264             }
265            
266             sub _destroy {
267 2     2   4 my $self = shift;
268            
269 2         10 $self->{_depth_list}->_destroy;
270 2         254 %$self = ();
271             }
272            
273             ####
274            
275             package SWF::Builder::Movie::Root;
276 1     1   6 use Carp;
  1         2  
  1         64  
277            
278 1     1   6 use base qw/ SWF::Builder::Movie SWF::Builder::ExElement::Color::AddColor /;
  1         2  
  1         2268  
279            
280             sub new {
281 1     1   4 my $class = shift;
282 1         6 my %param = @_;
283 1   50     10 my $version = $param{Version} || 6;
284            
285 1         14 my $self = $class->SUPER::new;
286            
287 4         16 $self->{_file} = SWF::File->new
288             ( undef,
289             Version => $version,
290             FrameRate => $param{FrameRate},
291 1         3 FrameSize => [ map {$_*20} @{$param{FrameSize}}],
  1         2  
292             );
293 1         305 $self->{_backgroundcolor} = $param{BackgroundColor};
294 1         3 $self->{_root} = $self;
295 1         2 $self->{_character_IDs} = [];
296 1         3 $self->{_ID_seed} = 1;
297 1         2 $self->{_target_path} = '_root';
298 1         3 $self->{_to_destroy} = [];
299 1         2 $self->{_version} = $version;
300 1         2 $self->{_as_namespace} = {};
301 1         2 $self->{_init_action} = undef;
302 1         3 $self->{_auto_namer} = 1;
303 1         12 $self->_init_is_alpha;
304 1         72 $self;
305             }
306            
307             sub pack {
308 1     1   3 my ($self, $stream) = @_;
309            
310 1         2 for my $id (@{$self->{_character_IDs}}) {
  1         3  
311 4         133 $id->configure(undef);
312             }
313            
314 1         15 $self->set_depth;
315            
316 1         6 $self->{_frame_list}->pack($stream);
317            
318             }
319            
320             our $EMPTY_SPRITE = SWF::Element::Tag::DefineSprite->new(ControlTags=>[SWF::Element::Tag::ShowFrame->new]);
321            
322             sub save {
323 1     1   3 my ($self, $file) = @_;
324 1         3 my $stream = $self->{_file};
325            
326 1         7 $self->{_is_alpha}->configure(0);
327 1         169 SWF::Element::Tag::SetBackgroundColor->new(BackgroundColor => $self->_add_color($self->{_backgroundcolor}))->pack($stream);
328 1         519 $self->{_ID_seed} = 1;
329 1 50       3 if (keys %{$self->{_as_namespace}}) {
  1         7  
330 0         0 my $action = SWF::Builder::ActionScript->new(Version => $self->{_version});
331 0         0 $action->compile(_create_namespace_initializer('', '_global', $self->{_as_namespace}));
332             # SWF::Element::Tag::DefineSprite->new(SpriteID => $self->{_ID_seed}, ControlTags=>[SWF::Element::Tag::ShowFrame->new])->pack($stream);
333 0         0 SWF::Element::Tag::DefineSprite->new(SpriteID => $self->{_ID_seed}, ControlTags=>[SWF::Element::Tag::End->new])->pack($stream);
334 0         0 SWF::Element::Tag::DoInitAction->new(SpriteID => $self->{_ID_seed}++, Actions => $action->{_actions})->pack($stream);
335             }
336 1 50       5 if ($self->{_init_action}) {
337             # SWF::Element::Tag::DefineSprite->new(SpriteID => $self->{_ID_seed}, ControlTags=>[SWF::Element::Tag::ShowFrame->new])->pack($stream);
338 0         0 SWF::Element::Tag::DefineSprite->new(SpriteID => $self->{_ID_seed}, ControlTags=>[SWF::Element::Tag::End->new])->pack($stream);
339 0         0 SWF::Element::Tag::DoInitAction->new(SpriteID => $self->{_ID_seed}++, Actions => $self->{_init_action}{_actions})->pack($stream);
340             }
341            
342 1         5 $self->pack($stream);
343 1         192 $stream->close($file);
344             }
345            
346             sub _create_namespace_initializer {
347 0     0   0 my ($as, $pname, $namehash) = @_;
348            
349 0         0 for my $name (keys %$namehash) {
350 0         0 my $n = "$pname.$name";
351 0         0 $as .= <
352             //#
353             if (eval('$n') == undefined) {
354             set('$n', new Object());
355             }
356             ASEND
357             #//
358 0         0 $as = _create_namespace_initializer($as, $n, $namehash->{$name});
359             }
360 0         0 return $as;
361             }
362            
363             sub use_namespace {
364 0     0   0 require SWF::Builder::ActionScript;
365            
366 0         0 my $self = shift;
367            
368 0         0 while (my $name = shift) {
369 0         0 my $ns = $self->{_as_namespace};
370 0         0 my @n = split /\./, $name;
371 0         0 for my $n (@n) {
372 0   0     0 $ns->{$n} ||= {};
373 0         0 $ns = $ns->{$n};
374             }
375             }
376             }
377            
378             sub init_action {
379 0     0   0 require SWF::Builder::ActionScript;
380            
381 0         0 my $self = shift;
382            
383 0   0     0 $self->{_init_action} ||= SWF::Builder::ActionScript->new(Version => $self->{_version});
384             }
385            
386             sub auto_namer {
387 0     0   0 shift->{_auto_namer} = 1;
388             }
389            
390             sub no_namer {
391 0     0   0 shift->{_auto_namer} = 0;
392             }
393            
394            
395             sub _depends {
396 1     1   3 my ($self, $char, $frame) = @_;
397            
398 1         1 push @{$self->{_frame_list}[$frame-1]}, $char;
  1         6  
399             }
400            
401             sub FrameRate {
402 1     1   2 my $self = shift;
403 1         4 $self->{_file}->FrameRate(@_);
404             }
405            
406             sub FrameSize {
407 0     0   0 my $self = shift;
408 0         0 $self->{_file}->FrameSize(map {$_*20} @_);
  0         0  
409             }
410            
411             sub BackgroundColor {
412 0     0   0 my ($self, $color) = @_;
413 0 0       0 $self->{_backgroundcolor} = $color if defined $color;
414 0         0 $self->{_backgroundcolor};
415             }
416            
417             sub compress {
418 0     0   0 my $self = shift;
419 0         0 $self->{_file}->compress(@_);
420             }
421            
422             sub _destroy {
423 1     1   3 my $self = shift;
424 1         2 undef $self->{_root};
425 1         2 for (@{$self->{_to_destroy}}) {
  1         4  
426 7         67 $_->_destroy;
427             }
428 1         9 $self->SUPER::_destroy;
429             }
430            
431             # Autoload methods go after =cut, and are processed by the autosplit program.
432            
433             1;
434             __END__