add blend mode tests
[swfdec.git] / swfdec / swfdec_sprite_movie_as.c
bloba9bde255619dce3b310ba698cf124b427babc44e
1 /* Swfdec
2 * Copyright (C) 2003-2006 David Schleef <ds@schleef.org>
3 * 2005-2006 Eric Anholt <eric@anholt.net>
4 * 2006-2008 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
26 #include "swfdec_movie.h"
27 #include "swfdec_as_internal.h"
28 #include "swfdec_as_strings.h"
29 #include "swfdec_bitmap_data.h"
30 #include "swfdec_bitmap_movie.h"
31 #include "swfdec_bits.h"
32 #include "swfdec_debug.h"
33 #include "swfdec_decoder.h"
34 #include "swfdec_filter.h"
35 #include "swfdec_internal.h"
36 #include "swfdec_player_internal.h"
37 #include "swfdec_sandbox.h"
38 #include "swfdec_sprite.h"
39 #include "swfdec_sprite_movie.h"
40 #include "swfdec_swf_decoder.h"
41 #include "swfdec_transform_as.h"
42 #include "swfdec_resource.h"
43 #include "swfdec_utils.h"
44 #include "swfdec_as_internal.h"
46 SWFDEC_AS_NATIVE (900, 200, swfdec_sprite_movie_get_tabIndex)
47 void
48 swfdec_sprite_movie_get_tabIndex (SwfdecAsContext *cx, SwfdecAsObject *object,
49 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
51 SWFDEC_STUB ("MovieClip.tabIndex (get)");
54 SWFDEC_AS_NATIVE (900, 201, swfdec_sprite_movie_set_tabIndex)
55 void
56 swfdec_sprite_movie_set_tabIndex (SwfdecAsContext *cx, SwfdecAsObject *object,
57 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
59 SWFDEC_STUB ("MovieClip.tabIndex (set)");
62 SWFDEC_AS_NATIVE (900, 300, swfdec_sprite_movie_get__lockroot)
63 void
64 swfdec_sprite_movie_get__lockroot (SwfdecAsContext *cx, SwfdecAsObject *object,
65 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
67 SwfdecMovie *movie;
69 SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE, &movie, "");
71 SWFDEC_AS_VALUE_SET_BOOLEAN (rval, movie->lockroot);
74 SWFDEC_AS_NATIVE (900, 301, swfdec_sprite_movie_set__lockroot)
75 void
76 swfdec_sprite_movie_set__lockroot (SwfdecAsContext *cx, SwfdecAsObject *object,
77 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
79 SwfdecMovie *movie;
80 gboolean lockroot;
82 SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE, &movie, "b", &lockroot);
84 movie->lockroot = lockroot;
87 SWFDEC_AS_NATIVE (900, 401, swfdec_sprite_movie_get_cacheAsBitmap)
88 void
89 swfdec_sprite_movie_get_cacheAsBitmap (SwfdecAsContext *cx, SwfdecAsObject *object,
90 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
92 SWFDEC_STUB ("MovieClip.cacheAsBitmap (get)");
95 SWFDEC_AS_NATIVE (900, 402, swfdec_sprite_movie_set_cacheAsBitmap)
96 void
97 swfdec_sprite_movie_set_cacheAsBitmap (SwfdecAsContext *cx, SwfdecAsObject *object,
98 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
100 SWFDEC_STUB ("MovieClip.cacheAsBitmap (set)");
103 SWFDEC_AS_NATIVE (900, 403, swfdec_sprite_movie_get_opaqueBackground)
104 void
105 swfdec_sprite_movie_get_opaqueBackground (SwfdecAsContext *cx, SwfdecAsObject *object,
106 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
108 SWFDEC_STUB ("MovieClip.opaqueBackground (get)");
111 SWFDEC_AS_NATIVE (900, 404, swfdec_sprite_movie_set_opaqueBackground)
112 void
113 swfdec_sprite_movie_set_opaqueBackground (SwfdecAsContext *cx, SwfdecAsObject *object,
114 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
116 SWFDEC_STUB ("MovieClip.opaqueBackground (set)");
119 SWFDEC_AS_NATIVE (900, 405, swfdec_sprite_movie_get_scrollRect)
120 void
121 swfdec_sprite_movie_get_scrollRect (SwfdecAsContext *cx, SwfdecAsObject *object,
122 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
124 SWFDEC_STUB ("MovieClip.scrollRect (get)");
127 SWFDEC_AS_NATIVE (900, 406, swfdec_sprite_movie_set_scrollRect)
128 void
129 swfdec_sprite_movie_set_scrollRect (SwfdecAsContext *cx, SwfdecAsObject *object,
130 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
132 SWFDEC_STUB ("MovieClip.scrollRect (set)");
135 SWFDEC_AS_NATIVE (900, 417, swfdec_sprite_movie_get_filters)
136 void
137 swfdec_sprite_movie_get_filters (SwfdecAsContext *cx, SwfdecAsObject *object,
138 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
140 SWFDEC_STUB ("MovieClip.filters (get)");
143 SWFDEC_AS_NATIVE (900, 418, swfdec_sprite_movie_set_filters)
144 void
145 swfdec_sprite_movie_set_filters (SwfdecAsContext *cx, SwfdecAsObject *object,
146 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
148 SwfdecAsObject *array;
149 SwfdecAsValue val;
150 SwfdecFilter *filter;
151 SwfdecMovie *movie;
152 int i, length;
153 GSList *list;
155 SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE, &movie, "o", &array);
157 swfdec_movie_invalidate_next (movie);
159 swfdec_as_object_get_variable (array, SWFDEC_AS_STR_length, &val);
160 length = swfdec_as_value_to_integer (cx, val);
162 list = NULL;
163 for (i = 0; i < length; i++) {
164 if (!swfdec_as_object_get_variable (array,
165 swfdec_as_integer_to_string (cx, i), &val) ||
166 !SWFDEC_AS_VALUE_IS_OBJECT (val) ||
167 !SWFDEC_IS_FILTER (SWFDEC_AS_VALUE_GET_OBJECT (val)->relay))
168 continue;
169 filter = SWFDEC_FILTER (SWFDEC_AS_VALUE_GET_OBJECT (val)->relay);
170 filter = swfdec_filter_clone (filter);
171 list = g_slist_prepend (list, filter);
173 g_slist_free (movie->filters);
174 movie->filters = list;
177 SWFDEC_AS_NATIVE (900, 419, swfdec_sprite_movie_get_transform)
178 void
179 swfdec_sprite_movie_get_transform (SwfdecAsContext *cx, SwfdecAsObject *object,
180 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
182 SwfdecTransformAs *trans;
183 SwfdecMovie *movie;
185 SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE, &movie, "");
187 trans = swfdec_transform_as_new (cx, movie);
188 SWFDEC_AS_VALUE_SET_OBJECT (rval, swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (trans)));
191 SWFDEC_AS_NATIVE (900, 420, swfdec_sprite_movie_set_transform)
192 void
193 swfdec_sprite_movie_set_transform (SwfdecAsContext *cx, SwfdecAsObject *object,
194 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
196 SWFDEC_STUB ("MovieClip.transform (set)");
199 static const char *blend_mode_names[] = {
200 SWFDEC_AS_STR_normal,
201 SWFDEC_AS_STR_layer,
202 SWFDEC_AS_STR_multiply,
203 SWFDEC_AS_STR_screen,
204 SWFDEC_AS_STR_lighten,
205 SWFDEC_AS_STR_darken,
206 SWFDEC_AS_STR_difference,
207 SWFDEC_AS_STR_add,
208 SWFDEC_AS_STR_subtract,
209 SWFDEC_AS_STR_invert,
210 SWFDEC_AS_STR_alpha,
211 SWFDEC_AS_STR_erase,
212 SWFDEC_AS_STR_overlay,
213 SWFDEC_AS_STR_hardlight
215 static const gsize num_blend_mode_names =
216 sizeof (blend_mode_names) / sizeof (blend_mode_names[0]);
218 SWFDEC_AS_NATIVE (900, 500, swfdec_sprite_movie_get_blendMode)
219 void
220 swfdec_sprite_movie_get_blendMode (SwfdecAsContext *cx, SwfdecAsObject *object,
221 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
223 SwfdecMovie *movie;
225 SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE, &movie, "");
227 if (movie->blend_mode > 0 && movie->blend_mode <= num_blend_mode_names)
228 SWFDEC_AS_VALUE_SET_STRING (rval, blend_mode_names[movie->blend_mode - 1]);
231 SWFDEC_AS_NATIVE (900, 501, swfdec_sprite_movie_set_blendMode)
232 void
233 swfdec_sprite_movie_set_blendMode (SwfdecAsContext *cx, SwfdecAsObject *object,
234 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
236 SwfdecMovie *movie;
237 SwfdecAsValue val;
238 const char *str;
239 int blend_mode;
240 gsize i;
242 SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE, &movie, "v", &val);
244 if (SWFDEC_AS_VALUE_IS_NUMBER (val)) {
245 blend_mode = SWFDEC_AS_VALUE_GET_NUMBER (val);
246 } else if (SWFDEC_AS_VALUE_IS_STRING (val)) {
247 blend_mode = 0;
248 str = SWFDEC_AS_VALUE_GET_STRING (val);
249 for (i = 0; i < num_blend_mode_names; i++) {
250 if (str == blend_mode_names[i]) { // case-sensitive
251 blend_mode = i + 1;
252 break;
255 } else if (SWFDEC_AS_VALUE_IS_OBJECT (val)) {
256 blend_mode = 0;
257 } else {
258 blend_mode = 1;
261 if ((guint)blend_mode != movie->blend_mode) {
262 movie->blend_mode = blend_mode;
263 swfdec_movie_invalidate_last (movie);
267 SWFDEC_AS_NATIVE (900, 2, swfdec_sprite_movie_localToGlobal)
268 void
269 swfdec_sprite_movie_localToGlobal (SwfdecAsContext *cx, SwfdecAsObject *object,
270 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
272 SwfdecMovie *movie;
273 SwfdecAsObject *o;
274 SwfdecAsValue *xv, *yv;
275 double x, y;
277 SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE, &movie, "O", &o);
279 xv = swfdec_as_object_peek_variable (o, SWFDEC_AS_STR_x);
280 if (xv == NULL || !SWFDEC_AS_VALUE_IS_NUMBER (*xv))
281 return;
282 yv = swfdec_as_object_peek_variable (o, SWFDEC_AS_STR_y);
283 if (yv == NULL || !SWFDEC_AS_VALUE_IS_NUMBER (*yv))
284 return;
286 x = SWFDEC_AS_VALUE_GET_NUMBER (*xv);
287 y = SWFDEC_AS_VALUE_GET_NUMBER (*yv);
288 x = swfdec_as_double_to_integer (x * SWFDEC_TWIPS_SCALE_FACTOR);
289 y = swfdec_as_double_to_integer (y * SWFDEC_TWIPS_SCALE_FACTOR);
290 swfdec_movie_local_to_global (movie, &x, &y);
291 *xv = swfdec_as_value_from_number (cx, SWFDEC_TWIPS_TO_DOUBLE ((SwfdecTwips) x));
292 *yv = swfdec_as_value_from_number (cx, SWFDEC_TWIPS_TO_DOUBLE ((SwfdecTwips) y));
295 SWFDEC_AS_NATIVE (900, 3, swfdec_sprite_movie_globalToLocal)
296 void
297 swfdec_sprite_movie_globalToLocal (SwfdecAsContext *cx, SwfdecAsObject *object,
298 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
300 SwfdecMovie *movie;
301 SwfdecAsObject *o;
302 SwfdecAsValue *xv, *yv;
303 double x, y;
305 SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE, &movie, "O", &o);
307 xv = swfdec_as_object_peek_variable (o, SWFDEC_AS_STR_x);
308 if (xv == NULL || !SWFDEC_AS_VALUE_IS_NUMBER (*xv))
309 return;
310 yv = swfdec_as_object_peek_variable (o, SWFDEC_AS_STR_y);
311 if (yv == NULL || !SWFDEC_AS_VALUE_IS_NUMBER (*yv))
312 return;
314 x = SWFDEC_AS_VALUE_GET_NUMBER (*xv);
315 y = SWFDEC_AS_VALUE_GET_NUMBER (*yv);
316 x = swfdec_as_double_to_integer (x * SWFDEC_TWIPS_SCALE_FACTOR);
317 y = swfdec_as_double_to_integer (y * SWFDEC_TWIPS_SCALE_FACTOR);
318 swfdec_movie_global_to_local (movie, &x, &y);
319 *xv = swfdec_as_value_from_number (cx, SWFDEC_TWIPS_TO_DOUBLE ((SwfdecTwips) x));
320 *yv = swfdec_as_value_from_number (cx, SWFDEC_TWIPS_TO_DOUBLE ((SwfdecTwips) y));
323 SWFDEC_AS_NATIVE (900, 8, swfdec_sprite_movie_attachAudio)
324 void
325 swfdec_sprite_movie_attachAudio (SwfdecAsContext *cx, SwfdecAsObject *object,
326 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
328 SWFDEC_STUB ("MovieClip.attachAudio");
331 SWFDEC_AS_NATIVE (900, 9, swfdec_sprite_movie_attachVideo)
332 void
333 swfdec_sprite_movie_attachVideo (SwfdecAsContext *cx, SwfdecAsObject *object,
334 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
336 SWFDEC_STUB ("MovieClip.attachVideo");
339 SWFDEC_AS_NATIVE (900, 23, swfdec_sprite_movie_getInstanceAtDepth)
340 void
341 swfdec_sprite_movie_getInstanceAtDepth (SwfdecAsContext *cx,
342 SwfdecAsObject *object, guint argc, SwfdecAsValue *argv,
343 SwfdecAsValue *rval)
345 SwfdecMovie *movie;
346 int depth;
348 SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE, &movie, "i", &depth);
350 // special case
351 if (SWFDEC_AS_VALUE_IS_UNDEFINED (argv[0]))
352 return;
354 movie = swfdec_movie_find (movie, depth);
355 if (movie != NULL) {
356 if (!swfdec_movie_is_scriptable (movie))
357 movie = movie->parent;
358 SWFDEC_AS_VALUE_SET_MOVIE (rval, movie);
362 SWFDEC_AS_NATIVE (900, 24, swfdec_sprite_movie_getSWFVersion)
363 void
364 swfdec_sprite_movie_getSWFVersion (SwfdecAsContext *cx, SwfdecAsObject *object,
365 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
367 if (object != NULL && object->movie) {
368 *rval = swfdec_as_value_from_integer (cx,
369 swfdec_movie_get_version (SWFDEC_MOVIE (object->relay)));
370 } else {
371 *rval = swfdec_as_value_from_integer (cx, -1);
375 SWFDEC_AS_NATIVE (900, 25, swfdec_sprite_movie_attachBitmap)
376 void
377 swfdec_sprite_movie_attachBitmap (SwfdecAsContext *cx, SwfdecAsObject *object,
378 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
380 SwfdecMovie *parent;
381 SwfdecAsObject *bitmap;
382 const char *snapping = SWFDEC_AS_STR_auto;
383 gboolean smoothing = FALSE;
384 int depth;
385 SwfdecMovie *movie;
387 SWFDEC_AS_CHECK (SWFDEC_TYPE_SPRITE_MOVIE, &parent, "oi|sb",
388 &bitmap, &depth, &snapping, &smoothing);
390 if (!SWFDEC_IS_BITMAP_DATA (bitmap->relay))
391 return;
392 if (swfdec_depth_classify (depth) == SWFDEC_DEPTH_CLASS_EMPTY)
393 return;
395 movie = swfdec_movie_find (parent, depth);
396 if (movie)
397 swfdec_movie_remove (movie);
399 swfdec_bitmap_movie_new (parent, SWFDEC_BITMAP_DATA (bitmap->relay), depth);
400 SWFDEC_LOG ("created new BitmapMovie to parent %s at depth %d",
401 parent->name, depth);
404 SWFDEC_AS_NATIVE (900, 26, swfdec_sprite_movie_getRect)
405 void
406 swfdec_sprite_movie_getRect (SwfdecAsContext *cx, SwfdecAsObject *object,
407 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
409 SWFDEC_STUB ("MovieClip.getRect");
412 SWFDEC_AS_NATIVE (900, 12, swfdec_sprite_movie_play)
413 void
414 swfdec_sprite_movie_play (SwfdecAsContext *cx, SwfdecAsObject *object,
415 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
417 SwfdecSpriteMovie *movie;
419 SWFDEC_AS_CHECK (SWFDEC_TYPE_SPRITE_MOVIE, &movie, "");
421 movie->playing = TRUE;
424 SWFDEC_AS_NATIVE (900, 13, swfdec_sprite_movie_stop)
425 void
426 swfdec_sprite_movie_stop (SwfdecAsContext *cx, SwfdecAsObject *object,
427 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
429 SwfdecSpriteMovie *movie;
431 SWFDEC_AS_CHECK (SWFDEC_TYPE_SPRITE_MOVIE, &movie, "");
433 movie->playing = FALSE;
436 SWFDEC_AS_NATIVE (900, 7, swfdec_sprite_movie_getBytesLoaded)
437 void
438 swfdec_sprite_movie_getBytesLoaded (SwfdecAsContext *cx, SwfdecAsObject *object,
439 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
441 SwfdecMovie *movie;
442 SwfdecResource *resource;
444 SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE, &movie, "");
446 resource = swfdec_movie_get_own_resource (movie);
447 if (resource && resource->decoder) {
448 *rval = swfdec_as_value_from_integer (cx, resource->decoder->bytes_loaded);
449 } else {
450 *rval = swfdec_as_value_from_integer (cx, 0);
454 SWFDEC_AS_NATIVE (900, 6, swfdec_sprite_movie_getBytesTotal)
455 void
456 swfdec_sprite_movie_getBytesTotal (SwfdecAsContext *cx, SwfdecAsObject *object,
457 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
459 SwfdecMovie *movie;
460 SwfdecResource *resource;
462 SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE, &movie, "");
464 resource = swfdec_movie_get_own_resource (movie);
465 if (resource) {
466 if (resource->decoder) {
467 *rval = swfdec_as_value_from_integer (cx, resource->decoder->bytes_total);
468 } else {
469 *rval = swfdec_as_value_from_integer (cx, -1);
471 } else {
472 *rval = swfdec_as_value_from_integer (cx, 0);
476 SWFDEC_AS_NATIVE (900, 22, swfdec_sprite_movie_getNextHighestDepth)
477 void
478 swfdec_sprite_movie_getNextHighestDepth (SwfdecAsContext *cx, SwfdecAsObject *object,
479 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
481 SwfdecMovie *movie;
482 int depth;
484 SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE, &movie, "");
486 if (movie->list) {
487 depth = SWFDEC_MOVIE (g_list_last (movie->list)->data)->depth + 1;
488 if (depth < 0)
489 depth = 0;
490 } else {
491 depth = 0;
493 *rval = swfdec_as_value_from_integer (cx, depth);
496 static void
497 swfdec_sprite_movie_do_goto (SwfdecSpriteMovie *movie, SwfdecAsValue *target)
499 int frame;
501 g_return_if_fail (SWFDEC_IS_SPRITE_MOVIE (movie));
502 g_return_if_fail (movie->sprite != NULL);
504 if (SWFDEC_AS_VALUE_IS_STRING (*target)) {
505 const char *label = SWFDEC_AS_VALUE_GET_STRING (*target);
506 frame = swfdec_sprite_get_frame (movie->sprite, label);
507 /* FIXME: nonexisting frames? */
508 if (frame == -1)
509 return;
510 frame++;
511 } else {
512 frame = swfdec_as_value_to_integer (swfdec_gc_object_get_context (movie), *target);
514 /* FIXME: how to handle overflow? */
515 frame = CLAMP (frame, 1, (int) movie->n_frames);
517 swfdec_sprite_movie_goto (movie, frame);
520 SWFDEC_AS_NATIVE (900, 16, swfdec_sprite_movie_gotoAndPlay)
521 void
522 swfdec_sprite_movie_gotoAndPlay (SwfdecAsContext *cx, SwfdecAsObject *object,
523 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
525 SwfdecSpriteMovie *movie;
526 SwfdecAsValue val;
528 SWFDEC_AS_CHECK (SWFDEC_TYPE_SPRITE_MOVIE, &movie, "v", &val);
530 if (movie->sprite == NULL)
531 return;
533 swfdec_sprite_movie_do_goto (movie, &val);
534 movie->playing = TRUE;
537 SWFDEC_AS_NATIVE (900, 17, swfdec_sprite_movie_gotoAndStop)
538 void
539 swfdec_sprite_movie_gotoAndStop (SwfdecAsContext *cx, SwfdecAsObject *object,
540 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
542 SwfdecSpriteMovie *movie;
543 SwfdecAsValue val;
545 SWFDEC_AS_CHECK (SWFDEC_TYPE_SPRITE_MOVIE, &movie, "v", &val);
547 if (movie->sprite == NULL)
548 return;
550 swfdec_sprite_movie_do_goto (movie, &val);
551 movie->playing = FALSE;
554 SWFDEC_AS_NATIVE (900, 14, swfdec_sprite_movie_nextFrame)
555 void
556 swfdec_sprite_movie_nextFrame (SwfdecAsContext *cx, SwfdecAsObject *object,
557 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
559 SwfdecSpriteMovie *movie;
561 SWFDEC_AS_CHECK (SWFDEC_TYPE_SPRITE_MOVIE, &movie, "");
563 swfdec_sprite_movie_goto (movie, movie->frame + 1);
564 movie->playing = FALSE;
567 SWFDEC_AS_NATIVE (900, 15, swfdec_sprite_movie_prevFrame)
568 void
569 swfdec_sprite_movie_prevFrame (SwfdecAsContext *cx, SwfdecAsObject *object,
570 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
572 SwfdecSpriteMovie *movie;
574 SWFDEC_AS_CHECK (SWFDEC_TYPE_SPRITE_MOVIE, &movie, "");
576 swfdec_sprite_movie_goto (movie, movie->frame - 1);
577 movie->playing = FALSE;
580 SWFDEC_AS_NATIVE (900, 4, swfdec_sprite_movie_hitTest)
581 void
582 swfdec_sprite_movie_hitTest (SwfdecAsContext *cx, SwfdecAsObject *object,
583 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
585 SwfdecMovie *movie;
587 SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE, &movie, "");
589 if (argc == 1) {
590 SwfdecMovie *other;
591 SwfdecRect movie_rect, other_rect;
593 SWFDEC_AS_VALUE_SET_BOOLEAN (rval, FALSE);
594 SWFDEC_AS_CHECK (0, NULL, "m", &other);
596 swfdec_movie_update (movie);
597 swfdec_movie_update (other);
598 movie_rect = movie->extents;
599 if (movie->parent)
600 swfdec_movie_rect_local_to_global (movie->parent, &movie_rect);
601 other_rect = other->extents;
602 if (other->parent)
603 swfdec_movie_rect_local_to_global (other->parent, &other_rect);
604 SWFDEC_AS_VALUE_SET_BOOLEAN (rval, swfdec_rect_intersect (NULL, &movie_rect, &other_rect));
605 } else if (argc >= 2) {
606 double x, y;
607 gboolean shape = FALSE;
608 gboolean ret;
610 SWFDEC_AS_CHECK (0, NULL, "nn|b", &x, &y, &shape);
611 x *= SWFDEC_TWIPS_SCALE_FACTOR;
612 y *= SWFDEC_TWIPS_SCALE_FACTOR;
614 if (shape) {
615 if (movie->parent)
616 swfdec_movie_global_to_local (movie->parent, &x, &y);
617 ret = swfdec_movie_contains (movie, x, y);
618 } else {
619 if (movie->cache_state >= SWFDEC_MOVIE_INVALID_EXTENTS)
620 swfdec_movie_update (movie);
621 swfdec_movie_global_to_local (movie, &x, &y);
622 ret = swfdec_rect_contains (&movie->original_extents, x, y);
624 SWFDEC_AS_VALUE_SET_BOOLEAN (rval, ret);
628 SWFDEC_AS_NATIVE (900, 20, swfdec_sprite_movie_startDrag)
629 void
630 swfdec_sprite_movie_startDrag (SwfdecAsContext *cx, SwfdecAsObject *object,
631 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
633 SwfdecActor *actor;
634 SwfdecPlayer *player = SWFDEC_PLAYER (cx);
635 gboolean center = FALSE;
637 SWFDEC_AS_CHECK (SWFDEC_TYPE_ACTOR, &actor, "");
639 if (argc > 0) {
640 center = swfdec_as_value_to_boolean (cx, argv[0]);
642 if (argc >= 5) {
643 SwfdecRect rect;
644 rect.x0 = swfdec_as_value_to_number (cx, argv[1]);
645 rect.y0 = swfdec_as_value_to_number (cx, argv[2]);
646 rect.x1 = swfdec_as_value_to_number (cx, argv[3]);
647 rect.y1 = swfdec_as_value_to_number (cx, argv[4]);
648 swfdec_rect_scale (&rect, &rect, SWFDEC_TWIPS_SCALE_FACTOR);
649 swfdec_player_set_drag_movie (player, actor, center, &rect);
650 } else {
651 swfdec_player_set_drag_movie (player, actor, center, NULL);
655 SWFDEC_AS_NATIVE (900, 21, swfdec_sprite_movie_stopDrag)
656 void
657 swfdec_sprite_movie_stopDrag (SwfdecAsContext *cx, SwfdecAsObject *object,
658 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
660 // FIXME: Should this work when called on non-movie objects or not?
662 swfdec_player_set_drag_movie (SWFDEC_PLAYER (cx), NULL, FALSE, NULL);
665 SWFDEC_AS_NATIVE (900, 1, swfdec_sprite_movie_swapDepths)
666 void
667 swfdec_sprite_movie_swapDepths (SwfdecAsContext *cx, SwfdecAsObject *object,
668 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
670 SwfdecMovie *movie, *other;
671 SwfdecAsValue value;
672 int depth;
674 SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE, &movie, "v", &value);
676 if (movie->parent == NULL)
677 SWFDEC_FIXME ("swapDepths on root movie, should do something weird");
679 if (SWFDEC_AS_VALUE_IS_MOVIE (value)) {
680 other = SWFDEC_AS_VALUE_GET_MOVIE (value);
681 if (other == NULL || other->parent != movie->parent)
682 return;
683 depth = other->depth;
684 } else {
685 depth = swfdec_as_value_to_integer (cx, value);
686 if (movie->parent) {
687 other = swfdec_movie_find (movie->parent, depth);
688 } else {
689 // special case: if root movie: we won't swap, but just set depth
690 other = NULL;
694 // FIXME: one different than the reserved range, should the classify function
695 // be changed instead?
696 if (swfdec_depth_classify (depth) == SWFDEC_DEPTH_CLASS_EMPTY ||
697 depth >= 2130690045)
698 return;
700 if (other)
701 swfdec_movie_set_depth (other, movie->depth);
702 swfdec_movie_set_depth (movie, depth);
705 SWFDEC_AS_NATIVE (901, 0, swfdec_sprite_movie_createEmptyMovieClip)
706 void
707 swfdec_sprite_movie_createEmptyMovieClip (SwfdecAsContext *cx, SwfdecAsObject *object,
708 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
710 SwfdecMovie *movie, *parent;
711 SwfdecSandbox *sandbox;
712 int depth;
713 const char *name;
715 SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE, &parent, "si", &name, &depth);
717 movie = swfdec_movie_find (parent, depth);
718 if (movie)
719 swfdec_movie_remove (movie);
720 movie = swfdec_movie_new (SWFDEC_PLAYER (cx), depth, parent, parent->resource, NULL, name);
722 sandbox = swfdec_sandbox_get (SWFDEC_PLAYER (cx));
723 swfdec_sandbox_unuse (sandbox);
724 swfdec_movie_initialize (movie);
725 swfdec_actor_execute (SWFDEC_ACTOR (movie), SWFDEC_EVENT_CONSTRUCT, 0);
726 swfdec_sandbox_use (sandbox);
728 SWFDEC_AS_VALUE_SET_MOVIE (rval, movie);
731 static void
732 swfdec_sprite_movie_copy_props (SwfdecMovie *target, SwfdecMovie *src)
734 swfdec_movie_begin_update_matrix (target);
735 target->matrix = src->matrix;
736 target->modified = src->modified;
737 target->xscale = src->xscale;
738 target->yscale = src->yscale;
739 target->rotation = src->rotation;
740 target->lockroot = src->lockroot;
741 target->color_transform = src->color_transform;
742 swfdec_movie_end_update_matrix (target);
745 static gboolean
746 swfdec_sprite_movie_foreach_copy_properties (SwfdecAsObject *object,
747 const char *variable, SwfdecAsValue *value, guint flags, gpointer data)
749 SwfdecMovie *target = SWFDEC_MOVIE (data);
751 /* FIXME: We likely need better flag handling here.
752 * We might even want to fix swfdec_as_object_foreach() */
753 if (flags & SWFDEC_AS_VARIABLE_HIDDEN)
754 return TRUE;
756 swfdec_as_object_set_variable (swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (target)),
757 variable, value);
759 return TRUE;
762 static void
763 swfdec_sprite_movie_init_from_object (SwfdecMovie *movie,
764 SwfdecAsObject *initObject)
766 g_return_if_fail (SWFDEC_IS_MOVIE (movie));
768 if (initObject != NULL) {
769 SwfdecAsContext *cx = swfdec_gc_object_get_context (movie);
770 if (cx->version <= 6) {
771 swfdec_as_object_foreach (initObject,
772 swfdec_sprite_movie_foreach_copy_properties, movie);
773 swfdec_movie_initialize (movie);
774 } else {
775 swfdec_movie_initialize (movie);
776 swfdec_as_object_foreach (initObject,
777 swfdec_sprite_movie_foreach_copy_properties, movie);
779 } else {
780 swfdec_movie_initialize (movie);
783 if (SWFDEC_IS_SPRITE_MOVIE (movie)) {
784 SwfdecSandbox *sandbox = movie->resource->sandbox;
785 SwfdecActor *actor = SWFDEC_ACTOR (movie);
786 swfdec_actor_queue_script (actor, SWFDEC_EVENT_INITIALIZE);
787 swfdec_actor_queue_script (actor, SWFDEC_EVENT_LOAD);
788 swfdec_sandbox_unuse (sandbox);
789 swfdec_actor_execute (actor, SWFDEC_EVENT_CONSTRUCT, 0);
790 swfdec_sandbox_use (sandbox);
794 SWFDEC_AS_NATIVE (900, 0, swfdec_sprite_movie_attachMovie)
795 void
796 swfdec_sprite_movie_attachMovie (SwfdecAsContext *cx, SwfdecAsObject *object,
797 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
799 SwfdecMovie *movie;
800 SwfdecMovie *ret;
801 SwfdecAsObject *initObject = NULL, *constructor, *o;
802 const char *name, *export;
803 int depth;
804 SwfdecGraphic *sprite;
806 SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE, &movie, "ssi|O", &export, &name, &depth, &initObject);
808 sprite = swfdec_resource_get_export (movie->resource, export);
809 if (!SWFDEC_IS_SPRITE (sprite)) {
810 if (sprite == NULL) {
811 SWFDEC_WARNING ("no symbol with name %s exported", export);
812 } else {
813 SWFDEC_WARNING ("can only use attachMovie with sprites");
815 return;
817 if (swfdec_depth_classify (depth) == SWFDEC_DEPTH_CLASS_EMPTY)
818 return;
819 ret = swfdec_movie_find (movie, depth);
820 if (ret)
821 swfdec_movie_remove (ret);
822 ret = swfdec_movie_new (SWFDEC_PLAYER (cx),
823 depth, movie, movie->resource, sprite, name);
824 SWFDEC_LOG ("attached %s (%u) as %s to depth %u", export, SWFDEC_CHARACTER (sprite)->id,
825 ret->name, ret->depth);
826 /* run init and construct */
827 constructor = swfdec_player_get_export_class (SWFDEC_PLAYER (cx), export);
828 o = swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (ret));
829 if (constructor == NULL) {
830 swfdec_as_object_set_constructor_by_name (o, SWFDEC_AS_STR_MovieClip, NULL);
831 } else {
832 swfdec_as_object_set_constructor (o, constructor);
835 swfdec_sprite_movie_init_from_object (ret, initObject);
836 SWFDEC_AS_VALUE_SET_MOVIE (rval, ret);
839 SWFDEC_AS_NATIVE (900, 18, swfdec_sprite_movie_duplicateMovieClip)
840 void
841 swfdec_sprite_movie_duplicateMovieClip (SwfdecAsContext *cx, SwfdecAsObject *object,
842 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
844 SwfdecMovie *movie;
845 SwfdecMovie *new;
846 const char *name;
847 int depth;
849 SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE, &movie, "si", &name, &depth);
851 if (swfdec_depth_classify (depth) == SWFDEC_DEPTH_CLASS_EMPTY)
852 return;
853 new = swfdec_movie_duplicate (movie, name, depth);
854 if (new == NULL)
855 return;
856 swfdec_sprite_movie_copy_props (new, movie);
857 SWFDEC_LOG ("duplicated %s as %s to depth %u", movie->name, new->name, new->depth);
858 SWFDEC_AS_VALUE_SET_MOVIE (rval, new);
861 SWFDEC_AS_NATIVE (900, 19, swfdec_sprite_movie_removeMovieClip)
862 void
863 swfdec_sprite_movie_removeMovieClip (SwfdecAsContext *cx, SwfdecAsObject *object,
864 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
866 SwfdecMovie *movie;
868 SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE, &movie, "");
870 if (swfdec_depth_classify (movie->depth) == SWFDEC_DEPTH_CLASS_DYNAMIC)
871 swfdec_movie_remove (movie);
874 SWFDEC_AS_NATIVE (900, 10, swfdec_sprite_movie_getDepth)
875 void
876 swfdec_sprite_movie_getDepth (SwfdecAsContext *cx, SwfdecAsObject *object,
877 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
879 SwfdecMovie *movie;
881 SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE, &movie, "");
883 *rval = swfdec_as_value_from_integer (cx, movie->depth);
886 SWFDEC_AS_NATIVE (900, 5, swfdec_sprite_movie_getBounds)
887 void
888 swfdec_sprite_movie_getBounds (SwfdecAsContext *cx, SwfdecAsObject *object,
889 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
891 int x0, x1, y0, y1;
892 SwfdecAsValue val;
893 SwfdecAsObject *obj;
894 SwfdecMovie *movie;
896 SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE, &movie, "");
898 obj= swfdec_as_object_new_empty (cx);
900 swfdec_movie_update (movie);
901 if (swfdec_rect_is_empty (&movie->extents)) {
902 x0 = x1 = y0 = y1 = 0x7FFFFFF;
903 } else {
904 SwfdecRect rect = movie->extents;
905 SwfdecMovie *other;
907 if (argc > 0) {
908 other =
909 swfdec_player_get_movie_from_value (SWFDEC_PLAYER (cx), &argv[0]);
910 if (!other)
911 return;
912 } else {
913 other = movie;
916 if (movie->parent)
917 swfdec_movie_rect_local_to_global (movie->parent, &rect);
918 swfdec_movie_rect_global_to_local (other, &rect);
920 x0 = rect.x0;
921 y0 = rect.y0;
922 x1 = rect.x1;
923 y1 = rect.y1;
925 val = swfdec_as_value_from_number (cx, SWFDEC_TWIPS_TO_DOUBLE (x0));
926 swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_xMin, &val);
927 val = swfdec_as_value_from_number (cx, SWFDEC_TWIPS_TO_DOUBLE (y0));
928 swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_yMin, &val);
929 val = swfdec_as_value_from_number (cx, SWFDEC_TWIPS_TO_DOUBLE (x1));
930 swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_xMax, &val);
931 val = swfdec_as_value_from_number (cx, SWFDEC_TWIPS_TO_DOUBLE (y1));
932 swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_yMax, &val);
934 SWFDEC_AS_VALUE_SET_OBJECT (rval, obj);
937 SWFDEC_AS_NATIVE (900, 11, swfdec_sprite_movie_setMask)
938 void
939 swfdec_sprite_movie_setMask (SwfdecAsContext *cx, SwfdecAsObject *object,
940 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
942 SwfdecMovie *movie, *mask;
944 /* yes, this works with regular movies */
945 SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE, &movie, "M", &mask);
947 if (argc > 0 && mask == NULL && !SWFDEC_AS_VALUE_IS_NULL (argv[0])) {
948 SWFDEC_FIXME ("mask is not a movie and not null, what now?");
949 mask = NULL;
951 if (movie->masked_by)
952 movie->masked_by->mask_of = NULL;
953 if (movie->mask_of)
954 movie->mask_of->masked_by = NULL;
955 movie->masked_by = mask;
956 movie->mask_of = NULL;
957 if (movie->clip_depth) {
958 g_assert (movie->parent);
959 swfdec_movie_invalidate_last (movie->parent);
960 movie->clip_depth = 0;
961 } else {
962 swfdec_movie_invalidate_last (movie);
964 if (mask) {
965 if (mask->masked_by)
966 mask->masked_by->mask_of = NULL;
967 if (mask->mask_of)
968 mask->mask_of->masked_by = NULL;
969 mask->masked_by = NULL;
970 mask->mask_of = movie;
971 swfdec_movie_invalidate_last (mask);
972 if (mask->clip_depth) {
973 g_assert (mask->parent);
974 swfdec_movie_invalidate_last (mask->parent);
975 mask->clip_depth = 0;
976 } else {
977 swfdec_movie_invalidate_last (mask);