Benjamin Otte
2007-Jun-18 21:59 UTC
[Swfdec] Branch 'as' - 8 commits - libswfdec/swfdec_movie.c libswfdec/swfdec_sprite.c libswfdec/swfdec_sprite.h libswfdec/swfdec_sprite_movie.c libswfdec/swfdec_sprite_movie.h libswfdec/swfdec_swf_decoder.c libswfdec/swfdec_swf_decoder.h libswfdec/swfdec_swf_instance.c libswfdec/swfdec_tag.c libswfdec/swfdec_tag.h test/image
libswfdec/swfdec_movie.c | 18 - libswfdec/swfdec_sprite.c | 308 ++---------------------------- libswfdec/swfdec_sprite.h | 36 +-- libswfdec/swfdec_sprite_movie.c | 357 ++++++++++++++++++++++++++++------- libswfdec/swfdec_sprite_movie.h | 12 - libswfdec/swfdec_swf_decoder.c | 32 ++- libswfdec/swfdec_swf_decoder.h | 11 + libswfdec/swfdec_swf_instance.c | 2 libswfdec/swfdec_tag.c | 75 +++++-- libswfdec/swfdec_tag.h | 35 +-- test/image/Makefile.am | 7 test/image/duplicate-depth-5.swf |binary test/image/duplicate-depth-5.swf.png |binary test/image/duplicate-depth-6.swf |binary test/image/duplicate-depth-6.swf.png |binary test/image/duplicate-depth-7.swf |binary test/image/duplicate-depth-7.swf.png |binary test/image/duplicate-depth.c | 89 ++++++++ 18 files changed, 560 insertions(+), 422 deletions(-) New commits: diff-tree 56c57b5b317120e3699c0c673942815691c9fa2e (from 4ff5c4320533e5c517fe0bba7e19c58242ccc290) Author: Benjamin Otte <otte at gnome.org> Date: Mon Jun 18 23:51:40 2007 +0200 add tests for duplicate depths and their stacking order. diff --git a/test/image/Makefile.am b/test/image/Makefile.am index bbdbb2d..44c9149 100644 --- a/test/image/Makefile.am +++ b/test/image/Makefile.am @@ -12,6 +12,13 @@ EXTRA_DIST = \ color-transform-add80.swf.png \ color-transform-add80-alpha.swf \ color-transform-add80-alpha.swf.png \ + duplicate-depth.c \ + duplicate-depth-5.swf \ + duplicate-depth-5.swf.png \ + duplicate-depth-6.swf \ + duplicate-depth-6.swf.png \ + duplicate-depth-7.swf \ + duplicate-depth-7.swf.png \ image-jpeg-alpha.swf \ image-jpeg-alpha.swf.png \ image-lossless-alpha.swf \ diff --git a/test/image/duplicate-depth-5.swf b/test/image/duplicate-depth-5.swf new file mode 100644 index 0000000..66109fd Binary files /dev/null and b/test/image/duplicate-depth-5.swf differ diff --git a/test/image/duplicate-depth-5.swf.png b/test/image/duplicate-depth-5.swf.png new file mode 100644 index 0000000..cbabddd Binary files /dev/null and b/test/image/duplicate-depth-5.swf.png differ diff --git a/test/image/duplicate-depth-6.swf b/test/image/duplicate-depth-6.swf new file mode 100644 index 0000000..cd12fa1 Binary files /dev/null and b/test/image/duplicate-depth-6.swf differ diff --git a/test/image/duplicate-depth-6.swf.png b/test/image/duplicate-depth-6.swf.png new file mode 100644 index 0000000..9fa8fe6 Binary files /dev/null and b/test/image/duplicate-depth-6.swf.png differ diff --git a/test/image/duplicate-depth-7.swf b/test/image/duplicate-depth-7.swf new file mode 100644 index 0000000..d31f275 Binary files /dev/null and b/test/image/duplicate-depth-7.swf differ diff --git a/test/image/duplicate-depth-7.swf.png b/test/image/duplicate-depth-7.swf.png new file mode 100644 index 0000000..9fa8fe6 Binary files /dev/null and b/test/image/duplicate-depth-7.swf.png differ diff --git a/test/image/duplicate-depth.c b/test/image/duplicate-depth.c new file mode 100644 index 0000000..180b696 --- /dev/null +++ b/test/image/duplicate-depth.c @@ -0,0 +1,89 @@ +/* gcc `pkg-config --libs --cflags libming glib-2.0` duplicate-depth.c -o duplicate-depth && ./duplicate-depth + */ + +#include <ming.h> +#include <glib.h> + +static void +add_rectangle (SWFMovieClip clip, int r, int g, int b) +{ + SWFShape shape; + SWFFillStyle fill; + + shape = newSWFShape (); + fill = SWFShape_addSolidFillStyle (shape, r, g, b, 255); + SWFShape_setRightFillStyle (shape, fill); + SWFShape_drawLineTo (shape, 50, 0); + SWFShape_drawLineTo (shape, 50, 50); + SWFShape_drawLineTo (shape, 0, 50); + SWFShape_drawLineTo (shape, 0, 0); + + SWFMovieClip_add (clip, (SWFBlock) shape); +} + +static void +modify_placement (SWFMovie movie, guint mod) +{ + SWFDisplayItem item; + SWFBlock clip, clip2; + + clip = (SWFBlock) newSWFMovieClip (); + add_rectangle ((SWFMovieClip) clip, 255, 0, 0); + SWFMovieClip_nextFrame ((SWFMovieClip) clip); + clip2 = (SWFBlock) newSWFMovieClip (); + add_rectangle ((SWFMovieClip) clip2, 0, 0, 255); + SWFMovieClip_nextFrame ((SWFMovieClip) clip2); + + item = SWFMovie_add (movie, clip); + SWFDisplayItem_setDepth (item, 1); + SWFDisplayItem_setName (item, "a"); + SWFMovie_nextFrame (movie); + + item = SWFMovie_add (movie, clip2); + SWFDisplayItem_setDepth (item, 1); + SWFDisplayItem_moveTo (item, 20, 20); + SWFDisplayItem_setName (item, "b"); +} + +static void +do_movie (int version) +{ + SWFMovie movie; + char *real_name; + guint i; + + movie = newSWFMovieWithVersion (version); + movie = newSWFMovie(); + SWFMovie_setRate (movie, 1); + SWFMovie_setDimension (movie, 200, 150); + + modify_placement (movie, i); + SWFMovie_nextFrame (movie); + + SWFMovie_add (movie, (SWFBlock) newSWFAction ("" +#if 0 + "loadMovie (\"FSCommand:quit\", \"\");" +#else + "stop ();" +#endif + )); + SWFMovie_nextFrame (movie); + + real_name = g_strdup_printf ("duplicate-depth-%d.swf", version); + SWFMovie_save (movie, real_name); + g_free (real_name); +} + +int +main (int argc, char **argv) +{ + int i; + + if (Ming_init ()) + return 1; + + for (i = 5; i < 8; i++) + do_movie (i); + + return 0; +} diff-tree 4ff5c4320533e5c517fe0bba7e19c58242ccc290 (from 050e05430d2e69be906db321a16eeaf26513b17d) Author: Benjamin Otte <otte at gnome.org> Date: Mon Jun 18 23:50:10 2007 +0200 allow adding movies in occupied depths in Flash <= 5 This might cause issues, if there is code that assumes depths contain not more than one movie. These are probably just g_return_if_fail or assert checks which can be safely removed, but who knows... diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c index f5019c3..5f57f9b 100644 --- a/libswfdec/swfdec_movie.c +++ b/libswfdec/swfdec_movie.c @@ -883,11 +883,6 @@ swfdec_movie_new (SwfdecPlayer *player, g_return_val_if_fail (SWFDEC_IS_PLAYER (player), NULL); g_return_val_if_fail (depth > -16385, NULL); /* the lower depths are for deleted movies */ g_return_val_if_fail (parent == NULL || SWFDEC_IS_MOVIE (parent), NULL); - if (parent) { - g_return_val_if_fail (swfdec_movie_find (parent, depth) == NULL, NULL); - } else { - /* FIXME: do a find on player here */ - } g_return_val_if_fail (graphic == NULL || SWFDEC_IS_GRAPHIC (graphic), NULL); /* create the right movie */ diff --git a/libswfdec/swfdec_sprite_movie.c b/libswfdec/swfdec_sprite_movie.c index e6430a3..89b076f 100644 --- a/libswfdec/swfdec_sprite_movie.c +++ b/libswfdec/swfdec_sprite_movie.c @@ -247,7 +247,7 @@ swfdec_sprite_movie_perform_place (Swfde has_ctrans ? &ctrans : NULL, ratio, clip_depth, events); } else { SwfdecGraphic *graphic; - if (cur != NULL) { + if (cur != NULL && version > 5) { SWFDEC_INFO ("depth %d is already occupied by movie %s, not placing", depth, cur->name); return TRUE; } diff-tree 050e05430d2e69be906db321a16eeaf26513b17d (from 0ca7a97fe2449e4fc4c63789ee59dafb07cf5175) Author: Benjamin Otte <otte at gnome.org> Date: Mon Jun 18 23:43:55 2007 +0200 abort on a place if the place has no character diff --git a/libswfdec/swfdec_sprite_movie.c b/libswfdec/swfdec_sprite_movie.c index 139e01d..e6430a3 100644 --- a/libswfdec/swfdec_sprite_movie.c +++ b/libswfdec/swfdec_sprite_movie.c @@ -254,7 +254,7 @@ swfdec_sprite_movie_perform_place (Swfde graphic = swfdec_swf_decoder_get_character (SWFDEC_SWF_DECODER (mov->swf->decoder), id); if (!SWFDEC_IS_GRAPHIC (graphic)) { SWFDEC_FIXME ("character %u is not a graphic (does it even exist?), aborting", id); - return TRUE; + return FALSE; } cur = swfdec_movie_new (player, depth, mov, graphic, name); swfdec_movie_set_static_properties (cur, has_transform ? &transform : NULL, diff-tree 0ca7a97fe2449e4fc4c63789ee59dafb07cf5175 (from d55b3b31fa7300ace9dc3ae107966d5fda9e1d6e) Author: Benjamin Otte <otte at gnome.org> Date: Mon Jun 18 23:43:19 2007 +0200 only trigger events for sprite movies diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c index a1c9be6..f5019c3 100644 --- a/libswfdec/swfdec_movie.c +++ b/libswfdec/swfdec_movie.c @@ -257,7 +257,10 @@ swfdec_movie_do_remove (SwfdecMovie *mov if (movie->parent) movie->parent->list = g_list_sort (movie->parent->list, swfdec_movie_compare_depths); - return !swfdec_movie_queue_script (movie, SWFDEC_EVENT_UNLOAD); + if (SWFDEC_IS_SPRITE_MOVIE (movie)) + return !swfdec_movie_queue_script (movie, SWFDEC_EVENT_UNLOAD); + else + return TRUE; } /** @@ -1000,9 +1003,11 @@ swfdec_movie_new_for_content (SwfdecMovi swfdec_movie_set_static_properties (movie, content->has_transform ? &content->transform : NULL, content->has_color_transform ? &content->color_transform : NULL, content->ratio, content->clip_depth, content->events); - g_queue_push_tail (player->init_queue, movie); - g_queue_push_tail (player->construct_queue, movie); - swfdec_movie_queue_script (movie, SWFDEC_EVENT_LOAD); + if (SWFDEC_IS_SPRITE_MOVIE (movie)) { + g_queue_push_tail (player->init_queue, movie); + g_queue_push_tail (player->construct_queue, movie); + swfdec_movie_queue_script (movie, SWFDEC_EVENT_LOAD); + } swfdec_movie_initialize (movie); return movie; diff --git a/libswfdec/swfdec_sprite_movie.c b/libswfdec/swfdec_sprite_movie.c index 28570ed..139e01d 100644 --- a/libswfdec/swfdec_sprite_movie.c +++ b/libswfdec/swfdec_sprite_movie.c @@ -253,15 +253,17 @@ swfdec_sprite_movie_perform_place (Swfde } graphic = swfdec_swf_decoder_get_character (SWFDEC_SWF_DECODER (mov->swf->decoder), id); if (!SWFDEC_IS_GRAPHIC (graphic)) { - SWFDEC_FIXME ("character %u is not a graphic (does it eve exist?), ignoring", id); + SWFDEC_FIXME ("character %u is not a graphic (does it even exist?), aborting", id); return TRUE; } cur = swfdec_movie_new (player, depth, mov, graphic, name); swfdec_movie_set_static_properties (cur, has_transform ? &transform : NULL, has_ctrans ? &ctrans : NULL, ratio, clip_depth, events); - g_queue_push_tail (player->init_queue, cur); - g_queue_push_tail (player->construct_queue, cur); - swfdec_movie_queue_script (cur, SWFDEC_EVENT_LOAD); + if (SWFDEC_IS_SPRITE_MOVIE (cur)) { + g_queue_push_tail (player->init_queue, cur); + g_queue_push_tail (player->construct_queue, cur); + swfdec_movie_queue_script (cur, SWFDEC_EVENT_LOAD); + } swfdec_movie_initialize (cur); } diff-tree d55b3b31fa7300ace9dc3ae107966d5fda9e1d6e (from d60a5d10e7a597d244cdffc1b900a557d237e437) Author: Benjamin Otte <otte at gnome.org> Date: Mon Jun 18 17:18:52 2007 +0200 move palce/remove tag handling from startup to on-demand. See http://lists.freedesktop.org/archives/swfdec/2007-June/000315.html for a rationale. Most of the lines in this diff is moving the parsers (in particular the PlaceObject parser) from swfdec_sprite.c to swfdec_sprite_movie.c. This patch achieves the following: - DisplayList tags are no longer parsed and put into a SwfdecContent structure, and then added to a sprites SwfdecFrame structure, but instead queued in sprite->actions, which is a list of tag/buffer tuples. - swfdec_sprite_movie_perform_one_action() is now given one tag/buffer tuple, parses it and executes it. - ShowFrame tags are now handled differently. They are queued into sprite->actions. swfdec_sprite_movie_perform_actions() stops when it encounters this tag. Stuff known to still be missing: - sprite->actions should be a GList. This needs a nicer way to store tag/buffer tuples first. - sprite->frames contents should stop exisiting. All its contents should be put into sprite->actions instead. This is mainly pending on an overhaul of the audio handlers. - SwfdecRootActions should probably be queued in sprite->actions instead of SwfdecSwfDecoder. diff --git a/libswfdec/swfdec_sprite.c b/libswfdec/swfdec_sprite.c index 9786f3b..fb3b111 100644 --- a/libswfdec/swfdec_sprite.c +++ b/libswfdec/swfdec_sprite.c @@ -59,32 +59,18 @@ swfdec_sprite_dispose (GObject *object) if (sprite->frames[i].sound_block) { swfdec_buffer_unref (sprite->frames[i].sound_block); } - if (sprite->frames[i].actions) { - guint j; - for (j = 0; j < sprite->frames[i].actions->len; j++) { - SwfdecSpriteAction *action = - &g_array_index (sprite->frames[i].actions, SwfdecSpriteAction, j); - switch (action->type) { - case SWFDEC_SPRITE_ACTION_SCRIPT: - swfdec_script_unref (action->data); - break; - case SWFDEC_SPRITE_ACTION_ADD: - case SWFDEC_SPRITE_ACTION_UPDATE: - swfdec_content_free (action->data); - break; - case SWFDEC_SPRITE_ACTION_REMOVE: - break; - default: - g_assert_not_reached (); - } - } - g_array_free (sprite->frames[i].actions, TRUE); - } g_slist_foreach (sprite->frames[i].sound, (GFunc) swfdec_sound_chunk_free, NULL); g_slist_free (sprite->frames[i].sound); } g_free(sprite->frames); } + for (i = 0; i < sprite->actions->len; i++) { + SwfdecSpriteAction *cur = &g_array_index (sprite->actions, SwfdecSpriteAction, i); + if (cur->buffer) + swfdec_buffer_unref (cur->buffer); + } + g_array_free (sprite->actions, TRUE); + sprite->actions = NULL; if (sprite->init_action) { swfdec_script_unref (sprite->init_action); sprite->init_action = NULL; @@ -118,62 +104,31 @@ swfdec_sprite_add_sound_chunk (SwfdecSpr SWFDEC_AUDIO_OUT_GRANULARITY (sprite->frames[frame].sound_head->original_format); } -static void -swfdec_sprite_remove_last_action (SwfdecSprite * sprite, guint frame_id) -{ - SwfdecSpriteFrame *frame; - - g_assert (frame_id < sprite->n_frames); - frame = &sprite->frames[frame_id]; - - g_assert (frame->actions != NULL); - g_assert (frame->actions->len > 0); - g_array_set_size (frame->actions, frame->actions->len - 1); -} - void -swfdec_sprite_add_action (SwfdecSprite *sprite, SwfdecSpriteActionType type, - gpointer data) +swfdec_sprite_add_action (SwfdecSprite *sprite, guint tag, SwfdecBuffer *buffer) { SwfdecSpriteAction action; - SwfdecSpriteFrame *frame; - g_assert (sprite->parse_frame < sprite->n_frames); - frame = &sprite->frames[sprite->parse_frame]; - - if (frame->actions == NULL) - frame->actions = g_array_new (FALSE, FALSE, sizeof (SwfdecSpriteAction)); - - action.type = type; - action.data = data; - g_array_append_val (frame->actions, action); -} - -static int -swfdec_get_clipeventflags (SwfdecSwfDecoder * s, SwfdecBits * bits) -{ - if (s->version <= 5) { - return swfdec_bits_get_u16 (bits); - } else { - return swfdec_bits_get_u32 (bits); - } -} - -int -tag_show_frame (SwfdecSwfDecoder * s, guint tag) -{ - SWFDEC_DEBUG("show_frame %d of id %d", s->parse_sprite->parse_frame, - SWFDEC_CHARACTER (s->parse_sprite)->id); - - s->parse_sprite->parse_frame++; - if (s->parse_sprite->parse_frame < s->parse_sprite->n_frames) { - SwfdecSpriteFrame *old = &s->parse_sprite->frames[s->parse_sprite->parse_frame - 1]; - SwfdecSpriteFrame *new = &s->parse_sprite->frames[s->parse_sprite->parse_frame]; - if (old->sound_head) - new->sound_head = g_object_ref (old->sound_head); - } - - return SWFDEC_STATUS_IMAGE; + action.tag = tag; + action.buffer = buffer; + g_array_append_val (sprite->actions, action); +} + +gboolean +swfdec_sprite_get_action (SwfdecSprite *sprite, guint n, guint *tag, SwfdecBuffer **buffer) +{ + SwfdecSpriteAction *action; + + g_return_val_if_fail (SWFDEC_IS_SPRITE (sprite), FALSE); + g_return_val_if_fail (tag != NULL, FALSE); + g_return_val_if_fail (buffer != NULL, FALSE); + + if (n >= sprite->actions->len) + return FALSE; + action = &g_array_index (sprite->actions, SwfdecSpriteAction, n); + *tag = action->tag; + *buffer = action->buffer; + return TRUE; } int @@ -213,212 +168,6 @@ swfdec_content_new (int depth) return content; } -static SwfdecContent * -swfdec_contents_create (SwfdecSprite *sprite, - int depth, gboolean move) -{ - SwfdecContent *content = swfdec_content_new (depth); - - swfdec_sprite_add_action (sprite, move ? SWFDEC_SPRITE_ACTION_UPDATE : SWFDEC_SPRITE_ACTION_ADD, content); - return content; -} - -static cairo_operator_t -swfdec_sprite_convert_operator (guint operator) -{ - return CAIRO_OPERATOR_OVER; -} - -int -swfdec_spriteseg_place_object (SwfdecSwfDecoder *s, guint tag) -{ - SwfdecBits *bits = &s->b; - int has_clip_actions; - int has_clip_depth; - int has_name; - int has_ratio; - int has_color_transform; - int has_matrix; - int has_character; - int move; - int depth; - int cache; - int has_blend_mode = 0; - int has_filter = 0; - SwfdecContent *content; - - has_clip_actions = swfdec_bits_getbit (bits); - has_clip_depth = swfdec_bits_getbit (bits); - has_name = swfdec_bits_getbit (bits); - has_ratio = swfdec_bits_getbit (bits); - has_color_transform = swfdec_bits_getbit (bits); - has_matrix = swfdec_bits_getbit (bits); - has_character = swfdec_bits_getbit (bits); - move = swfdec_bits_getbit (bits); - - SWFDEC_LOG (" has_clip_actions = %d", has_clip_actions); - SWFDEC_LOG (" has_clip_depth = %d", has_clip_depth); - SWFDEC_LOG (" has_name = %d", has_name); - SWFDEC_LOG (" has_ratio = %d", has_ratio); - SWFDEC_LOG (" has_color_transform = %d", has_color_transform); - SWFDEC_LOG (" has_matrix = %d", has_matrix); - SWFDEC_LOG (" has_character = %d", has_character); - SWFDEC_LOG (" move = %d", move); - - if (tag == SWFDEC_TAG_PLACEOBJECT3) { - swfdec_bits_getbits (bits, 5); - cache = swfdec_bits_getbit (bits); - has_blend_mode = swfdec_bits_getbit (bits); - has_filter = swfdec_bits_getbit (bits); - SWFDEC_LOG (" cache = %d", cache); - SWFDEC_LOG (" has filter = %d", has_filter); - SWFDEC_LOG (" has blend mode = %d", has_blend_mode); - } - - depth = swfdec_bits_get_u16 (bits); - if (depth >= 16384) { - SWFDEC_WARNING ("depth of placement too high: %u >= 16384", depth); - } - SWFDEC_LOG (" depth = %d (=> %d)", depth, depth - 16384); - depth -= 16384; - - /* new name always means new object */ - content = swfdec_contents_create (s->parse_sprite, depth, move); - if (has_character) { - int id = swfdec_bits_get_u16 (bits); - content->graphic = swfdec_swf_decoder_get_character (s, id); - if (!SWFDEC_IS_GRAPHIC (content->graphic)) { - swfdec_content_free (content); - swfdec_sprite_remove_last_action (s->parse_sprite, - s->parse_sprite->parse_frame); - SWFDEC_ERROR ("id %u does not specify a graphic", id); - return SWFDEC_STATUS_OK; - } - SWFDEC_LOG (" id = %d", id); - } else if (!move) { - SWFDEC_ERROR ("no character specified and not a move command"); - swfdec_content_free (content); - swfdec_sprite_remove_last_action (s->parse_sprite, - s->parse_sprite->parse_frame); - return SWFDEC_STATUS_OK; - } - - - if (has_matrix) { - swfdec_bits_get_matrix (bits, &content->transform, NULL); - SWFDEC_LOG (" matrix = { %g %g, %g %g } + { %g %g }", - content->transform.xx, content->transform.yx, - content->transform.xy, content->transform.yy, - content->transform.x0, content->transform.y0); - content->has_transform = TRUE; - } - if (has_color_transform) { - swfdec_bits_get_color_transform (bits, &content->color_transform); - SWFDEC_LOG (" color transform = %d %d %d %d %d %d %d %d", - content->color_transform.ra, content->color_transform.rb, - content->color_transform.ga, content->color_transform.gb, - content->color_transform.ba, content->color_transform.bb, - content->color_transform.aa, content->color_transform.ab); - content->has_color_transform = TRUE; - } - swfdec_bits_syncbits (bits); - if (has_ratio) { - content->ratio = swfdec_bits_get_u16 (bits); - SWFDEC_LOG (" ratio = %d", content->ratio); - } - if (has_name) { - g_free (content->name); - content->name = swfdec_bits_get_string (bits); - SWFDEC_LOG (" name = %s", content->name); - } - if (has_clip_depth) { - content->clip_depth = swfdec_bits_get_u16 (bits) - 16384; - SWFDEC_LOG (" clip_depth = %d (=> %d)", content->clip_depth + 16384, content->clip_depth); - } - if (has_filter) { - SWFDEC_ERROR ("filters aren't implemented, skipping PlaceObject tag!"); - swfdec_content_free (content); - swfdec_sprite_remove_last_action (s->parse_sprite, - s->parse_sprite->parse_frame); - return SWFDEC_STATUS_OK; - } - if (has_blend_mode) { - guint operator = swfdec_bits_get_u8 (bits); - content->operator = swfdec_sprite_convert_operator (operator); - SWFDEC_ERROR (" operator = %u", operator); - } - if (has_clip_actions) { - int reserved, clip_event_flags, event_flags, key_code; - char *script_name; - - g_assert (content->events == NULL); - content->events = swfdec_event_list_new (SWFDEC_DECODER (s)->player); - reserved = swfdec_bits_get_u16 (bits); - clip_event_flags = swfdec_get_clipeventflags (s, bits); - - if (content->name) - script_name = g_strdup (content->name); - else if (content->graphic) - script_name = g_strdup_printf ("Sprite%u", SWFDEC_CHARACTER (content->graphic)->id); - else - script_name = g_strdup ("unknown"); - while ((event_flags = swfdec_get_clipeventflags (s, bits)) != 0) { - guint length = swfdec_bits_get_u32 (bits); - SwfdecBits action_bits; - - swfdec_bits_init_bits (&action_bits, bits, length); - if (event_flags & SWFDEC_EVENT_KEY_PRESS) - key_code = swfdec_bits_get_u8 (&action_bits); - else - key_code = 0; - - SWFDEC_INFO ("clip event with flags 0x%X, key code %d", event_flags, key_code); -#define SWFDEC_IMPLEMENTED_EVENTS \ - (SWFDEC_EVENT_LOAD | SWFDEC_EVENT_UNLOAD | SWFDEC_EVENT_ENTER | SWFDEC_EVENT_INITIALIZE | SWFDEC_EVENT_CONSTRUCT | \ - SWFDEC_EVENT_MOUSE_DOWN | SWFDEC_EVENT_MOUSE_MOVE | SWFDEC_EVENT_MOUSE_UP) - if (event_flags & ~SWFDEC_IMPLEMENTED_EVENTS) { - SWFDEC_ERROR ("using non-implemented clip events %u", event_flags & ~SWFDEC_IMPLEMENTED_EVENTS); - } - swfdec_event_list_parse (content->events, &action_bits, s->version, - event_flags, key_code, script_name); - if (swfdec_bits_left (&action_bits)) { - SWFDEC_ERROR ("not all action data was parsed: %u bytes left", - swfdec_bits_left (&action_bits)); - } - } - g_free (script_name); - } - - return SWFDEC_STATUS_OK; -} - -int -swfdec_spriteseg_remove_object (SwfdecSwfDecoder * s, guint tag) -{ - int depth; - - swfdec_bits_get_u16 (&s->b); - depth = swfdec_bits_get_u16 (&s->b); - SWFDEC_LOG (" depth = %d (=> %d)", depth, depth - 16384); - depth -= 16384; - swfdec_sprite_add_action (s->parse_sprite, SWFDEC_SPRITE_ACTION_REMOVE, GINT_TO_POINTER (depth)); - - return SWFDEC_STATUS_OK; -} - -int -swfdec_spriteseg_remove_object_2 (SwfdecSwfDecoder * s, guint tag) -{ - guint depth; - - depth = swfdec_bits_get_u16 (&s->b); - SWFDEC_LOG (" depth = %u", depth); - depth -= 16384; - swfdec_sprite_add_action (s->parse_sprite, SWFDEC_SPRITE_ACTION_REMOVE, GINT_TO_POINTER (depth)); - - return SWFDEC_STATUS_OK; -} - static SwfdecMovie * swfdec_sprite_create_movie (SwfdecGraphic *graphic, gsize *size) { @@ -444,6 +193,7 @@ swfdec_sprite_class_init (SwfdecSpriteCl static void swfdec_sprite_init (SwfdecSprite * sprite) { + sprite->actions = g_array_new (FALSE, FALSE, sizeof (SwfdecSpriteAction)); } void diff --git a/libswfdec/swfdec_sprite.h b/libswfdec/swfdec_sprite.h index 661be2b..9bf1712 100644 --- a/libswfdec/swfdec_sprite.h +++ b/libswfdec/swfdec_sprite.h @@ -33,16 +33,14 @@ typedef struct _SwfdecSpriteClass Swfdec typedef struct _SwfdecSpriteAction SwfdecSpriteAction; typedef struct _SwfdecExport SwfdecExport; -typedef enum { - SWFDEC_SPRITE_ACTION_SCRIPT, /* contains an action only */ - SWFDEC_SPRITE_ACTION_ADD, /* contains a SwfdecSpriteContent */ - SWFDEC_SPRITE_ACTION_REMOVE, /* contains a depth */ - SWFDEC_SPRITE_ACTION_UPDATE /* contains a SwfdecSpriteContent */ -} SwfdecSpriteActionType; - +/* FIXME: It might make sense to event a SwfdecActionBuffer - a subclass of + * SwfdecBuffer that carries around a the tag. + * It might also make more sense to not parse the file into buffers at all + * and operate on the memory directly. + */ struct _SwfdecSpriteAction { - guint type; - gpointer data; + guint tag; /* the data tag (see swfdec_tag.h) */ + SwfdecBuffer * buffer; /* the buffer for this data (can be NULL) */ }; #define SWFDEC_TYPE_SPRITE (swfdec_sprite_get_type()) @@ -59,11 +57,8 @@ struct _SwfdecSpriteFrame SwfdecSound *sound_head; /* sound head for this frame */ int sound_skip; /* samples to skip - maybe even backwards */ SwfdecBuffer *sound_block; /* sound chunk to play here or NULL for none */ - guint sound_samples; /* number of samples in this frame */ + guint sound_samples; /* number of samples in this frame */ GSList *sound; /* list of SwfdecSoundChunk events to start playing here */ - - /* visuals */ - GArray *actions; /* SwfdecSpriteAction in execution order */ }; struct _SwfdecSprite @@ -73,6 +68,7 @@ struct _SwfdecSprite SwfdecSpriteFrame * frames; /* the n_frames different frames */ guint n_frames; /* number of frames in this sprite */ SwfdecScript * init_action; /* action to run when initializing this sprite */ + GArray * actions; /* SwfdecSpriteAction in execution order */ /* parse state */ guint parse_frame; /* frame we're currently parsing. == n_frames if done parsing */ @@ -89,20 +85,20 @@ int tag_func_define_sprite (SwfdecSwfDec void swfdec_sprite_add_sound_chunk (SwfdecSprite * sprite, guint frame, SwfdecBuffer * chunk, int skip, guint n_samples); void swfdec_sprite_set_n_frames (SwfdecSprite *sprite, guint n_frames, guint rate); -void swfdec_sprite_add_action (SwfdecSprite * sprite, - SwfdecSpriteActionType type, gpointer data); -guint swfdec_sprite_get_next_frame (SwfdecSprite *sprite, guint current_frame); +void swfdec_sprite_add_action (SwfdecSprite * sprite, guint tag, SwfdecBuffer *buffer); +gboolean swfdec_sprite_get_action (SwfdecSprite * sprite, + guint n, + guint * tag, + SwfdecBuffer ** buffer); +guint swfdec_sprite_get_next_frame (SwfdecSprite * sprite, + guint current_frame); int swfdec_sprite_get_frame (SwfdecSprite * sprite, const char * label); SwfdecContent *swfdec_content_new (int depth); void swfdec_content_free (SwfdecContent *content); -int tag_show_frame (SwfdecSwfDecoder * s, guint tag); int tag_func_set_background_color (SwfdecSwfDecoder * s, guint tag); -int swfdec_spriteseg_place_object (SwfdecSwfDecoder * s, guint tag); -int swfdec_spriteseg_remove_object (SwfdecSwfDecoder * s, guint tag); -int swfdec_spriteseg_remove_object_2 (SwfdecSwfDecoder * s, guint tag); G_END_DECLS diff --git a/libswfdec/swfdec_sprite_movie.c b/libswfdec/swfdec_sprite_movie.c index 3fc00f3..28570ed 100644 --- a/libswfdec/swfdec_sprite_movie.c +++ b/libswfdec/swfdec_sprite_movie.c @@ -33,6 +33,7 @@ #include "swfdec_script.h" #include "swfdec_sprite.h" #include "swfdec_swf_instance.h" +#include "swfdec_tag.h" #include "swfdec_utils.h" /*** SWFDEC_SPRITE_MOVIE ***/ @@ -55,55 +56,269 @@ swfdec_sprite_movie_run_script (gpointer swfdec_as_object_run (movie, data); } -static void -swfdec_sprite_movie_perform_one_action (SwfdecSpriteMovie *movie, SwfdecSpriteAction *action, +static cairo_operator_t +swfdec_sprite_convert_operator (guint operator) +{ + return CAIRO_OPERATOR_OVER; +} + +static int +swfdec_get_clipeventflags (SwfdecMovie *movie, SwfdecBits * bits) +{ + if (SWFDEC_SWF_DECODER (movie->swf->decoder)->version <= 5) { + return swfdec_bits_get_u16 (bits); + } else { + return swfdec_bits_get_u32 (bits); + } +} + +gboolean +swfdec_sprite_movie_perform_place (SwfdecSpriteMovie *movie, SwfdecBits *bits, guint tag) +{ + SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context); + SwfdecMovie *mov = SWFDEC_MOVIE (movie); + SwfdecMovie *cur; + gboolean has_clip_actions; + gboolean has_clip_depth; + gboolean has_name; + gboolean has_ratio; + gboolean has_ctrans; + gboolean has_transform; + gboolean has_character; + gboolean move; + gboolean depth; + gboolean cache; + gboolean has_blend_mode = 0; + gboolean has_filter = 0; + int clip_depth; + cairo_matrix_t transform; + SwfdecColorTransform ctrans; + guint ratio, id, version; + SwfdecEventList *events; + const char *name; + + version = SWFDEC_SWF_DECODER (mov->swf->decoder)->version; + + /* 1) check which stuff is set */ + has_clip_actions = swfdec_bits_getbit (bits); + has_clip_depth = swfdec_bits_getbit (bits); + has_name = swfdec_bits_getbit (bits); + has_ratio = swfdec_bits_getbit (bits); + has_ctrans = swfdec_bits_getbit (bits); + has_transform = swfdec_bits_getbit (bits); + has_character = swfdec_bits_getbit (bits); + move = swfdec_bits_getbit (bits); + + SWFDEC_LOG ("performing PlaceObject%d on movie %s", tag == SWFDEC_TAG_PLACEOBJECT2 ? 2 : 3, mov->name); + SWFDEC_LOG (" has_clip_actions = %d", has_clip_actions); + SWFDEC_LOG (" has_clip_depth = %d", has_clip_depth); + SWFDEC_LOG (" has_name = %d", has_name); + SWFDEC_LOG (" has_ratio = %d", has_ratio); + SWFDEC_LOG (" has_ctrans = %d", has_ctrans); + SWFDEC_LOG (" has_transform = %d", has_transform); + SWFDEC_LOG (" has_character = %d", has_character); + SWFDEC_LOG (" move = %d", move); + + if (tag == SWFDEC_TAG_PLACEOBJECT3) { + swfdec_bits_getbits (bits, 5); + cache = swfdec_bits_getbit (bits); + has_blend_mode = swfdec_bits_getbit (bits); + has_filter = swfdec_bits_getbit (bits); + SWFDEC_LOG (" cache = %d", cache); + SWFDEC_LOG (" has filter = %d", has_filter); + SWFDEC_LOG (" has blend mode = %d", has_blend_mode); + } + + /* 2) read all properties */ + depth = swfdec_bits_get_u16 (bits); + if (depth >= 16384) { + SWFDEC_FIXME ("depth of placement too high: %u >= 16384", depth); + } + SWFDEC_LOG (" depth = %d (=> %d)", depth, depth - 16384); + depth -= 16384; + if (has_character) { + id = swfdec_bits_get_u16 (bits); + SWFDEC_LOG (" id = %d", id); + } else { + id = 0; + } + + if (has_transform) { + swfdec_bits_get_matrix (bits, &transform, NULL); + SWFDEC_LOG (" matrix = { %g %g, %g %g } + { %g %g }", + transform.xx, transform.yx, + transform.xy, transform.yy, + transform.x0, transform.y0); + } + if (has_ctrans) { + swfdec_bits_get_color_transform (bits, &ctrans); + SWFDEC_LOG (" color transform = %d %d %d %d %d %d %d %d", + ctrans.ra, ctrans.rb, + ctrans.ga, ctrans.gb, + ctrans.ba, ctrans.bb, + ctrans.aa, ctrans.ab); + } + + if (has_ratio) { + ratio = swfdec_bits_get_u16 (bits); + SWFDEC_LOG (" ratio = %d", ratio); + } else { + ratio = 0; + } + + if (has_name) { + char *s = swfdec_bits_get_string_with_version (bits, version); + name = swfdec_as_context_give_string (SWFDEC_AS_CONTEXT (player), s); + SWFDEC_LOG (" name = %s", name); + } else { + name = NULL; + } + + if (has_clip_depth) { + clip_depth = swfdec_bits_get_u16 (bits) - 16384; + SWFDEC_LOG (" clip_depth = %d (=> %d)", clip_depth + 16384, clip_depth); + } else { + clip_depth = 0; + } + + if (has_filter) { + SWFDEC_ERROR ("filters aren't implemented, skipping PlaceObject tag!"); + return TRUE; + } + + if (has_blend_mode) { + /* FIXME: implement */ + guint operator = swfdec_bits_get_u8 (bits); + swfdec_sprite_convert_operator (operator); + SWFDEC_ERROR (" operator = %u", operator); + } + + if (has_clip_actions) { + int reserved, clip_event_flags, event_flags, key_code; + char *script_name; + + events = swfdec_event_list_new (player); + reserved = swfdec_bits_get_u16 (bits); + clip_event_flags = swfdec_get_clipeventflags (mov, bits); + + if (name) + script_name = g_strdup (name); + else if (id) + script_name = g_strdup_printf ("Sprite%u", id); + else + script_name = g_strdup ("unknown"); + while ((event_flags = swfdec_get_clipeventflags (mov, bits)) != 0) { + guint length = swfdec_bits_get_u32 (bits); + SwfdecBits action_bits; + + swfdec_bits_init_bits (&action_bits, bits, length); + if (event_flags & SWFDEC_EVENT_KEY_PRESS) + key_code = swfdec_bits_get_u8 (&action_bits); + else + key_code = 0; + + SWFDEC_INFO ("clip event with flags 0x%X, key code %d", event_flags, key_code); +#define SWFDEC_IMPLEMENTED_EVENTS \ + (SWFDEC_EVENT_LOAD | SWFDEC_EVENT_UNLOAD | SWFDEC_EVENT_ENTER | SWFDEC_EVENT_INITIALIZE | SWFDEC_EVENT_CONSTRUCT | \ + SWFDEC_EVENT_MOUSE_DOWN | SWFDEC_EVENT_MOUSE_MOVE | SWFDEC_EVENT_MOUSE_UP) + if (event_flags & ~SWFDEC_IMPLEMENTED_EVENTS) { + SWFDEC_ERROR ("using non-implemented clip events %u", event_flags & ~SWFDEC_IMPLEMENTED_EVENTS); + } + swfdec_event_list_parse (events, &action_bits, version, + event_flags, key_code, script_name); + if (swfdec_bits_left (&action_bits)) { + SWFDEC_ERROR ("not all action data was parsed: %u bytes left", + swfdec_bits_left (&action_bits)); + } + } + g_free (script_name); + } else { + events = NULL; + } + + /* 3) perform the actions depending on the set properties */ + cur = swfdec_movie_find (mov, depth); + if (move) { + if (cur == NULL) { + SWFDEC_INFO ("no movie at depth %d, ignoring move command", depth); + return TRUE; + } + swfdec_movie_set_static_properties (cur, has_transform ? &transform : NULL, + has_ctrans ? &ctrans : NULL, ratio, clip_depth, events); + } else { + SwfdecGraphic *graphic; + if (cur != NULL) { + SWFDEC_INFO ("depth %d is already occupied by movie %s, not placing", depth, cur->name); + return TRUE; + } + graphic = swfdec_swf_decoder_get_character (SWFDEC_SWF_DECODER (mov->swf->decoder), id); + if (!SWFDEC_IS_GRAPHIC (graphic)) { + SWFDEC_FIXME ("character %u is not a graphic (does it eve exist?), ignoring", id); + return TRUE; + } + cur = swfdec_movie_new (player, depth, mov, graphic, name); + swfdec_movie_set_static_properties (cur, has_transform ? &transform : NULL, + has_ctrans ? &ctrans : NULL, ratio, clip_depth, events); + g_queue_push_tail (player->init_queue, cur); + g_queue_push_tail (player->construct_queue, cur); + swfdec_movie_queue_script (cur, SWFDEC_EVENT_LOAD); + swfdec_movie_initialize (cur); + } + + return TRUE; +} + +static gboolean +swfdec_sprite_movie_perform_one_action (SwfdecSpriteMovie *movie, guint tag, SwfdecBuffer *buffer, gboolean skip_scripts) { SwfdecMovie *mov = SWFDEC_MOVIE (movie); SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (mov)->context); - SwfdecMovie *child; - SwfdecContent *content; + SwfdecBits bits; - switch (action->type) { - case SWFDEC_SPRITE_ACTION_SCRIPT: + g_assert (mov->swf); + swfdec_bits_init (&bits, buffer); + + SWFDEC_LOG ("%p: executing %uth tag %s in frame %u", movie, movie->next_action - 1, + swfdec_swf_decoder_get_tag_name (tag), mov->frame); + switch (tag) { + case SWFDEC_TAG_DOACTION: SWFDEC_LOG ("SCRIPT action"); if (!skip_scripts) { - swfdec_player_add_action (player, mov, swfdec_sprite_movie_run_script, action->data); + SwfdecScript *script = swfdec_swf_decoder_get_script ( + SWFDEC_SWF_DECODER (mov->swf->decoder), buffer->data); + g_assert (script); + swfdec_player_add_action (player, mov, swfdec_sprite_movie_run_script, script); } - break; - case SWFDEC_SPRITE_ACTION_ADD: - content = action->data; - SWFDEC_LOG ("ADD action: depth %d", content->depth); - if (swfdec_movie_find (mov, content->depth)) { - SWFDEC_WARNING ("Could not add movie, depth %d is already occupied", content->depth); - } else { - child = swfdec_movie_new_for_content (mov, content); + return TRUE; + case SWFDEC_TAG_PLACEOBJECT2: + case SWFDEC_TAG_PLACEOBJECT3: + return swfdec_sprite_movie_perform_place (movie, &bits, tag); + case SWFDEC_TAG_REMOVEOBJECT: + /* yes, this code is meant to be like this - the following u16 is the + * character id, that we don't care about, the rest is like RemoveObject2 + */ + swfdec_bits_get_u16 (&bits); + /* fall through */ + case SWFDEC_TAG_REMOVEOBJECT2: + { + int depth = swfdec_bits_get_u16 (&bits); + SWFDEC_LOG ("REMOVE action: depth %d => %d", depth, depth - 16384); + depth -= 16384; + if (!swfdec_sprite_movie_remove_child (mov, depth)) + SWFDEC_INFO ("could not remove, no child at depth %d", depth); } - break; - case SWFDEC_SPRITE_ACTION_UPDATE: - content = action->data; - SWFDEC_LOG ("ADD action: depth %d", content->depth); - child = swfdec_movie_find (mov, content->depth); - if (child != NULL) { - /* FIXME: add ability to change characters - This needs lots of refactoring */ - swfdec_movie_set_static_properties (child, content->has_transform ? &content->transform : NULL, - content->has_color_transform ? &content->color_transform : NULL, - content->ratio, content->clip_depth, content->events); - if (content->name && !g_str_equal (content->name, child->name)) { - /* test this more */ - child->name = swfdec_as_context_get_string (SWFDEC_AS_CONTEXT (player), content->name); - } + return TRUE; + case SWFDEC_TAG_SHOWFRAME: + if (mov->frame < mov->n_frames) { + mov->frame++; } else { - SWFDEC_WARNING ("supposed to move a character, but can't"); + SWFDEC_ERROR ("too many ShowFrame tags"); } - break; - case SWFDEC_SPRITE_ACTION_REMOVE: - SWFDEC_LOG ("REMOVE action: depth %d", GPOINTER_TO_INT (action->data)); - if (!swfdec_sprite_movie_remove_child (mov, GPOINTER_TO_INT (action->data))) - SWFDEC_INFO ("could not remove, no child at depth %d", GPOINTER_TO_INT (action->data)); - break; + return FALSE; default: g_assert_not_reached (); + return FALSE; } } @@ -129,7 +344,7 @@ swfdec_sprite_movie_goto (SwfdecMovie *m SwfdecSpriteMovie *movie = SWFDEC_SPRITE_MOVIE (mov); SwfdecPlayer *player; GList *old; - guint i, j, start; + guint n; g_assert (goto_frame < mov->n_frames); if (goto_frame >= movie->sprite->parse_frame) { @@ -140,40 +355,48 @@ swfdec_sprite_movie_goto (SwfdecMovie *m if (mov->will_be_removed) return; - if (goto_frame == movie->current_frame) + if (goto_frame == mov->frame) return; player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (mov)->context); SWFDEC_LOG ("doing goto %u for %p %d", goto_frame, mov, SWFDEC_CHARACTER (SWFDEC_SPRITE_MOVIE (mov)->sprite)->id); - mov->frame = goto_frame; - if (goto_frame < movie->current_frame) { - start = 0; + SWFDEC_DEBUG ("performing goto %u -> %u for character %u", + mov->frame, goto_frame, SWFDEC_CHARACTER (movie->sprite)->id); + if (goto_frame < mov->frame) { + /* this path is also taken on init */ + mov->frame = 0; old = mov->list; mov->list = NULL; + n = goto_frame + 1; + movie->next_action = 0; } else { - start = movie->current_frame + 1; old = NULL; + n = goto_frame - mov->frame; + mov->frame++; } - movie->current_frame = goto_frame; - SWFDEC_DEBUG ("performing goto %u -> %u for character %u", - start, goto_frame, SWFDEC_CHARACTER (movie->sprite)->id); + /* from here on, mov->frame is 1-indexed */ if (movie->sprite == NULL) return; - for (i = start; i <= movie->current_frame; i++) { - SwfdecSpriteFrame *frame = &movie->sprite->frames[i]; + while (n) { + guint tag; + SwfdecBuffer *buffer; + /* FIXME: These actions should probably just be added to the action queue */ if (movie == mov->swf->movie && - mov->swf->parse_frame <= i) { + mov->swf->parse_frame <= mov->frame) swfdec_swf_instance_advance (mov->swf); - } - if (frame->actions == NULL) - continue; - for (j = 0; j < frame->actions->len; j++) { - swfdec_sprite_movie_perform_one_action (movie, - &g_array_index (frame->actions, SwfdecSpriteAction, j), - i != movie->current_frame); - } + if (!swfdec_sprite_get_action (movie->sprite, movie->next_action, &tag, &buffer)) + break; + movie->next_action++; + if (!swfdec_sprite_movie_perform_one_action (movie, tag, buffer, n > 1)) + n--; + } + /* now make mov->frame 0-indexed again */ + if (mov->frame) { + mov->frame--; + } else { + SWFDEC_FIXME ("how to handle movies without a ShowFrame tag?"); } /* now try to copy eventual movies */ if (old) { @@ -259,7 +482,7 @@ swfdec_sprite_movie_iterate_end (SwfdecM GSList *walk; SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (mov)->context); - g_assert (movie->current_frame < mov->n_frames); + g_assert (mov->frame < mov->n_frames); if (!SWFDEC_MOVIE_CLASS (swfdec_sprite_movie_parent_class)->iterate_end (mov)) { g_assert (movie->sound_stream == NULL); return FALSE; @@ -267,10 +490,10 @@ swfdec_sprite_movie_iterate_end (SwfdecM if (movie->sprite == NULL) return TRUE; - current = &movie->sprite->frames[movie->current_frame]; + current = &movie->sprite->frames[mov->frame]; /* first start all event sounds */ /* FIXME: is this correct? */ - if (movie->sound_frame != movie->current_frame) { + if (movie->sound_frame != mov->frame) { for (walk = current->sound; walk; walk = walk->next) { SwfdecAudio *audio = swfdec_audio_event_new (player, walk->data); if (audio) @@ -290,8 +513,8 @@ swfdec_sprite_movie_iterate_end (SwfdecM } if (movie->sound_stream == NULL && current->sound_block == NULL) goto exit; - SWFDEC_LOG ("iterating audio (from %u to %u)", movie->sound_frame, movie->current_frame); - if (movie->sound_frame + 1 != movie->current_frame) + SWFDEC_LOG ("iterating audio (from %u to %u)", movie->sound_frame, mov->frame); + if (movie->sound_frame + 1 != mov->frame) goto new_decoder; if (movie->sound_frame == (guint) -1) goto new_decoder; @@ -301,7 +524,7 @@ swfdec_sprite_movie_iterate_end (SwfdecM if (last->sound_head != current->sound_head) goto new_decoder; exit: - movie->sound_frame = movie->current_frame; + movie->sound_frame = mov->frame; return TRUE; new_decoder: @@ -312,8 +535,8 @@ new_decoder: if (current->sound_block) { movie->sound_stream = swfdec_audio_stream_new (player, - movie->sprite, movie->current_frame); - movie->sound_frame = movie->current_frame; + movie->sprite, mov->frame); + movie->sound_frame = mov->frame; } return TRUE; } @@ -432,7 +655,9 @@ swfdec_sprite_movie_class_init (SwfdecSp static void swfdec_sprite_movie_init (SwfdecSpriteMovie * movie) { - movie->current_frame = (guint) -1; + SwfdecMovie *mov = SWFDEC_MOVIE (movie); + + mov->frame = (guint) -1; movie->sound_frame = (guint) -1; } diff --git a/libswfdec/swfdec_sprite_movie.h b/libswfdec/swfdec_sprite_movie.h index 316827d..9db258a 100644 --- a/libswfdec/swfdec_sprite_movie.h +++ b/libswfdec/swfdec_sprite_movie.h @@ -43,7 +43,7 @@ struct _SwfdecSpriteMovie SwfdecSprite * sprite; /* displayed sprite */ /* frame information */ - guint current_frame; /* frame that is currently displayed (NB: indexed from 0) */ + guint next_action; /* next action in sprite to perform */ /* color information */ SwfdecColor bg_color; /* background color (only used on main sprite) */ diff --git a/libswfdec/swfdec_tag.c b/libswfdec/swfdec_tag.c index 82a884d..9f56aa1 100644 --- a/libswfdec/swfdec_tag.c +++ b/libswfdec/swfdec_tag.c @@ -252,22 +252,6 @@ tag_func_define_sprite (SwfdecSwfDecoder return SWFDEC_STATUS_OK; } -int -tag_func_do_action (SwfdecSwfDecoder * s, guint tag) -{ - SwfdecScript *script; - char *name; - - name = g_strdup_printf ("Sprite%u_Frame%u", SWFDEC_CHARACTER (s->parse_sprite)->id, - s->parse_sprite->parse_frame); - script = swfdec_script_new_for_context (SWFDEC_AS_CONTEXT (SWFDEC_DECODER (s)->player), &s->b, name, s->version); - g_free (name); - if (script) - swfdec_sprite_add_action (s->parse_sprite, SWFDEC_SPRITE_ACTION_SCRIPT, script); - - return SWFDEC_STATUS_OK; -} - #define CONTENT_IN_FRAME(content, frame) \ ((content)->sequence->start <= frame && \ (content)->sequence->end > frame) @@ -572,6 +556,55 @@ tag_func_do_init_action (SwfdecSwfDecode return SWFDEC_STATUS_OK; } +static int +tag_func_enqueue (SwfdecSwfDecoder *s, guint tag) +{ + SwfdecBuffer *buffer; + + buffer = swfdec_bits_get_buffer (&s->b, -1); + SWFDEC_LOG ("queueing %s tag for sprite %u", swfdec_swf_decoder_get_tag_name (tag), + SWFDEC_CHARACTER (s->parse_sprite)->id); + swfdec_sprite_add_action (s->parse_sprite, tag, buffer); + + return SWFDEC_STATUS_OK; +} + +static int +tag_func_show_frame (SwfdecSwfDecoder * s, guint tag) +{ + SWFDEC_DEBUG("show_frame %d of id %d", s->parse_sprite->parse_frame, + SWFDEC_CHARACTER (s->parse_sprite)->id); + + s->parse_sprite->parse_frame++; + if (s->parse_sprite->parse_frame < s->parse_sprite->n_frames) { + SwfdecSpriteFrame *old = &s->parse_sprite->frames[s->parse_sprite->parse_frame - 1]; + SwfdecSpriteFrame *new = &s->parse_sprite->frames[s->parse_sprite->parse_frame]; + if (old->sound_head) + new->sound_head = g_object_ref (old->sound_head); + } + tag_func_enqueue (s, tag); + + return SWFDEC_STATUS_IMAGE; +} + +static int +tag_func_do_action (SwfdecSwfDecoder * s, guint tag) +{ + SwfdecScript *script; + char *name; + + name = g_strdup_printf ("Sprite%u_Frame%u", SWFDEC_CHARACTER (s->parse_sprite)->id, + s->parse_sprite->parse_frame); + script = swfdec_script_new_for_context (SWFDEC_AS_CONTEXT (SWFDEC_DECODER (s)->player), &s->b, name, s->version); + g_free (name); + if (script) { + swfdec_swf_decoder_add_script (s, script); + swfdec_sprite_add_action (s->parse_sprite, tag, swfdec_buffer_ref (script->buffer)); + } + + return SWFDEC_STATUS_OK; +} + /* may appear inside DefineSprite */ #define SPRITE 1 struct tag_func_struct @@ -582,11 +615,11 @@ struct tag_func_struct }; static struct tag_func_struct tag_funcs[] = { [SWFDEC_TAG_END] = {"End", tag_func_end, SPRITE}, - [SWFDEC_TAG_SHOWFRAME] = {"ShowFrame", tag_show_frame, SPRITE}, + [SWFDEC_TAG_SHOWFRAME] = {"ShowFrame", tag_func_show_frame, SPRITE}, [SWFDEC_TAG_DEFINESHAPE] = {"DefineShape", tag_define_shape, 0}, [SWFDEC_TAG_FREECHARACTER] = {"FreeCharacter", NULL, 0}, [SWFDEC_TAG_PLACEOBJECT] = {"PlaceObject", NULL, SPRITE}, - [SWFDEC_TAG_REMOVEOBJECT] = {"RemoveObject", swfdec_spriteseg_remove_object, SPRITE}, + [SWFDEC_TAG_REMOVEOBJECT] = {"RemoveObject", tag_func_enqueue, SPRITE}, [SWFDEC_TAG_DEFINEBITSJPEG] = {"DefineBitsJPEG", tag_func_define_bits_jpeg, 0}, [SWFDEC_TAG_DEFINEBUTTON] = {"DefineButton", tag_func_define_button, 0}, [SWFDEC_TAG_JPEGTABLES] = {"JPEGTables", swfdec_image_jpegtables, 0}, @@ -608,8 +641,8 @@ static struct tag_func_struct tag_funcs[ [SWFDEC_TAG_DEFINESHAPE2] = {"DefineShape2", tag_define_shape, 0}, [SWFDEC_TAG_DEFINEBUTTONCXFORM] = {"DefineButtonCXForm", NULL, 0}, [SWFDEC_TAG_PROTECT] = {"Protect", tag_func_protect, 0}, - [SWFDEC_TAG_PLACEOBJECT2] = {"PlaceObject2", swfdec_spriteseg_place_object, SPRITE}, - [SWFDEC_TAG_REMOVEOBJECT2] = {"RemoveObject2", swfdec_spriteseg_remove_object_2, SPRITE}, + [SWFDEC_TAG_PLACEOBJECT2] = {"PlaceObject2", tag_func_enqueue, SPRITE}, + [SWFDEC_TAG_REMOVEOBJECT2] = {"RemoveObject2", tag_func_enqueue, SPRITE}, [SWFDEC_TAG_DEFINESHAPE3] = {"DefineShape3", tag_define_shape_3, 0}, [SWFDEC_TAG_DEFINETEXT2] = {"DefineText2", tag_func_define_text, 0}, [SWFDEC_TAG_DEFINEBUTTON2] = {"DefineButton2", tag_func_define_button_2, 0}, @@ -642,7 +675,7 @@ static struct tag_func_struct tag_funcs[ [SWFDEC_TAG_SCRIPTLIMITS] = {"ScriptLimits", NULL, 0}, [SWFDEC_TAG_SETTABINDEX] = {"SetTabIndex", NULL, 0}, [SWFDEC_TAG_FILEATTRIBUTES] = {"FileAttributes", tag_func_file_attributes, 0}, - [SWFDEC_TAG_PLACEOBJECT3] = {"PlaceObject3", swfdec_spriteseg_place_object, SPRITE}, + [SWFDEC_TAG_PLACEOBJECT3] = {"PlaceObject3", tag_func_enqueue, SPRITE}, [SWFDEC_TAG_IMPORTASSETS2] = {"ImportAssets2", NULL, 0}, [SWFDEC_TAG_DEFINEFONTALIGNZONES] = {"DefineFontAlignZones", NULL, 0}, [SWFDEC_TAG_CSMTEXTSETTINGS] = {"CSMTextSettings", NULL, 0}, diff-tree d60a5d10e7a597d244cdffc1b900a557d237e437 (from ab6b5c6adf505db81b5f4d4e7e0cff72c7130031) Author: Benjamin Otte <otte at gnome.org> Date: Mon Jun 18 17:06:46 2007 +0200 - s/SwfdecSpriteAction/SwfdecRootAction/ as SwfdecSpriteAction is about to be changed - allow SwfdecSWFDecoder to cache scripts to avoid duplication of script parsing and (even more interesting) having all scripts exactly once in the debugger diff --git a/libswfdec/swfdec_swf_decoder.c b/libswfdec/swfdec_swf_decoder.c index 77a1f66..1bd5ff5 100644 --- a/libswfdec/swfdec_swf_decoder.c +++ b/libswfdec/swfdec_swf_decoder.c @@ -48,7 +48,7 @@ enum { G_DEFINE_TYPE (SwfdecSwfDecoder, swfdec_swf_decoder, SWFDEC_TYPE_DECODER) static void -swfdec_decoder_dispose (GObject *object) +swfdec_swf_decoder_dispose (GObject *object) { SwfdecSwfDecoder *s = SWFDEC_SWF_DECODER (object); guint i,j; @@ -58,7 +58,7 @@ swfdec_decoder_dispose (GObject *object) GArray *array = s->root_actions[i]; if (array) { for (j = 0; j < array->len; j++) { - SwfdecSpriteAction *action = &g_array_index (array, SwfdecSpriteAction, j); + SwfdecRootAction *action = &g_array_index (array, SwfdecRootAction, j); switch (action->type) { case SWFDEC_ROOT_ACTION_EXPORT: @@ -86,6 +86,7 @@ swfdec_decoder_dispose (GObject *object) g_hash_table_destroy (s->characters); g_object_unref (s->main_sprite); + g_hash_table_destroy (s->scripts); if (s->uncompressed_buffer) { inflateEnd (&s->z); @@ -379,7 +380,7 @@ swfdec_swf_decoder_class_init (SwfdecSwf GObjectClass *object_class = G_OBJECT_CLASS (class); SwfdecDecoderClass *decoder_class = SWFDEC_DECODER_CLASS (class); - object_class->dispose = swfdec_decoder_dispose; + object_class->dispose = swfdec_swf_decoder_dispose; decoder_class->parse = swfdec_swf_decoder_parse; } @@ -392,6 +393,8 @@ swfdec_swf_decoder_init (SwfdecSwfDecode s->characters = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref); s->input_queue = swfdec_buffer_queue_new (); + s->scripts = g_hash_table_new_full (g_direct_hash, g_direct_equal, + NULL, (GDestroyNotify) swfdec_script_unref); } gpointer @@ -444,7 +447,7 @@ swfdec_swf_decoder_add_root_action (Swfd { SwfdecSprite *sprite; GArray *array; - SwfdecSpriteAction action; + SwfdecRootAction action; g_return_if_fail (SWFDEC_IS_SWF_DECODER (s)); sprite = s->main_sprite; @@ -456,7 +459,7 @@ swfdec_swf_decoder_add_root_action (Swfd array = s->root_actions[sprite->parse_frame]; if (array == NULL) { s->root_actions[sprite->parse_frame] = - g_array_new (FALSE, FALSE, sizeof (SwfdecSpriteAction)); + g_array_new (FALSE, FALSE, sizeof (SwfdecRootAction)); array = s->root_actions[sprite->parse_frame]; } action.type = type; @@ -464,3 +467,22 @@ swfdec_swf_decoder_add_root_action (Swfd g_array_append_val (array, action); } +void +swfdec_swf_decoder_add_script (SwfdecSwfDecoder *s, SwfdecScript *script) +{ + g_return_if_fail (SWFDEC_IS_SWF_DECODER (s)); + g_return_if_fail (script != NULL); + g_return_if_fail (script->buffer != NULL); + + g_hash_table_insert (s->scripts, script->buffer->data, script); +} + +SwfdecScript * +swfdec_swf_decoder_get_script (SwfdecSwfDecoder *s, guint8 *data) +{ + g_return_val_if_fail (SWFDEC_IS_SWF_DECODER (s), NULL); + g_return_val_if_fail (data != NULL, NULL); + + return g_hash_table_lookup (s->scripts, data); +} + diff --git a/libswfdec/swfdec_swf_decoder.h b/libswfdec/swfdec_swf_decoder.h index 930d1e3..5bddb02 100644 --- a/libswfdec/swfdec_swf_decoder.h +++ b/libswfdec/swfdec_swf_decoder.h @@ -42,6 +42,12 @@ typedef enum { SWFDEC_ROOT_ACTION_INIT_SCRIPT, /* contains a SwfdecScript */ } SwfdecRootActionType; +typedef struct _SwfdecRootAction SwfdecRootAction; +struct _SwfdecRootAction { + guint type; + gpointer data; +}; + struct _SwfdecRootExportData { char * name; SwfdecCharacter * character; @@ -74,6 +80,7 @@ struct _SwfdecSwfDecoder SwfdecSprite *main_sprite; SwfdecSprite *parse_sprite; GArray **root_actions; /* actions to be executed by the root sprite */ + GHashTable *scripts; /* buffer -> script mapping for all scripts */ gboolean protection; /* TRUE is this file is protected and may not be edited */ char *password; /* MD5'd password to open for editing or NULL if may not be opened */ @@ -97,6 +104,10 @@ gpointer swfdec_swf_decoder_create_chara void swfdec_swf_decoder_add_root_action (SwfdecSwfDecoder * s, SwfdecRootActionType type, gpointer data); +void swfdec_swf_decoder_add_script (SwfdecSwfDecoder * s, + SwfdecScript * script); +SwfdecScript * swfdec_swf_decoder_get_script (SwfdecSwfDecoder * s, + guint8 * data); SwfdecTagFunc swfdec_swf_decoder_get_tag_func (int tag); const char *swfdec_swf_decoder_get_tag_name (int tag); diff --git a/libswfdec/swfdec_swf_instance.c b/libswfdec/swfdec_swf_instance.c index 5ff43b5..e21ce47 100644 --- a/libswfdec/swfdec_swf_instance.c +++ b/libswfdec/swfdec_swf_instance.c @@ -245,7 +245,7 @@ swfdec_swf_instance_advance (SwfdecSwfIn if (array == NULL) return; for (i = 0; i < array->len; i++) { - SwfdecSpriteAction *action = &g_array_index (array, SwfdecSpriteAction, i); + SwfdecRootAction *action = &g_array_index (array, SwfdecRootAction, i); switch (action->type) { case SWFDEC_ROOT_ACTION_INIT_SCRIPT: swfdec_as_object_run (SWFDEC_AS_OBJECT (instance->movie), action->data); diff-tree ab6b5c6adf505db81b5f4d4e7e0cff72c7130031 (from fa8acc601252c3ee1a7f74f06e4b113ecdcb57ce) Author: Benjamin Otte <otte at gnome.org> Date: Mon Jun 18 11:47:04 2007 +0200 clean up header diff --git a/libswfdec/swfdec_sprite_movie.h b/libswfdec/swfdec_sprite_movie.h index e244a54..316827d 100644 --- a/libswfdec/swfdec_sprite_movie.h +++ b/libswfdec/swfdec_sprite_movie.h @@ -40,17 +40,17 @@ struct _SwfdecSpriteMovie { SwfdecMovie movie; - SwfdecSprite * sprite; /* displayed sprite */ + SwfdecSprite * sprite; /* displayed sprite */ /* frame information */ - guint current_frame; /* frame that is currently displayed (NB: indexed from 0) */ + guint current_frame; /* frame that is currently displayed (NB: indexed from 0) */ /* color information */ - SwfdecColor bg_color; /* background color (only used on main sprite) */ + SwfdecColor bg_color; /* background color (only used on main sprite) */ /* audio stream handling */ - guint sound_frame; /* current sound frame */ - SwfdecAudio * sound_stream; /* stream that currently plays */ + guint sound_frame; /* current sound frame */ + SwfdecAudio * sound_stream; /* stream that currently plays */ }; struct _SwfdecSpriteMovieClass @@ -60,8 +60,6 @@ struct _SwfdecSpriteMovieClass GType swfdec_sprite_movie_get_type (void); -void swfdec_sprite_movie_prepare (SwfdecSpriteMovie * movie); - G_END_DECLS #endif diff-tree fa8acc601252c3ee1a7f74f06e4b113ecdcb57ce (from d766f996e21c12d9fbca23b8e315cc1e79b4e784) Author: Benjamin Otte <otte at gnome.org> Date: Sun Jun 17 21:56:58 2007 +0200 adapt license to LGPL If anyone wanna complain about it, see http://sswf.sourceforge.net/SWFalexref.html diff --git a/libswfdec/swfdec_tag.h b/libswfdec/swfdec_tag.h index 6a4e155..ac7c2fa 100644 --- a/libswfdec/swfdec_tag.h +++ b/libswfdec/swfdec_tag.h @@ -1,22 +1,27 @@ -/* tags.h */ -/* Take from: */ -/* rfxswf.h - - Headers for rfxswf.c and modules - - Part of the swftools package. - - Copyright (c) 2000, 2001 Rainer B?hme <rfxswf at reflex-studio.de> - - This file is distributed under the GPL, see file COPYING for details - -*/ +/* Swfdec + * Copyright (C) 2003-2006 David Schleef <ds at schleef.org> + * 2005-2006 Eric Anholt <eric at anholt.net> + * 2006-2007 Benjamin Otte <otte at gnome.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ #ifndef __LIBSWFDEC_TAGS_H__ #define __LIBSWFDEC_TAGS_H__ -/* Tag IDs (adopted from J. C. Kessels' Form2Flash) */ - typedef enum { SWFDEC_TAG_END = 0, SWFDEC_TAG_SHOWFRAME = 1,
Maybe Matching Threads
- 2 commits - doc/swfdec-sections.txt libswfdec/swfdec_color.h libswfdec/swfdec_player.c libswfdec/swfdec_player.h libswfdec/swfdec_player_internal.h libswfdec/swfdec_sprite.c libswfdec/swfdec_sprite.h libswfdec/swfdec_sprite_movie.c
- 11 commits - libswfdec/swfdec_event.c libswfdec/swfdec_event.h libswfdec/swfdec_js_movie.c libswfdec/swfdec_movie.c libswfdec/swfdec_scriptable.c libswfdec/swfdec_scriptable.h libswfdec/swfdec_script.c libswfdec/swfdec_sprite.c libswfdec/swfdec_sprite.h
- Branch 'as' - 6 commits - libswfdec/swfdec_as_interpret.c libswfdec/swfdec_movie_asprops.c libswfdec/swfdec_movie.c libswfdec/swfdec_movie.h libswfdec/swfdec_sprite.c libswfdec/swfdec_sprite.h libswfdec/swfdec_sprite_movie_as.c
- Branch 'as' - libswfdec/Makefile.am libswfdec/swfdec_root_movie.c libswfdec/swfdec_root_sprite.c libswfdec/swfdec_root_sprite.h libswfdec/swfdec_swf_decoder.c libswfdec/swfdec_swf_decoder.h libswfdec/swfdec_tag.c
- Branch 'as' - 6 commits - libswfdec/swfdec_as_array.c libswfdec/swfdec_button_movie.c libswfdec/swfdec_morph_movie.c libswfdec/swfdec_movie_asprops.c libswfdec/swfdec_movie.c libswfdec/swfdec_movie.h libswfdec/swfdec_player.c libswfdec/swfdec_sprite.c