2 * Copyright (C) 2003-2006 David Schleef <ds@schleef.org>
3 * 2005-2006 Eric Anholt <eric@anholt.net>
4 * 2006-2007 Benjamin Otte <otte@gnome.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
28 #include "swfdec_movie.h"
29 #include "swfdec_as_strings.h"
30 #include "swfdec_bits.h"
31 #include "swfdec_debug.h"
32 #include "swfdec_decoder.h"
33 #include "swfdec_internal.h"
34 #include "swfdec_player_internal.h"
35 #include "swfdec_sprite.h"
36 #include "swfdec_sprite_movie.h"
37 #include "swfdec_resource.h"
40 mc_x_get (SwfdecMovie
*movie
, SwfdecAsValue
*rval
)
44 swfdec_movie_update (movie
);
45 d
= SWFDEC_TWIPS_TO_DOUBLE (movie
->matrix
.x0
);
46 SWFDEC_AS_VALUE_SET_NUMBER (rval
, d
);
50 mc_x_set (SwfdecMovie
*movie
, const SwfdecAsValue
*val
)
54 if (!swfdec_as_value_to_twips (swfdec_gc_object_get_context (movie
), val
, FALSE
, &x
))
56 movie
->modified
= TRUE
;
57 if (x
!= movie
->matrix
.x0
) {
58 swfdec_movie_begin_update_matrix (movie
);
60 swfdec_movie_end_update_matrix (movie
);
65 mc_y_get (SwfdecMovie
*movie
, SwfdecAsValue
*rval
)
69 swfdec_movie_update (movie
);
70 d
= SWFDEC_TWIPS_TO_DOUBLE (movie
->matrix
.y0
);
71 SWFDEC_AS_VALUE_SET_NUMBER (rval
, d
);
75 mc_y_set (SwfdecMovie
*movie
, const SwfdecAsValue
*val
)
79 if (!swfdec_as_value_to_twips (swfdec_gc_object_get_context (movie
), val
, FALSE
, &y
))
81 movie
->modified
= TRUE
;
82 if (y
!= movie
->matrix
.y0
) {
83 swfdec_movie_begin_update_matrix (movie
);
85 swfdec_movie_end_update_matrix (movie
);
90 mc_xscale_get (SwfdecMovie
*movie
, SwfdecAsValue
*rval
)
92 SWFDEC_AS_VALUE_SET_NUMBER (rval
, movie
->xscale
);
96 mc_xscale_set (SwfdecMovie
*movie
, const SwfdecAsValue
*val
)
100 d
= swfdec_as_value_to_number (swfdec_gc_object_get_context (movie
), val
);
102 SWFDEC_WARNING ("trying to set xscale to a non-finite value, ignoring");
105 movie
->modified
= TRUE
;
106 if (movie
->xscale
!= d
) {
107 swfdec_movie_begin_update_matrix (movie
);
109 swfdec_movie_end_update_matrix (movie
);
114 mc_yscale_get (SwfdecMovie
*movie
, SwfdecAsValue
*rval
)
116 SWFDEC_AS_VALUE_SET_NUMBER (rval
, movie
->yscale
);
120 mc_yscale_set (SwfdecMovie
*movie
, const SwfdecAsValue
*val
)
124 d
= swfdec_as_value_to_number (swfdec_gc_object_get_context (movie
), val
);
126 SWFDEC_WARNING ("trying to set yscale to a non-finite value, ignoring");
129 movie
->modified
= TRUE
;
130 if (movie
->yscale
!= d
) {
131 swfdec_movie_begin_update_matrix (movie
);
133 swfdec_movie_end_update_matrix (movie
);
138 mc_name_get (SwfdecMovie
*movie
, SwfdecAsValue
*rval
)
140 SWFDEC_AS_VALUE_SET_STRING (rval
, movie
->name
);
144 mc_name_set (SwfdecMovie
*movie
, const SwfdecAsValue
*val
)
146 movie
->name
= swfdec_as_value_to_string (swfdec_gc_object_get_context (movie
), val
);
150 mc_alpha_get (SwfdecMovie
*movie
, SwfdecAsValue
*rval
)
152 SWFDEC_AS_VALUE_SET_NUMBER (rval
,
153 movie
->color_transform
.aa
* 100.0 / 256.0);
157 mc_alpha_set (SwfdecMovie
*movie
, const SwfdecAsValue
*val
)
162 d
= swfdec_as_value_to_number (swfdec_gc_object_get_context (movie
), val
);
164 SWFDEC_WARNING ("trying to set alpha to a non-finite value, ignoring");
167 alpha
= d
* 256.0 / 100.0;
168 if (alpha
!= movie
->color_transform
.aa
) {
169 movie
->color_transform
.aa
= alpha
;
170 swfdec_movie_invalidate_last (movie
);
175 mc_visible_get (SwfdecMovie
*movie
, SwfdecAsValue
*rval
)
177 SWFDEC_AS_VALUE_SET_BOOLEAN (rval
, movie
->visible
);
181 mc_visible_set (SwfdecMovie
*movie
, const SwfdecAsValue
*val
)
185 b
= swfdec_as_value_to_boolean (swfdec_gc_object_get_context (movie
), val
);
186 if (b
!= movie
->visible
) {
188 swfdec_movie_invalidate_last (movie
);
193 mc_width_get (SwfdecMovie
*movie
, SwfdecAsValue
*rval
)
197 swfdec_movie_update (movie
);
198 d
= rint (movie
->extents
.x1
- movie
->extents
.x0
);
199 d
= SWFDEC_TWIPS_TO_DOUBLE ((SwfdecTwips
) d
);
200 SWFDEC_AS_VALUE_SET_NUMBER (rval
, d
);
204 mc_width_set (SwfdecMovie
*movie
, const SwfdecAsValue
*val
)
208 /* property was readonly in Flash 4 and before */
209 if (swfdec_gc_object_get_context (movie
)->version
< 5)
211 d
= swfdec_as_value_to_number (swfdec_gc_object_get_context (movie
), val
);
213 SWFDEC_WARNING ("trying to set width to a non-finite value, ignoring");
216 swfdec_movie_update (movie
);
217 movie
->modified
= TRUE
;
218 cur
= rint (movie
->original_extents
.x1
- movie
->original_extents
.x0
);
219 cur
= SWFDEC_TWIPS_TO_DOUBLE ((SwfdecTwips
) cur
);
222 if (d
== movie
->xscale
)
224 swfdec_movie_begin_update_matrix (movie
);
227 swfdec_movie_begin_update_matrix (movie
);
231 swfdec_movie_end_update_matrix (movie
);
235 mc_height_get (SwfdecMovie
*movie
, SwfdecAsValue
*rval
)
239 swfdec_movie_update (movie
);
240 d
= rint (movie
->extents
.y1
- movie
->extents
.y0
);
241 d
= SWFDEC_TWIPS_TO_DOUBLE ((SwfdecTwips
) d
);
242 SWFDEC_AS_VALUE_SET_NUMBER (rval
, d
);
246 mc_height_set (SwfdecMovie
*movie
, const SwfdecAsValue
*val
)
250 /* property was readonly in Flash 4 and before */
251 if (swfdec_gc_object_get_context (movie
)->version
< 5)
253 d
= swfdec_as_value_to_number (swfdec_gc_object_get_context (movie
), val
);
255 SWFDEC_WARNING ("trying to set height to a non-finite value, ignoring");
258 swfdec_movie_update (movie
);
259 movie
->modified
= TRUE
;
260 cur
= rint (movie
->original_extents
.y1
- movie
->original_extents
.y0
);
261 cur
= SWFDEC_TWIPS_TO_DOUBLE ((SwfdecTwips
) cur
);
264 if (d
== movie
->yscale
)
266 swfdec_movie_begin_update_matrix (movie
);
269 swfdec_movie_begin_update_matrix (movie
);
273 swfdec_movie_end_update_matrix (movie
);
277 mc_rotation_get (SwfdecMovie
*movie
, SwfdecAsValue
*rval
)
279 SWFDEC_AS_VALUE_SET_NUMBER (rval
, movie
->rotation
);
283 mc_rotation_set (SwfdecMovie
*movie
, const SwfdecAsValue
*val
)
287 /* FIXME: Flash 4 handles this differently */
288 d
= swfdec_as_value_to_number (swfdec_gc_object_get_context (movie
), val
);
290 SWFDEC_WARNING ("setting rotation to NaN - not allowed");
298 if (swfdec_gc_object_get_context (movie
)->version
< 5) {
301 SWFDEC_FIXME ("implement correct rounding errors here");
303 movie
->modified
= TRUE
;
304 if (movie
->rotation
!= d
) {
305 swfdec_movie_begin_update_matrix (movie
);
307 swfdec_movie_end_update_matrix (movie
);
312 mc_xmouse_get (SwfdecMovie
*movie
, SwfdecAsValue
*rval
)
316 swfdec_movie_get_mouse (movie
, &x
, &y
);
317 x
= SWFDEC_TWIPS_TO_DOUBLE (rint (x
));
318 SWFDEC_AS_VALUE_SET_NUMBER (rval
, x
);
322 mc_ymouse_get (SwfdecMovie
*movie
, SwfdecAsValue
*rval
)
326 swfdec_movie_get_mouse (movie
, &x
, &y
);
327 y
= SWFDEC_TWIPS_TO_DOUBLE (rint (y
));
328 SWFDEC_AS_VALUE_SET_NUMBER (rval
, y
);
332 mc_parent (SwfdecMovie
*movie
, SwfdecAsValue
*rval
)
335 SWFDEC_AS_VALUE_SET_OBJECT (rval
, SWFDEC_AS_OBJECT (movie
->parent
));
337 SWFDEC_AS_VALUE_SET_UNDEFINED (rval
);
342 mc_root (SwfdecMovie
*movie
, SwfdecAsValue
*rval
)
344 movie
= swfdec_movie_get_root (movie
);
345 SWFDEC_AS_VALUE_SET_OBJECT (rval
, SWFDEC_AS_OBJECT (movie
));
349 mc_target_get (SwfdecMovie
*movie
, SwfdecAsValue
*rval
)
353 s
= g_string_new ("");
354 while (movie
->parent
) {
355 g_string_prepend (s
, movie
->name
);
356 g_string_prepend_c (s
, '/');
357 movie
= movie
->parent
;
360 SWFDEC_AS_VALUE_SET_STRING (rval
, SWFDEC_AS_STR_SLASH
);
361 g_string_free (s
, TRUE
);
363 SWFDEC_AS_VALUE_SET_STRING (rval
, swfdec_as_context_give_string (
364 swfdec_gc_object_get_context (movie
), g_string_free (s
, FALSE
)));
369 mc_url_get (SwfdecMovie
*movie
, SwfdecAsValue
*rval
)
371 SWFDEC_AS_VALUE_SET_STRING (rval
, swfdec_as_context_get_string (
372 swfdec_gc_object_get_context (movie
),
373 swfdec_url_get_url (swfdec_loader_get_url (movie
->resource
->loader
))));
377 mc_focusrect_get (SwfdecMovie
*movie
, SwfdecAsValue
*rval
)
382 if (!SWFDEC_IS_ACTOR (movie
)) {
383 SWFDEC_FIXME ("should not be possible to get _focusrect on non-actors");
386 actor
= SWFDEC_ACTOR (movie
);
387 cx
= swfdec_gc_object_get_context (actor
);
389 switch (actor
->focusrect
) {
390 case SWFDEC_FLASH_YES
:
392 SWFDEC_AS_VALUE_SET_BOOLEAN (rval
, TRUE
);
394 SWFDEC_AS_VALUE_SET_INT (rval
, 1);
396 case SWFDEC_FLASH_NO
:
398 SWFDEC_AS_VALUE_SET_BOOLEAN (rval
, FALSE
);
400 SWFDEC_AS_VALUE_SET_INT (rval
, 0);
402 case SWFDEC_FLASH_MAYBE
:
403 SWFDEC_AS_VALUE_SET_NULL (rval
);
406 g_assert_not_reached();
411 mc_focusrect_set (SwfdecMovie
*movie
, const SwfdecAsValue
*val
)
417 if (!SWFDEC_IS_ACTOR (movie
)) {
418 SWFDEC_FIXME ("should not be possible to get _focusrect on non-actors");
421 cx
= swfdec_gc_object_get_context (movie
);
422 actor
= SWFDEC_ACTOR (movie
);
424 if (SWFDEC_AS_VALUE_IS_UNDEFINED (val
) ||
425 SWFDEC_AS_VALUE_IS_NULL (val
)) {
426 if (movie
->parent
== NULL
)
428 b
= SWFDEC_FLASH_MAYBE
;
430 if (movie
->parent
== NULL
) {
431 double d
= swfdec_as_value_to_number (cx
, val
);
434 b
= d
? SWFDEC_FLASH_YES
: SWFDEC_FLASH_NO
;
436 b
= swfdec_as_value_to_boolean (cx
, val
) ? SWFDEC_FLASH_YES
: SWFDEC_FLASH_NO
;
440 if (b
!= actor
->focusrect
) {
441 SwfdecPlayerPrivate
*priv
= SWFDEC_PLAYER (cx
)->priv
;
442 gboolean had_focusrect
= priv
->focus
? swfdec_actor_has_focusrect (priv
->focus
) : FALSE
;
443 actor
->focusrect
= b
;
444 if (priv
->focus
&& had_focusrect
!= swfdec_actor_has_focusrect (priv
->focus
))
445 swfdec_player_invalidate_focusrect (SWFDEC_PLAYER (cx
));
451 void (* get
) (SwfdecMovie
*movie
, SwfdecAsValue
*ret
);
452 void (* set
) (SwfdecMovie
*movie
, const SwfdecAsValue
*val
);
453 } swfdec_movieclip_props
[] = {
454 { SWFDEC_AS_STR__x
, mc_x_get
, mc_x_set
},
455 { SWFDEC_AS_STR__y
, mc_y_get
, mc_y_set
},
456 { SWFDEC_AS_STR__xscale
, mc_xscale_get
, mc_xscale_set
},
457 { SWFDEC_AS_STR__yscale
, mc_yscale_get
, mc_yscale_set
},
458 { SWFDEC_AS_STR__currentframe
,NULL
, NULL
},
459 { SWFDEC_AS_STR__totalframes
, NULL
, NULL
},
460 { SWFDEC_AS_STR__alpha
, mc_alpha_get
, mc_alpha_set
},
461 { SWFDEC_AS_STR__visible
, mc_visible_get
, mc_visible_set
},
462 { SWFDEC_AS_STR__width
, mc_width_get
, mc_width_set
},
463 { SWFDEC_AS_STR__height
, mc_height_get
, mc_height_set
},
464 { SWFDEC_AS_STR__rotation
, mc_rotation_get
, mc_rotation_set
},
465 { SWFDEC_AS_STR__target
, mc_target_get
, NULL
},
466 { SWFDEC_AS_STR__framesloaded
,NULL
, NULL
},
467 { SWFDEC_AS_STR__name
, mc_name_get
, mc_name_set
},
468 { SWFDEC_AS_STR__droptarget
, NULL
, NULL
}, //"_droptarget"
469 { SWFDEC_AS_STR__url
, mc_url_get
, NULL
},
470 { SWFDEC_AS_STR__highquality
, NULL
, NULL
}, //"_highquality"
471 { SWFDEC_AS_STR__focusrect
, mc_focusrect_get
, mc_focusrect_set
}, //"_focusrect"
472 { SWFDEC_AS_STR__soundbuftime
,NULL
, NULL
}, //"_soundbuftime"
473 { SWFDEC_AS_STR__quality
, NULL
, NULL
}, //"_quality"
474 { SWFDEC_AS_STR__xmouse
, mc_xmouse_get
, NULL
},
475 { SWFDEC_AS_STR__ymouse
, mc_ymouse_get
, NULL
},
476 { SWFDEC_AS_STR__parent
, mc_parent
, NULL
},
477 { SWFDEC_AS_STR__root
, mc_root
, NULL
},
481 swfdec_movie_property_lookup (const char *name
)
485 for (i
= 0; i
< G_N_ELEMENTS (swfdec_movieclip_props
); i
++) {
486 if (swfdec_movieclip_props
[i
].name
== name
)
493 swfdec_movie_property_do_get (SwfdecMovie
*movie
, guint id
,
496 if (id
>= G_N_ELEMENTS (swfdec_movieclip_props
) ||
497 swfdec_movieclip_props
[id
].get
== NULL
) {
498 SWFDEC_AS_VALUE_SET_UNDEFINED (val
);
500 swfdec_movieclip_props
[id
].get (movie
, val
);
505 swfdec_movie_property_do_set (SwfdecMovie
*movie
, guint id
,
506 const SwfdecAsValue
*val
)
508 if (id
< G_N_ELEMENTS (swfdec_movieclip_props
) &&
509 swfdec_movieclip_props
[id
].set
!= NULL
) {
510 swfdec_movieclip_props
[id
].set (movie
, val
);