[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
Benjamin Otte
company at kemper.freedesktop.org
Mon Jun 18 14:59:17 PDT 2007
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,
More information about the Swfdec
mailing list