[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