[Swfdec] 5 commits - libswfdec/Makefile.am libswfdec/swfdec_color.c libswfdec/swfdec_color.h libswfdec/swfdec_font.c libswfdec/swfdec_loadertarget.c libswfdec/swfdec_movie.h libswfdec/swfdec_pattern.c libswfdec/swfdec_pattern.h libswfdec/swfdec_player.c libswfdec/swfdec_player_internal.h libswfdec/swfdec_shape.c libswfdec/swfdec_sprite.c libswfdec/swfdec_sprite.h libswfdec/swfdec_stroke.c libswfdec/swfdec_stroke.h libswfdec/swfdec_swf_decoder.c libswfdec/swfdec_tag.c player/swfdec_debug_widget.c

Benjamin Otte company at kemper.freedesktop.org
Fri Apr 13 08:23:47 PDT 2007


 libswfdec/Makefile.am              |    2 
 libswfdec/swfdec_color.c           |   23 +++
 libswfdec/swfdec_color.h           |    3 
 libswfdec/swfdec_font.c            |    5 
 libswfdec/swfdec_loadertarget.c    |    2 
 libswfdec/swfdec_movie.h           |    5 
 libswfdec/swfdec_pattern.c         |  229 ++++---------------------------------
 libswfdec/swfdec_pattern.h         |   24 ++-
 libswfdec/swfdec_player.c          |    5 
 libswfdec/swfdec_player_internal.h |    7 -
 libswfdec/swfdec_shape.c           |   11 -
 libswfdec/swfdec_sprite.c          |   48 +++++++
 libswfdec/swfdec_sprite.h          |    1 
 libswfdec/swfdec_stroke.c          |  210 +++++++++++++++++++++++++++++++++
 libswfdec/swfdec_stroke.h          |   69 +++++++++++
 libswfdec/swfdec_swf_decoder.c     |    8 -
 libswfdec/swfdec_tag.c             |    2 
 player/swfdec_debug_widget.c       |    2 
 18 files changed, 423 insertions(+), 233 deletions(-)

