back to development
[swfdec.git] / swfdec / swfdec_movie_asprops.c
blob2a885a406a62bd28f540354d2838bd9be9dd61f6
1 /* Swfdec
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
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 #include <string.h>
26 #include <math.h>
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"
39 static void
40 mc_x_get (SwfdecMovie *movie, SwfdecAsValue *rval)
42 double d;
44 swfdec_movie_update (movie);
45 d = SWFDEC_TWIPS_TO_DOUBLE (movie->matrix.x0);
46 SWFDEC_AS_VALUE_SET_NUMBER (rval, d);
49 static void
50 mc_x_set (SwfdecMovie *movie, const SwfdecAsValue *val)
52 SwfdecTwips x;
54 if (!swfdec_as_value_to_twips (swfdec_gc_object_get_context (movie), val, FALSE, &x))
55 return;
56 movie->modified = TRUE;
57 if (x != movie->matrix.x0) {
58 swfdec_movie_begin_update_matrix (movie);
59 movie->matrix.x0 = x;
60 swfdec_movie_end_update_matrix (movie);
64 static void
65 mc_y_get (SwfdecMovie *movie, SwfdecAsValue *rval)
67 double d;
69 swfdec_movie_update (movie);
70 d = SWFDEC_TWIPS_TO_DOUBLE (movie->matrix.y0);
71 SWFDEC_AS_VALUE_SET_NUMBER (rval, d);
74 static void
75 mc_y_set (SwfdecMovie *movie, const SwfdecAsValue *val)
77 SwfdecTwips y;
79 if (!swfdec_as_value_to_twips (swfdec_gc_object_get_context (movie), val, FALSE, &y))
80 return;
81 movie->modified = TRUE;
82 if (y != movie->matrix.y0) {
83 swfdec_movie_begin_update_matrix (movie);
84 movie->matrix.y0 = y;
85 swfdec_movie_end_update_matrix (movie);
89 static void
90 mc_xscale_get (SwfdecMovie *movie, SwfdecAsValue *rval)
92 SWFDEC_AS_VALUE_SET_NUMBER (rval, movie->xscale);
95 static void
96 mc_xscale_set (SwfdecMovie *movie, const SwfdecAsValue *val)
98 double d;
100 d = swfdec_as_value_to_number (swfdec_gc_object_get_context (movie), val);
101 if (!isfinite (d)) {
102 SWFDEC_WARNING ("trying to set xscale to a non-finite value, ignoring");
103 return;
105 movie->modified = TRUE;
106 if (movie->xscale != d) {
107 swfdec_movie_begin_update_matrix (movie);
108 movie->xscale = d;
109 swfdec_movie_end_update_matrix (movie);
113 static void
114 mc_yscale_get (SwfdecMovie *movie, SwfdecAsValue *rval)
116 SWFDEC_AS_VALUE_SET_NUMBER (rval, movie->yscale);
119 static void
120 mc_yscale_set (SwfdecMovie *movie, const SwfdecAsValue *val)
122 double d;
124 d = swfdec_as_value_to_number (swfdec_gc_object_get_context (movie), val);
125 if (!isfinite (d)) {
126 SWFDEC_WARNING ("trying to set yscale to a non-finite value, ignoring");
127 return;
129 movie->modified = TRUE;
130 if (movie->yscale != d) {
131 swfdec_movie_begin_update_matrix (movie);
132 movie->yscale = d;
133 swfdec_movie_end_update_matrix (movie);
137 static void
138 mc_name_get (SwfdecMovie *movie, SwfdecAsValue *rval)
140 SWFDEC_AS_VALUE_SET_STRING (rval, movie->name);
143 static void
144 mc_name_set (SwfdecMovie *movie, const SwfdecAsValue *val)
146 movie->name = swfdec_as_value_to_string (swfdec_gc_object_get_context (movie), val);
149 static void
150 mc_alpha_get (SwfdecMovie *movie, SwfdecAsValue *rval)
152 SWFDEC_AS_VALUE_SET_NUMBER (rval,
153 movie->color_transform.aa * 100.0 / 256.0);
156 static void
157 mc_alpha_set (SwfdecMovie *movie, const SwfdecAsValue *val)
159 double d;
160 int alpha;
162 d = swfdec_as_value_to_number (swfdec_gc_object_get_context (movie), val);
163 if (!isfinite (d)) {
164 SWFDEC_WARNING ("trying to set alpha to a non-finite value, ignoring");
165 return;
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);
174 static void
175 mc_visible_get (SwfdecMovie *movie, SwfdecAsValue *rval)
177 SWFDEC_AS_VALUE_SET_BOOLEAN (rval, movie->visible);
180 static void
181 mc_visible_set (SwfdecMovie *movie, const SwfdecAsValue *val)
183 gboolean b;
185 b = swfdec_as_value_to_boolean (swfdec_gc_object_get_context (movie), val);
186 if (b != movie->visible) {
187 movie->visible = b;
188 swfdec_movie_invalidate_last (movie);
192 static void
193 mc_width_get (SwfdecMovie *movie, SwfdecAsValue *rval)
195 double d;
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);
203 static void
204 mc_width_set (SwfdecMovie *movie, const SwfdecAsValue *val)
206 double d, cur;
208 /* property was readonly in Flash 4 and before */
209 if (swfdec_gc_object_get_context (movie)->version < 5)
210 return;
211 d = swfdec_as_value_to_number (swfdec_gc_object_get_context (movie), val);
212 if (!isfinite (d)) {
213 SWFDEC_WARNING ("trying to set width to a non-finite value, ignoring");
214 return;
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);
220 if (cur != 0) {
221 d = 100 * d / cur;
222 if (d == movie->xscale)
223 return;
224 swfdec_movie_begin_update_matrix (movie);
225 movie->xscale = d;
226 } else {
227 swfdec_movie_begin_update_matrix (movie);
228 movie->xscale = 0;
229 movie->yscale = 0;
231 swfdec_movie_end_update_matrix (movie);
234 static void
235 mc_height_get (SwfdecMovie *movie, SwfdecAsValue *rval)
237 double d;
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);
245 static void
246 mc_height_set (SwfdecMovie *movie, const SwfdecAsValue *val)
248 double d, cur;
250 /* property was readonly in Flash 4 and before */
251 if (swfdec_gc_object_get_context (movie)->version < 5)
252 return;
253 d = swfdec_as_value_to_number (swfdec_gc_object_get_context (movie), val);
254 if (!isfinite (d)) {
255 SWFDEC_WARNING ("trying to set height to a non-finite value, ignoring");
256 return;
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);
262 if (cur != 0) {
263 d = 100 * d / cur;
264 if (d == movie->yscale)
265 return;
266 swfdec_movie_begin_update_matrix (movie);
267 movie->yscale = d;
268 } else {
269 swfdec_movie_begin_update_matrix (movie);
270 movie->xscale = 0;
271 movie->yscale = 0;
273 swfdec_movie_end_update_matrix (movie);
276 static void
277 mc_rotation_get (SwfdecMovie *movie, SwfdecAsValue *rval)
279 SWFDEC_AS_VALUE_SET_NUMBER (rval, movie->rotation);
282 static void
283 mc_rotation_set (SwfdecMovie *movie, const SwfdecAsValue *val)
285 double d;
287 /* FIXME: Flash 4 handles this differently */
288 d = swfdec_as_value_to_number (swfdec_gc_object_get_context (movie), val);
289 if (isnan (d)) {
290 SWFDEC_WARNING ("setting rotation to NaN - not allowed");
291 return;
293 d = fmod (d, 360.0);
294 if (d > 180.0)
295 d -= 360.0;
296 if (d < -180.0)
297 d += 360.0;
298 if (swfdec_gc_object_get_context (movie)->version < 5) {
299 if (!isfinite (d))
300 return;
301 SWFDEC_FIXME ("implement correct rounding errors here");
303 movie->modified = TRUE;
304 if (movie->rotation != d) {
305 swfdec_movie_begin_update_matrix (movie);
306 movie->rotation = d;
307 swfdec_movie_end_update_matrix (movie);
311 static void
312 mc_xmouse_get (SwfdecMovie *movie, SwfdecAsValue *rval)
314 double x, y;
316 swfdec_movie_get_mouse (movie, &x, &y);
317 x = SWFDEC_TWIPS_TO_DOUBLE (rint (x));
318 SWFDEC_AS_VALUE_SET_NUMBER (rval, x);
321 static void
322 mc_ymouse_get (SwfdecMovie *movie, SwfdecAsValue *rval)
324 double x, y;
326 swfdec_movie_get_mouse (movie, &x, &y);
327 y = SWFDEC_TWIPS_TO_DOUBLE (rint (y));
328 SWFDEC_AS_VALUE_SET_NUMBER (rval, y);
331 static void
332 mc_parent (SwfdecMovie *movie, SwfdecAsValue *rval)
334 if (movie->parent) {
335 SWFDEC_AS_VALUE_SET_OBJECT (rval, SWFDEC_AS_OBJECT (movie->parent));
336 } else {
337 SWFDEC_AS_VALUE_SET_UNDEFINED (rval);
341 static void
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));
348 static void
349 mc_target_get (SwfdecMovie *movie, SwfdecAsValue *rval)
351 GString *s;
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;
359 if (s->len == 0) {
360 SWFDEC_AS_VALUE_SET_STRING (rval, SWFDEC_AS_STR_SLASH);
361 g_string_free (s, TRUE);
362 } else {
363 SWFDEC_AS_VALUE_SET_STRING (rval, swfdec_as_context_give_string (
364 swfdec_gc_object_get_context (movie), g_string_free (s, FALSE)));
368 static void
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))));
376 static void
377 mc_focusrect_get (SwfdecMovie *movie, SwfdecAsValue *rval)
379 SwfdecAsContext *cx;
380 SwfdecActor *actor;
382 if (!SWFDEC_IS_ACTOR (movie)) {
383 SWFDEC_FIXME ("should not be possible to get _focusrect on non-actors");
384 return;
386 actor = SWFDEC_ACTOR (movie);
387 cx = swfdec_gc_object_get_context (actor);
389 switch (actor->focusrect) {
390 case SWFDEC_FLASH_YES:
391 if (cx->version > 5)
392 SWFDEC_AS_VALUE_SET_BOOLEAN (rval, TRUE);
393 else
394 SWFDEC_AS_VALUE_SET_INT (rval, 1);
395 break;
396 case SWFDEC_FLASH_NO:
397 if (cx->version > 5)
398 SWFDEC_AS_VALUE_SET_BOOLEAN (rval, FALSE);
399 else
400 SWFDEC_AS_VALUE_SET_INT (rval, 0);
401 break;
402 case SWFDEC_FLASH_MAYBE:
403 SWFDEC_AS_VALUE_SET_NULL (rval);
404 break;
405 default:
406 g_assert_not_reached();
410 static void
411 mc_focusrect_set (SwfdecMovie *movie, const SwfdecAsValue *val)
413 SwfdecAsContext *cx;
414 SwfdecActor *actor;
415 SwfdecFlashBool b;
417 if (!SWFDEC_IS_ACTOR (movie)) {
418 SWFDEC_FIXME ("should not be possible to get _focusrect on non-actors");
419 return;
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)
427 return;
428 b = SWFDEC_FLASH_MAYBE;
429 } else {
430 if (movie->parent == NULL) {
431 double d = swfdec_as_value_to_number (cx, val);
432 if (isnan (d))
433 return;
434 b = d ? SWFDEC_FLASH_YES : SWFDEC_FLASH_NO;
435 } else {
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));
449 struct {
450 const char *name;
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 },
480 guint
481 swfdec_movie_property_lookup (const char *name)
483 guint i;
485 for (i = 0; i < G_N_ELEMENTS (swfdec_movieclip_props); i++) {
486 if (swfdec_movieclip_props[i].name == name)
487 return i;
489 return G_MAXUINT;
492 void
493 swfdec_movie_property_do_get (SwfdecMovie *movie, guint id,
494 SwfdecAsValue *val)
496 if (id >= G_N_ELEMENTS (swfdec_movieclip_props) ||
497 swfdec_movieclip_props[id].get == NULL) {
498 SWFDEC_AS_VALUE_SET_UNDEFINED (val);
499 } else {
500 swfdec_movieclip_props[id].get (movie, val);
504 void
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);