New commits:
diff-tree 26ee7f5d85a1d809daa20b2f67cf4cb99420ed66 (from 61c1915ce1a6b610a5023443af62d64632322b6a)
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Apr 13 17:24:04 2007 +0200

    fix crash with 0x0 sized movies (fixes #10629)

diff --git a/libswfdec/swfdec_loadertarget.c b/libswfdec/swfdec_loadertarget.c
index 40ad26f..a19a0bf 100644
--- a/libswfdec/swfdec_loadertarget.c
+++ b/libswfdec/swfdec_loadertarget.c
@@ -125,8 +125,6 @@ swfdec_loader_target_parse_default (Swfd
 	{
 	  SwfdecPlayer *player;
 	  player = swfdec_loader_target_get_player (target);
-	  g_assert (dec->width > 0);
-	  g_assert (dec->height > 0);
 	  swfdec_player_initialize (player, dec->rate, 
 	      dec->width, dec->height);
 	  if (!swfdec_loader_target_init (target)) {
diff --git a/libswfdec/swfdec_player.c b/libswfdec/swfdec_player.c
index 6e03f55..517b2cb 100644
--- a/libswfdec/swfdec_player.c
+++ b/libswfdec/swfdec_player.c
@@ -1023,8 +1023,6 @@ void
 swfdec_player_initialize (SwfdecPlayer *player, guint rate, guint width, guint height)
 {
   g_return_if_fail (SWFDEC_IS_PLAYER (player));
-  g_return_if_fail (width > 0);
-  g_return_if_fail (height > 0);
 
   if (swfdec_player_is_initialized (player))
     return;
@@ -1033,6 +1031,7 @@ swfdec_player_initialize (SwfdecPlayer *
   player->rate = rate;
   player->width = width;
   player->height = height;
+  player->initialized = TRUE;
   if (rate) {
     player->iterate_timeout.timestamp = player->time + SWFDEC_TICKS_PER_SECOND * 256 / rate;
     swfdec_player_add_timeout (player, &player->iterate_timeout);
@@ -1334,7 +1333,7 @@ swfdec_player_is_initialized (SwfdecPlay
 {
   g_return_val_if_fail (SWFDEC_IS_PLAYER (player), FALSE);
 
-  return player->width > 0 && player->height > 0;
+  return player->initialized;
 }
 
 /**
diff --git a/libswfdec/swfdec_player_internal.h b/libswfdec/swfdec_player_internal.h
index f4de1a1..527ee6e 100644
--- a/libswfdec/swfdec_player_internal.h
+++ b/libswfdec/swfdec_player_internal.h
@@ -42,9 +42,10 @@ struct _SwfdecPlayer
   GObject		object;
 
   /* global properties */
-  guint		rate;			/* divide by 256 to get iterations per second */
-  guint		width;			/* width of movie */
-  guint		height;			/* height of movie */
+  gboolean		initialized;		/* if width and height are set already */
+  guint		  	rate;			/* divide by 256 to get iterations per second */
+  guint			width;			/* width of movie */
+  guint			height;			/* height of movie */
   GList *		roots;			/* all the root movies */
   SwfdecCache *		cache;			/* player cache */
   gboolean		bgcolor_set;		/* TRUE if the background color has been set */
diff --git a/libswfdec/swfdec_swf_decoder.c b/libswfdec/swfdec_swf_decoder.c
index 97f6965..f8a34b1 100644
--- a/libswfdec/swfdec_swf_decoder.c
+++ b/libswfdec/swfdec_swf_decoder.c
@@ -194,9 +194,11 @@ swf_parse_header2 (SwfdecSwfDecoder * s)
 
   swfdec_bits_get_rect (&s->b, &rect);
   if (rect.x0 != 0.0 || rect.y0 != 0.0)
-    SWFDEC_ERROR ("SWF window doesn't start at 0 0 but at %g %g\n", rect.x0, rect.y0);
-  dec->width = ceil (rect.x1 / SWFDEC_TWIPS_SCALE_FACTOR);
-  dec->height = ceil (rect.y1 / SWFDEC_TWIPS_SCALE_FACTOR);
+    SWFDEC_ERROR ("SWF window doesn't start at 0 0 but at %g %g", rect.x0, rect.y0);
+  SWFDEC_INFO ("SWF size: %g x %g pixels", rect.x1 / SWFDEC_TWIPS_SCALE_FACTOR,
+      rect.y1 / SWFDEC_TWIPS_SCALE_FACTOR);
+  dec->width = MAX (0, ceil (rect.x1 / SWFDEC_TWIPS_SCALE_FACTOR));
+  dec->height = MAX (0, ceil (rect.y1 / SWFDEC_TWIPS_SCALE_FACTOR));
   swfdec_bits_syncbits (&s->b);
   dec->rate = swfdec_bits_get_u16 (&s->b);
   SWFDEC_LOG ("rate = %g", dec->rate / 256.0);
diff-tree 61c1915ce1a6b610a5023443af62d64632322b6a (from ffd9d1fab29d4f256c59b597aac0a11ee1f58317)
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Apr 13 14:50:00 2007 +0200

    split out the stroke pattern as a seperate object.
    
    This is inpreparation for Flash 8's new strokes

diff --git a/libswfdec/Makefile.am b/libswfdec/Makefile.am
index 352d46b..54710bf 100644
--- a/libswfdec/Makefile.am
+++ b/libswfdec/Makefile.am
@@ -79,6 +79,7 @@ libswfdec_ at SWFDEC_MAJORMINOR@_la_SOURCES
 	swfdec_scriptable.c \
 	swfdec_shape.c \
 	swfdec_sound.c \
+	swfdec_stroke.c \
 	swfdec_sprite.c \
 	swfdec_sprite_movie.c \
 	swfdec_swf_decoder.c \
@@ -159,6 +160,7 @@ noinst_HEADERS = \
 	swfdec_sprite.h \
 	swfdec_sprite_movie.h \
 	swfdec_swf_decoder.h \
+	swfdec_stroke.h \
 	swfdec_tag.h \
 	swfdec_text.h \
 	swfdec_types.h \
diff --git a/libswfdec/swfdec_color.c b/libswfdec/swfdec_color.c
index 23fda5a..83be167 100644
--- a/libswfdec/swfdec_color.c
+++ b/libswfdec/swfdec_color.c
@@ -250,3 +250,26 @@ swfdec_matrix_get_rotation (const cairo_
   return atan2 (matrix->yx, matrix->xx) * 180 / G_PI;
 }
 
+void
+swfdec_matrix_morph (cairo_matrix_t *dest, const cairo_matrix_t *start,
+    const cairo_matrix_t *end, guint ratio)
+{
+  guint inv_ratio = 65535 - ratio;
+  g_assert (ratio < 65536);
+
+  if (ratio == 0) {
+    *dest = *start;
+    return;
+  }
+  if (ratio == 65535) {
+    *dest = *end;
+    return;
+  }
+  dest->xx = (start->xx * inv_ratio + end->xx * ratio) / 65535;
+  dest->xy = (start->xy * inv_ratio + end->xy * ratio) / 65535;
+  dest->yy = (start->yy * inv_ratio + end->yy * ratio) / 65535;
+  dest->yx = (start->yx * inv_ratio + end->yx * ratio) / 65535;
+  dest->x0 = (start->x0 * inv_ratio + end->x0 * ratio) / 65535;
+  dest->y0 = (start->y0 * inv_ratio + end->y0 * ratio) / 65535;
+}
+
diff --git a/libswfdec/swfdec_color.h b/libswfdec/swfdec_color.h
index 296311b..e43458f 100644
--- a/libswfdec/swfdec_color.h
+++ b/libswfdec/swfdec_color.h
@@ -80,5 +80,8 @@ void swfdec_matrix_ensure_invertible (ca
 double swfdec_matrix_get_xscale (const cairo_matrix_t *matrix);
 double swfdec_matrix_get_yscale (const cairo_matrix_t *matrix);
 double swfdec_matrix_get_rotation (const cairo_matrix_t *matrix);
+void swfdec_matrix_morph (cairo_matrix_t *dest, const cairo_matrix_t *start,
+    const cairo_matrix_t *end, guint ratio);
+
 
 #endif
diff --git a/libswfdec/swfdec_font.c b/libswfdec/swfdec_font.c
index 1b032d8..9efe573 100644
--- a/libswfdec/swfdec_font.c
+++ b/libswfdec/swfdec_font.c
@@ -27,6 +27,7 @@
 #include "swfdec_bits.h"
 #include "swfdec_debug.h"
 #include "swfdec_shape.h"
+#include "swfdec_stroke.h"
 #include "swfdec_swf_decoder.h"
 
 G_DEFINE_TYPE (SwfdecFont, swfdec_font, SWFDEC_TYPE_CHARACTER)
@@ -184,7 +185,7 @@ swfdec_font_parse_shape (SwfdecSwfDecode
   entry->shape = shape;
 
   g_ptr_array_add (shape->fills, swfdec_pattern_new_color (0xFFFFFFFF));
-  g_ptr_array_add (shape->lines, swfdec_pattern_new_stroke (20, 0xFFFFFFFF));
+  g_ptr_array_add (shape->lines, swfdec_stroke_new (20, 0xFFFFFFFF));
 
   shape->n_fill_bits = swfdec_bits_getbits (&s->b, 4);
   SWFDEC_LOG ("n_fill_bits = %d", shape->n_fill_bits);
@@ -327,7 +328,7 @@ tag_func_define_font_2 (SwfdecSwfDecoder
     entry->shape = shape;
 
     g_ptr_array_add (shape->fills, swfdec_pattern_new_color (0xFFFFFFFF));
-    g_ptr_array_add (shape->lines, swfdec_pattern_new_stroke (20, 0xFFFFFFFF));
+    g_ptr_array_add (shape->lines, swfdec_stroke_new (20, 0xFFFFFFFF));
 
     swfdec_bits_syncbits (&s->b);
     shape->n_fill_bits = swfdec_bits_getbits (&s->b, 4);
diff --git a/libswfdec/swfdec_pattern.c b/libswfdec/swfdec_pattern.c
index c3214cb..8a2bda7 100644
--- a/libswfdec/swfdec_pattern.c
+++ b/libswfdec/swfdec_pattern.c
@@ -29,31 +29,7 @@
 #include "swfdec_debug.h"
 #include "swfdec_decoder.h"
 #include "swfdec_image.h"
-
-/*** MORPHING ***/
-
-static void
-swfdec_matrix_morph (cairo_matrix_t *dest, const cairo_matrix_t *start,
-    const cairo_matrix_t *end, guint ratio)
-{
-  guint inv_ratio = 65535 - ratio;
-  g_assert (ratio < 65536);
-
-  if (ratio == 0) {
-    *dest = *start;
-    return;
-  }
-  if (ratio == 65535) {
-    *dest = *end;
-    return;
-  }
-  dest->xx = (start->xx * inv_ratio + end->xx * ratio) / 65535;
-  dest->xy = (start->xy * inv_ratio + end->xy * ratio) / 65535;
-  dest->yy = (start->yy * inv_ratio + end->yy * ratio) / 65535;
-  dest->yx = (start->yx * inv_ratio + end->yx * ratio) / 65535;
-  dest->x0 = (start->x0 * inv_ratio + end->x0 * ratio) / 65535;
-  dest->y0 = (start->y0 * inv_ratio + end->y0 * ratio) / 65535;
-}
+#include "swfdec_stroke.h"
 
 /*** PATTERN ***/
 
@@ -71,131 +47,6 @@ swfdec_pattern_init (SwfdecPattern *patt
   cairo_matrix_init_identity (&pattern->end_transform);
 }
 
-/*** STROKE PATTERN ***/
-
-#define MAX_ALIGN 10
-
-typedef struct _SwfdecStrokePattern SwfdecStrokePattern;
-typedef struct _SwfdecStrokePatternClass SwfdecStrokePatternClass;
-
-#define SWFDEC_TYPE_STROKE_PATTERN                    (swfdec_stroke_pattern_get_type())
-#define SWFDEC_IS_STROKE_PATTERN(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_STROKE_PATTERN))
-#define SWFDEC_IS_STROKE_PATTERN_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_STROKE_PATTERN))
-#define SWFDEC_STROKE_PATTERN(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_STROKE_PATTERN, SwfdecStrokePattern))
-#define SWFDEC_STROKE_PATTERN_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_STROKE_PATTERN, SwfdecStrokePatternClass))
-#define SWFDEC_STROKE_PATTERN_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_STROKE_PATTERN, SwfdecStrokePatternClass))
-
-struct _SwfdecStrokePattern
-{
-  SwfdecPattern		pattern;
-
-  guint			start_width;		/* width of line */
-  SwfdecColor		start_color;		/* color to paint with */
-  guint			end_width;		/* width of line */
-  SwfdecColor		end_color;		/* color to paint with */
-};
-
-struct _SwfdecStrokePatternClass
-{
-  SwfdecPatternClass	pattern_class;
-};
-
-G_DEFINE_TYPE (SwfdecStrokePattern, swfdec_stroke_pattern, SWFDEC_TYPE_PATTERN);
-
-static void
-swfdec_pattern_append_path_snapped (cairo_t *cr, const cairo_path_t *path)
-{
-  cairo_path_data_t *data;
-  double x, y;
-  int i;
-
-  data = path->data;
-  for (i = 0; i < path->num_data; i++) {
-    switch (data[i].header.type) {
-      case CAIRO_PATH_MOVE_TO:
-	i++;
-	x = data[i].point.x;
-	y = data[i].point.y;
-	cairo_user_to_device (cr, &x, &y);
-	x = rint (x - 0.5) + 0.5;
-	y = rint (y - 0.5) + 0.5;
-	cairo_device_to_user (cr, &x, &y);
-	/* FIXME: currently we need to clamp this due to extents */
-	x = CLAMP (x, data[i].point.x - MAX_ALIGN, data[i].point.x + MAX_ALIGN);
-	y = CLAMP (y, data[i].point.y - MAX_ALIGN, data[i].point.y + MAX_ALIGN);
-	cairo_move_to (cr, x, y);
-	break;
-      case CAIRO_PATH_LINE_TO:
-	i++;
-	x = data[i].point.x;
-	y = data[i].point.y;
-	cairo_user_to_device (cr, &x, &y);
-	x = rint (x - 0.5) + 0.5;
-	y = rint (y - 0.5) + 0.5;
-	cairo_device_to_user (cr, &x, &y);
-	/* FIXME: currently we need to clamp this due to extents */
-	x = CLAMP (x, data[i].point.x - MAX_ALIGN, data[i].point.x + MAX_ALIGN);
-	y = CLAMP (y, data[i].point.y - MAX_ALIGN, data[i].point.y + MAX_ALIGN);
-	cairo_line_to (cr, x, y);
-	break;
-      case CAIRO_PATH_CURVE_TO:
-	x = data[i+3].point.x;
-	y = data[i+3].point.y;
-	cairo_user_to_device (cr, &x, &y);
-	x = rint (x - 0.5) + 0.5;
-	y = rint (y - 0.5) + 0.5;
-	cairo_device_to_user (cr, &x, &y);
-	/* FIXME: currently we need to clamp this due to extents */
-	x = CLAMP (x, data[i+3].point.x - MAX_ALIGN, data[i+3].point.x + MAX_ALIGN);
-	y = CLAMP (y, data[i+3].point.y - MAX_ALIGN, data[i+3].point.y + MAX_ALIGN);
-	cairo_curve_to (cr, data[i+1].point.x, data[i+1].point.y, 
-	    data[i+2].point.x, data[i+2].point.y, x, y);
-	i += 3;
-	break;
-      case CAIRO_PATH_CLOSE_PATH:
-	/* doesn't exist in our code */
-      default:
-	g_assert_not_reached ();
-    }
-  }
-}
-
-static void
-swfdec_stroke_pattern_paint (SwfdecPattern *pattern, cairo_t *cr, const cairo_path_t *path,
-    const SwfdecColorTransform *trans, guint ratio)
-{
-  SwfdecColor color;
-  double width;
-  SwfdecStrokePattern *stroke = SWFDEC_STROKE_PATTERN (pattern);
-
-  swfdec_pattern_append_path_snapped (cr, path);
-  color = swfdec_color_apply_morph (stroke->start_color, stroke->end_color, ratio);
-  color = swfdec_color_apply_transform (color, trans);
-  swfdec_color_set_source (cr, color);
-  if (ratio == 0) {
-    width = stroke->start_width;
-  } else if (ratio == 65535) {
-    width = stroke->end_width;
-  } else {
-    width = (stroke->start_width * (65535 - ratio) + stroke->end_width * ratio) / 65535;
-  }
-  if (width < SWFDEC_TWIPS_SCALE_FACTOR)
-    width = SWFDEC_TWIPS_SCALE_FACTOR;
-  cairo_set_line_width (cr, width);
-  cairo_stroke (cr);
-}
-
-static void
-swfdec_stroke_pattern_class_init (SwfdecStrokePatternClass *klass)
-{
-  SWFDEC_PATTERN_CLASS (klass)->paint = swfdec_stroke_pattern_paint;
-}
-
-static void
-swfdec_stroke_pattern_init (SwfdecStrokePattern *pattern)
-{
-}
-
 /*** COLOR PATTERN ***/
 
 typedef struct _SwfdecColorPattern SwfdecColorPattern;
@@ -663,63 +514,14 @@ swfdec_pattern_to_string (SwfdecPattern 
     SwfdecGradientPattern *gradient = SWFDEC_GRADIENT_PATTERN (pattern);
     return g_strdup_printf ("%s gradient (%u colors)", gradient->radial ? "radial" : "linear",
 	gradient->gradient->n_gradients);
-  } else if (SWFDEC_IS_STROKE_PATTERN (pattern)) {
-    SwfdecStrokePattern *line = SWFDEC_STROKE_PATTERN (pattern);
+  } else if (SWFDEC_IS_STROKE (pattern)) {
+    SwfdecStroke *line = SWFDEC_STROKE (pattern);
     return g_strdup_printf ("line (width %u, color #%08X)", line->start_width, line->start_color);
   } else {
     return g_strdup_printf ("%s", G_OBJECT_TYPE_NAME (pattern));
   }
 }
 
-SwfdecPattern *
-swfdec_pattern_parse_stroke (SwfdecSwfDecoder *dec, gboolean rgba)
-{
-  SwfdecBits *bits = &dec->b;
-  SwfdecStrokePattern *pattern = g_object_new (SWFDEC_TYPE_STROKE_PATTERN, NULL);
-
-  pattern->start_width = swfdec_bits_get_u16 (bits);
-  pattern->end_width = pattern->start_width;
-  if (rgba) {
-    pattern->start_color = swfdec_bits_get_rgba (bits);
-  } else {
-    pattern->start_color = swfdec_bits_get_color (bits);
-  }
-  pattern->end_color = pattern->start_color;
-  SWFDEC_LOG ("new stroke pattern: width %u color %08x", pattern->start_width, pattern->start_color);
-
-  return SWFDEC_PATTERN (pattern);
-}
-
-SwfdecPattern *
-swfdec_pattern_parse_morph_stroke (SwfdecSwfDecoder *dec)
-{
-  SwfdecBits *bits = &dec->b;
-  SwfdecStrokePattern *pattern = g_object_new (SWFDEC_TYPE_STROKE_PATTERN, NULL);
-
-  pattern->start_width = swfdec_bits_get_u16 (bits);
-  pattern->end_width = swfdec_bits_get_u16 (bits);
-  pattern->start_color = swfdec_bits_get_rgba (bits);
-  pattern->end_color = swfdec_bits_get_rgba (bits);
-  SWFDEC_LOG ("new stroke pattern: width %u => %u color %08X => %08X", 
-      pattern->start_width, pattern->end_width,
-      pattern->start_color, pattern->end_color);
-
-  return SWFDEC_PATTERN (pattern);
-}
-
-SwfdecPattern *
-swfdec_pattern_new_stroke (guint width, SwfdecColor color)
-{
-  SwfdecStrokePattern *pattern = g_object_new (SWFDEC_TYPE_STROKE_PATTERN, NULL);
-
-  pattern->start_width = width;
-  pattern->end_width = width;
-  pattern->start_color = color;
-  pattern->end_color = color;
-
-  return SWFDEC_PATTERN (pattern);
-}
-
 static void
 swfdec_path_get_extents (const cairo_path_t *path, SwfdecRect *extents, double line_width)
 {
@@ -791,11 +593,13 @@ swfdec_path_get_extents (const cairo_pat
 #undef ADD_POINT
 }
 
+#define MAX_ALIGN 10
+
 void
 swfdec_pattern_get_path_extents (SwfdecPattern *pattern, const cairo_path_t *path, SwfdecRect *extents)
 {
-  if (SWFDEC_IS_STROKE_PATTERN (pattern)) {
-    SwfdecStrokePattern *stroke = SWFDEC_STROKE_PATTERN (pattern);
+  if (SWFDEC_IS_STROKE (pattern)) {
+    SwfdecStroke *stroke = SWFDEC_STROKE (pattern);
     double line_width = MAX (stroke->start_width, stroke->end_width);
     line_width = MAX (line_width, SWFDEC_TWIPS_SCALE_FACTOR);
     swfdec_path_get_extents (path, extents, line_width / 2);
diff --git a/libswfdec/swfdec_pattern.h b/libswfdec/swfdec_pattern.h
index e2112da..7ea97f5 100644
--- a/libswfdec/swfdec_pattern.h
+++ b/libswfdec/swfdec_pattern.h
@@ -59,14 +59,9 @@ struct _SwfdecPatternClass
 GType		swfdec_pattern_get_type		(void);
 
 SwfdecPattern *	swfdec_pattern_new_color	(SwfdecColor			color);
-SwfdecPattern *	swfdec_pattern_new_stroke	(guint				width,
-						 SwfdecColor			color);
 SwfdecPattern *	swfdec_pattern_parse		(SwfdecSwfDecoder *		dec,
 						 gboolean			rgba);
-SwfdecPattern *	swfdec_pattern_parse_stroke   	(SwfdecSwfDecoder *		dec,
-						 gboolean			rgba);
 SwfdecPattern *	swfdec_pattern_parse_morph    	(SwfdecSwfDecoder *		dec);
-SwfdecPattern *	swfdec_pattern_parse_morph_stroke (SwfdecSwfDecoder *		dec);
 
 void		swfdec_pattern_paint		(SwfdecPattern *		pattern, 
 						 cairo_t *			cr,
diff --git a/libswfdec/swfdec_shape.c b/libswfdec/swfdec_shape.c
index 49dfa7b..65a5166 100644
--- a/libswfdec/swfdec_shape.c
+++ b/libswfdec/swfdec_shape.c
@@ -1,7 +1,7 @@
 /* Swfdec
  * Copyright (C) 2003-2006 David Schleef <ds at schleef.org>
  *		 2005-2006 Eric Anholt <eric at anholt.net>
- *		      2006 Benjamin Otte <otte at gnome.org>
+ *		 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
@@ -29,6 +29,7 @@
 #include "swfdec_shape.h"
 #include "swfdec.h"
 #include "swfdec_debug.h"
+#include "swfdec_stroke.h"
 
 G_DEFINE_TYPE (SwfdecShape, swfdec_shape, SWFDEC_TYPE_GRAPHIC)
 
@@ -367,13 +368,13 @@ parse_rgba (SwfdecSwfDecoder * s)
 static SwfdecPattern *
 parse_stroke_rgb (SwfdecSwfDecoder * s)
 {
-  return swfdec_pattern_parse_stroke (s, FALSE);
+  return swfdec_stroke_parse (s, FALSE);
 }
 
 static SwfdecPattern *
 parse_stroke_rgba (SwfdecSwfDecoder * s)
 {
-  return swfdec_pattern_parse_stroke (s, TRUE);
+  return swfdec_stroke_parse (s, TRUE);
 }
 
 int
@@ -936,7 +937,7 @@ swfdec_morph_shape_get_recs (SwfdecSwfDe
     switch (start_type) {
       case SWFDEC_SHAPE_TYPE_CHANGE:
 	start_path = swfdec_shape_parse_change (s, shape, start_path_array, start_path, &start_x, &start_y, 
-	    swfdec_pattern_parse_morph, swfdec_pattern_parse_morph_stroke);
+	    swfdec_pattern_parse_morph, swfdec_stroke_parse_morph);
 	end_path = swfdec_morph_shape_do_change (end_bits, start_path, morph, end_path_array, end_path, &end_x, &end_y);
 	break;
       case SWFDEC_SHAPE_TYPE_LINE:
@@ -1023,7 +1024,7 @@ tag_define_morph_shape (SwfdecSwfDecoder
   bits->end = end_bits.ptr;
 
   swfdec_shape_add_styles (s, SWFDEC_SHAPE (morph),
-      swfdec_pattern_parse_morph, swfdec_pattern_parse_morph_stroke);
+      swfdec_pattern_parse_morph, swfdec_stroke_parse_morph);
 
   morph->n_fill_bits = swfdec_bits_getbits (&end_bits, 4);
   morph->n_line_bits = swfdec_bits_getbits (&end_bits, 4);
diff --git a/libswfdec/swfdec_stroke.c b/libswfdec/swfdec_stroke.c
new file mode 100644
index 0000000..7239479
--- /dev/null
+++ b/libswfdec/swfdec_stroke.c
@@ -0,0 +1,210 @@
+/* Swfdec
+ * Copyright (C) 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
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <math.h>
+
+#include "swfdec_stroke.h"
+#include "swfdec_bits.h"
+#include "swfdec_color.h"
+#include "swfdec_debug.h"
+#include "swfdec_decoder.h"
+#include "swfdec_image.h"
+
+#define MAX_ALIGN 10
+
+G_DEFINE_TYPE (SwfdecStroke, swfdec_stroke, SWFDEC_TYPE_PATTERN);
+
+static void
+swfdec_stroke_append_path_snapped (cairo_t *cr, const cairo_path_t *path)
+{
+  cairo_path_data_t *data;
+  double x, y;
+  int i;
+
+  data = path->data;
+  for (i = 0; i < path->num_data; i++) {
+    switch (data[i].header.type) {
+      case CAIRO_PATH_MOVE_TO:
+	i++;
+	x = data[i].point.x;
+	y = data[i].point.y;
+	cairo_user_to_device (cr, &x, &y);
+	x = rint (x - 0.5) + 0.5;
+	y = rint (y - 0.5) + 0.5;
+	cairo_device_to_user (cr, &x, &y);
+	/* FIXME: currently we need to clamp this due to extents */
+	x = CLAMP (x, data[i].point.x - MAX_ALIGN, data[i].point.x + MAX_ALIGN);
+	y = CLAMP (y, data[i].point.y - MAX_ALIGN, data[i].point.y + MAX_ALIGN);
+	cairo_move_to (cr, x, y);
+	break;
+      case CAIRO_PATH_LINE_TO:
+	i++;
+	x = data[i].point.x;
+	y = data[i].point.y;
+	cairo_user_to_device (cr, &x, &y);
+	x = rint (x - 0.5) + 0.5;
+	y = rint (y - 0.5) + 0.5;
+	cairo_device_to_user (cr, &x, &y);
+	/* FIXME: currently we need to clamp this due to extents */
+	x = CLAMP (x, data[i].point.x - MAX_ALIGN, data[i].point.x + MAX_ALIGN);
+	y = CLAMP (y, data[i].point.y - MAX_ALIGN, data[i].point.y + MAX_ALIGN);
+	cairo_line_to (cr, x, y);
+	break;
+      case CAIRO_PATH_CURVE_TO:
+	x = data[i+3].point.x;
+	y = data[i+3].point.y;
+	cairo_user_to_device (cr, &x, &y);
+	x = rint (x - 0.5) + 0.5;
+	y = rint (y - 0.5) + 0.5;
+	cairo_device_to_user (cr, &x, &y);
+	/* FIXME: currently we need to clamp this due to extents */
+	x = CLAMP (x, data[i+3].point.x - MAX_ALIGN, data[i+3].point.x + MAX_ALIGN);
+	y = CLAMP (y, data[i+3].point.y - MAX_ALIGN, data[i+3].point.y + MAX_ALIGN);
+	cairo_curve_to (cr, data[i+1].point.x, data[i+1].point.y, 
+	    data[i+2].point.x, data[i+2].point.y, x, y);
+	i += 3;
+	break;
+      case CAIRO_PATH_CLOSE_PATH:
+	/* doesn't exist in our code */
+      default:
+	g_assert_not_reached ();
+    }
+  }
+}
+
+static void
+swfdec_stroke_paint (SwfdecPattern *pattern, cairo_t *cr, const cairo_path_t *path,
+    const SwfdecColorTransform *trans, guint ratio)
+{
+  SwfdecColor color;
+  double width;
+  SwfdecStroke *stroke = SWFDEC_STROKE (pattern);
+
+  swfdec_stroke_append_path_snapped (cr, path);
+  color = swfdec_color_apply_morph (stroke->start_color, stroke->end_color, ratio);
+  color = swfdec_color_apply_transform (color, trans);
+  swfdec_color_set_source (cr, color);
+  if (ratio == 0) {
+    width = stroke->start_width;
+  } else if (ratio == 65535) {
+    width = stroke->end_width;
+  } else {
+    width = (stroke->start_width * (65535 - ratio) + stroke->end_width * ratio) / 65535;
+  }
+  if (width < SWFDEC_TWIPS_SCALE_FACTOR)
+    width = SWFDEC_TWIPS_SCALE_FACTOR;
+  cairo_set_line_width (cr, width);
+  cairo_stroke (cr);
+}
+
+static void
+swfdec_stroke_class_init (SwfdecStrokeClass *klass)
+{
+  SWFDEC_PATTERN_CLASS (klass)->paint = swfdec_stroke_paint;
+}
+
+static void
+swfdec_stroke_init (SwfdecStroke *stroke)
+{
+}
+
+/*** EXPORTED API ***/
+
+SwfdecPattern *
+swfdec_stroke_parse (SwfdecSwfDecoder *dec, gboolean rgba)
+{
+  SwfdecBits *bits = &dec->b;
+  SwfdecStroke *stroke = g_object_new (SWFDEC_TYPE_STROKE, NULL);
+
+  stroke->start_width = swfdec_bits_get_u16 (bits);
+  stroke->end_width = stroke->start_width;
+  if (rgba) {
+    stroke->start_color = swfdec_bits_get_rgba (bits);
+  } else {
+    stroke->start_color = swfdec_bits_get_color (bits);
+  }
+  stroke->end_color = stroke->start_color;
+  SWFDEC_LOG ("new stroke stroke: width %u color %08x", stroke->start_width, stroke->start_color);
+
+  return SWFDEC_PATTERN (stroke);
+}
+
+SwfdecPattern *
+swfdec_stroke_parse_morph (SwfdecSwfDecoder *dec)
+{
+  SwfdecBits *bits = &dec->b;
+  SwfdecStroke *stroke = g_object_new (SWFDEC_TYPE_STROKE, NULL);
+
+  stroke->start_width = swfdec_bits_get_u16 (bits);
+  stroke->end_width = swfdec_bits_get_u16 (bits);
+  stroke->start_color = swfdec_bits_get_rgba (bits);
+  stroke->end_color = swfdec_bits_get_rgba (bits);
+  SWFDEC_LOG ("new stroke stroke: width %u => %u color %08X => %08X", 
+      stroke->start_width, stroke->end_width,
+      stroke->start_color, stroke->end_color);
+
+  return SWFDEC_PATTERN (stroke);
+}
+
+SwfdecPattern *
+swfdec_stroke_new (guint width, SwfdecColor color)
+{
+  SwfdecStroke *stroke = g_object_new (SWFDEC_TYPE_STROKE, NULL);
+
+  stroke->start_width = width;
+  stroke->end_width = width;
+  stroke->start_color = color;
+  stroke->end_color = color;
+
+  return SWFDEC_PATTERN (stroke);
+}
+
+static SwfdecPattern *
+swfdec_stroke_do_parse_extended (SwfdecBits *bits, gboolean morph,
+    SwfdecPattern *fill_styles, guint n_fill_styles)
+{
+  SwfdecStroke *stroke = g_object_new (SWFDEC_TYPE_STROKE, NULL);
+
+  SWFDEC_ERROR ("FIXME: implement");
+  return SWFDEC_PATTERN (stroke);
+}
+
+SwfdecPattern *
+swfdec_stroke_parse_extended (SwfdecSwfDecoder *dec, SwfdecPattern *fill_styles,
+    guint n_fill_styles)
+{
+  g_return_val_if_fail (SWFDEC_IS_SWF_DECODER (dec), NULL);
+  g_return_val_if_fail (n_fill_styles == 0 || fill_styles != NULL, NULL);
+
+  return swfdec_stroke_do_parse_extended (&dec->b, FALSE, fill_styles, n_fill_styles);
+}
+
+SwfdecPattern *
+swfdec_stroke_parse_morph_extended (SwfdecSwfDecoder *dec, SwfdecPattern *fill_styles,
+    guint n_fill_styles)
+{
+  g_return_val_if_fail (SWFDEC_IS_SWF_DECODER (dec), NULL);
+  g_return_val_if_fail (n_fill_styles == 0 || fill_styles != NULL, NULL);
+
+  return swfdec_stroke_do_parse_extended (&dec->b, TRUE, fill_styles, n_fill_styles);
+}
diff --git a/libswfdec/swfdec_stroke.h b/libswfdec/swfdec_stroke.h
new file mode 100644
index 0000000..51dbf07
--- /dev/null
+++ b/libswfdec/swfdec_stroke.h
@@ -0,0 +1,69 @@
+/* Swfdec
+ * Copyright (C) 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 _SWFDEC_STROKE_H_
+#define _SWFDEC_STROKE_H_
+
+#include <libswfdec/swfdec_pattern.h>
+
+G_BEGIN_DECLS
+
+typedef struct _SwfdecStroke SwfdecStroke;
+typedef struct _SwfdecStrokeClass SwfdecStrokeClass;
+
+#define SWFDEC_TYPE_STROKE                    (swfdec_stroke_get_type())
+#define SWFDEC_IS_STROKE(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_STROKE))
+#define SWFDEC_IS_STROKE_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_STROKE))
+#define SWFDEC_STROKE(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_STROKE, SwfdecStroke))
+#define SWFDEC_STROKE_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_STROKE, SwfdecStrokeClass))
+#define SWFDEC_STROKE_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_STROKE, SwfdecStrokeClass))
+
+struct _SwfdecStroke
+{
+  SwfdecPattern		pattern;
+
+  guint			start_width;		/* width of line */
+  SwfdecColor		start_color;		/* color to paint with */
+  guint			end_width;		/* width of line */
+  SwfdecColor		end_color;		/* color to paint with */
+};
+
+struct _SwfdecStrokeClass
+{
+  SwfdecPatternClass  	pattern_class;
+};
+
+GType		swfdec_stroke_get_type		(void);
+
+SwfdecPattern *	swfdec_stroke_new		(guint			width,
+						 SwfdecColor		color);
+SwfdecPattern *	swfdec_stroke_parse		(SwfdecSwfDecoder *	dec,
+						 gboolean		rgba);
+SwfdecPattern *	swfdec_stroke_parse_extended	(SwfdecSwfDecoder *	dec,
+						 SwfdecPattern *	fill_styles,
+						 guint			n_fill_styles);
+SwfdecPattern *	swfdec_stroke_parse_morph    	(SwfdecSwfDecoder *	dec);
+SwfdecPattern *	swfdec_stroke_parse_morph_extended
+						(SwfdecSwfDecoder *	dec,
+						 SwfdecPattern *	fill_styles,
+						 guint			n_fill_styles);
+
+
+G_END_DECLS
+#endif
diff-tree ffd9d1fab29d4f256c59b597aac0a11ee1f58317 (from 2fd1d7c21735f01ac9df501dbd42b47da0a5a868)
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Apr 13 10:04:53 2007 +0200

    use current scale, not user-set one

diff --git a/player/swfdec_debug_widget.c b/player/swfdec_debug_widget.c
index 4c7ebcc..953b918 100644
--- a/player/swfdec_debug_widget.c
+++ b/player/swfdec_debug_widget.c
@@ -60,7 +60,7 @@ swfdec_debug_widget_button_press (GtkWid
     return FALSE;
 
   if (event->button == 1 && swfdec_gtk_widget_get_interactive (widget)) {
-    double scale = swfdec_gtk_widget_get_scale (widget);
+    double scale = swfdec_gtk_widget_get_current_scale (widget);
     SwfdecPlayer *player = swfdec_gtk_widget_get_player (widget);
     switch (event->type) {
       case GDK_BUTTON_PRESS:
diff-tree 2fd1d7c21735f01ac9df501dbd42b47da0a5a868 (from 10622f56c90f64ad45f3c239bf0a0750590ad5e5)
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Apr 13 10:04:23 2007 +0200

    add copyright header

diff --git a/libswfdec/swfdec_pattern.c b/libswfdec/swfdec_pattern.c
index 4e32436..c3214cb 100644
--- a/libswfdec/swfdec_pattern.c
+++ b/libswfdec/swfdec_pattern.c
@@ -1,3 +1,22 @@
+/* Swfdec
+ * Copyright (C) 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
+ */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
diff --git a/libswfdec/swfdec_pattern.h b/libswfdec/swfdec_pattern.h
index b25dd56..e2112da 100644
--- a/libswfdec/swfdec_pattern.h
+++ b/libswfdec/swfdec_pattern.h
@@ -1,4 +1,21 @@
-
+/* Swfdec
+ * Copyright (C) 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 _SWFDEC_PATTERN_H_
 #define _SWFDEC_PATTERN_H_
diff-tree 10622f56c90f64ad45f3c239bf0a0750590ad5e5 (from d2d5d5c377fd595bd8fef79d9773c9ed78410fc1)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Apr 8 20:57:46 2007 +0200

    Add initial support PlaceObject3
    
    the code only reads the tag and aborts when parsing filters.

diff --git a/libswfdec/swfdec_movie.h b/libswfdec/swfdec_movie.h
index f1db624..5b56656 100644
--- a/libswfdec/swfdec_movie.h
+++ b/libswfdec/swfdec_movie.h
@@ -45,11 +45,12 @@ struct _SwfdecContent {
   SwfdecGraphic *	graphic;	/* object to display or NULL */
   int	         	depth;		/* at which depth to display */
   int			clip_depth;	/* clip depth of object */
-  guint		ratio;
+  guint			ratio;
   cairo_matrix_t	transform;
   SwfdecColorTransform	color_transform;
   char *		name;
   SwfdecEventList *	events;
+  cairo_operator_t	operator;	/* operator to use when painting (aka blend mode) */   
 
   SwfdecContent *	sequence;	/* first element in sequence this content belongs to */
   /* NB: the next two elements are only filled for the sequence leader */
@@ -57,7 +58,7 @@ struct _SwfdecContent {
   guint			end;		/* first frame that does not contain this sequence anymore */
 };
 #define SWFDEC_CONTENT_DEFAULT { NULL, -1, 0, 0, { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, \
-  { 256, 0, 256, 0, 256, 0, 256, 0 }, NULL, NULL, NULL, 0, G_MAXUINT }
+  { 256, 0, 256, 0, 256, 0, 256, 0 }, NULL, NULL, CAIRO_OPERATOR_OVER, NULL, 0, G_MAXUINT }
 
 #define SWFDEC_TYPE_MOVIE                    (swfdec_movie_get_type())
 #define SWFDEC_IS_MOVIE(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_MOVIE))
diff --git a/libswfdec/swfdec_sprite.c b/libswfdec/swfdec_sprite.c
index 7bb3629..86f7997 100644
--- a/libswfdec/swfdec_sprite.c
+++ b/libswfdec/swfdec_sprite.c
@@ -274,6 +274,7 @@ swfdec_content_new (int depth)
   cairo_matrix_init_identity (&content->transform);
   swfdec_color_transform_init_identity (&content->color_transform);
   content->depth = depth;
+  content->operator = CAIRO_OPERATOR_OVER;
   content->sequence = content;
   content->end = G_MAXUINT;
   return content;
@@ -313,8 +314,14 @@ swfdec_contents_create (SwfdecSprite *sp
   return content;
 }
 
-int
-swfdec_spriteseg_place_object_2 (SwfdecSwfDecoder * s)
+static cairo_operator_t
+swfdec_sprite_convert_operator (guint operator)
+{
+  return CAIRO_OPERATOR_OVER;
+}
+
+static int
+swfdec_spriteseg_do_place_object (SwfdecSwfDecoder *s, unsigned int version)
 {
   SwfdecBits *bits = &s->b;
   int has_clip_actions;
@@ -326,6 +333,9 @@ swfdec_spriteseg_place_object_2 (SwfdecS
   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);
@@ -349,6 +359,15 @@ swfdec_spriteseg_place_object_2 (SwfdecS
   SWFDEC_LOG ("  depth = %d (=> %d)", depth, depth - 16384);
   depth -= 16384;
 
+  if (version > 2) {
+    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 ("  has filter = %d", has_filter);
+    SWFDEC_LOG ("  has blend mode = %d", has_blend_mode);
+  }
+
   /* new name always means new object */
   content = swfdec_contents_create (s->parse_sprite, depth, move, has_character || has_name);
   if (has_character) {
@@ -402,6 +421,19 @@ swfdec_spriteseg_place_object_2 (SwfdecS
     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!");
+    g_hash_table_remove (s->parse_sprite->live_content, GUINT_TO_POINTER (content->depth));
+    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;
@@ -450,6 +482,18 @@ swfdec_spriteseg_place_object_2 (SwfdecS
 }
 
 int
+swfdec_spriteseg_place_object_2 (SwfdecSwfDecoder * s)
+{
+  return swfdec_spriteseg_do_place_object (s, 2);
+}
+
+int
+swfdec_spriteseg_place_object_3 (SwfdecSwfDecoder * s)
+{
+  return swfdec_spriteseg_do_place_object (s, 3);
+}
+
+int
 swfdec_spriteseg_remove_object (SwfdecSwfDecoder * s)
 {
   int depth;
diff --git a/libswfdec/swfdec_sprite.h b/libswfdec/swfdec_sprite.h
index 1812302..43aa4d1 100644
--- a/libswfdec/swfdec_sprite.h
+++ b/libswfdec/swfdec_sprite.h
@@ -102,6 +102,7 @@ void swfdec_content_free (SwfdecContent 
 int tag_show_frame (SwfdecSwfDecoder * s);
 int tag_func_set_background_color (SwfdecSwfDecoder * s);
 int swfdec_spriteseg_place_object_2 (SwfdecSwfDecoder * s);
+int swfdec_spriteseg_place_object_3 (SwfdecSwfDecoder * s);
 int swfdec_spriteseg_remove_object (SwfdecSwfDecoder * s);
 int swfdec_spriteseg_remove_object_2 (SwfdecSwfDecoder * s);
 
diff --git a/libswfdec/swfdec_tag.c b/libswfdec/swfdec_tag.c
index c2f8343..c7373eb 100644
--- a/libswfdec/swfdec_tag.c
+++ b/libswfdec/swfdec_tag.c
@@ -558,7 +558,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", NULL, 0},
+  [SWFDEC_TAG_PLACEOBJECT3] = {"PlaceObject3", swfdec_spriteseg_place_object_3, SPRITE},
   [SWFDEC_TAG_IMPORTASSETS2] = {"ImportAssets2", NULL, 0},
   [SWFDEC_TAG_DEFINEFONTALIGNZONES] = {"DefineFontAlignZones", NULL, 0},
   [SWFDEC_TAG_CSMTEXTSETTINGS] = {"CSMTextSettings", NULL, 0},


More information about the Swfdec mailing list