[Swfdec] 7 commits - libswfdec/swfdec_codec_gst.c libswfdec/swfdec_font.c libswfdec/swfdec_js_movie.c libswfdec/swfdec_morph_movie.c libswfdec/swfdec_pattern.c libswfdec/swfdec_pattern.h libswfdec/swfdec_shape.c libswfdec/swfdec_shape.h libswfdec/swfdec_sprite.c libswfdec/swfdec_stroke.c libswfdec/swfdec_stroke.h libswfdec/swfdec_tag.c test/dump.c

Benjamin Otte company at kemper.freedesktop.org
Mon Apr 16 00:59:21 PDT 2007


 libswfdec/swfdec_codec_gst.c   |    2 
 libswfdec/swfdec_font.c        |    4 
 libswfdec/swfdec_js_movie.c    |   39 ++++++++-
 libswfdec/swfdec_morph_movie.c |   18 ++--
 libswfdec/swfdec_pattern.c     |  130 +++++++++++++++++++------------
 libswfdec/swfdec_pattern.h     |   16 ++-
 libswfdec/swfdec_shape.c       |   99 +++++++++++++-----------
 libswfdec/swfdec_shape.h       |   11 +-
 libswfdec/swfdec_sprite.c      |    8 +
 libswfdec/swfdec_stroke.c      |  167 +++++++++++++++++++++++++++++++++--------
 libswfdec/swfdec_stroke.h      |   39 ++++++---
 libswfdec/swfdec_tag.c         |    2 
 test/dump.c                    |   23 +++--
 13 files changed, 380 insertions(+), 178 deletions(-)

New commits:
diff-tree c396c1d9b1488becf71c3ab32ea5b7cd510b8a47 (from ef3becaadc12e3167a7c02a4a8185bf02d9737e2)
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Apr 16 09:52:20 2007 +0200

    make hitTest not crash if the movie's parents don't match
    
    Attempt to do the right thing instead. (Untested)

diff --git a/libswfdec/swfdec_js_movie.c b/libswfdec/swfdec_js_movie.c
index 3f6333c..53fb5d9 100644
--- a/libswfdec/swfdec_js_movie.c
+++ b/libswfdec/swfdec_js_movie.c
@@ -308,7 +308,9 @@ mc_hitTest (JSContext *cx, JSObject *obj
   }
   
   if (argc == 1) {
-    SwfdecMovie *other;
+    SwfdecMovie *other, *tmp;
+    SwfdecRect movie_rect, other_rect;
+    guint movie_depth, other_depth;
     other = swfdec_scriptable_from_jsval (cx, argv[0], SWFDEC_TYPE_MOVIE);
     if (other == NULL) {
       SWFDEC_ERROR ("FIXME: what happens now?");
@@ -316,9 +318,36 @@ mc_hitTest (JSContext *cx, JSObject *obj
     }
     other = SWFDEC_MOVIE (JS_GetPrivate(cx, JSVAL_TO_OBJECT (argv[0])));
     swfdec_movie_update (movie);
-    swfdec_movie_update (other);
-    /* FIXME */
-    g_assert (movie->parent == other->parent);
+    if (movie->parent != other->parent) {
+      movie_rect = movie->original_extents;
+      other_rect = other->original_extents;
+      swfdec_movie_update (other);
+      tmp = movie;
+      for (movie_depth = 0; tmp->parent; movie_depth++)
+	tmp = tmp->parent;
+      tmp = other;
+      for (other_depth = 0; tmp->parent; other_depth++)
+	tmp = tmp->parent;
+      while (movie_depth > other_depth) {
+	swfdec_rect_transform (&movie_rect, &movie_rect, &movie->matrix);
+	movie = movie->parent;
+	movie_depth--;
+      }
+      while (other_depth > movie_depth) {
+	swfdec_rect_transform (&other_rect, &other_rect, &other->matrix);
+	other = other->parent;
+	other_depth--;
+      }
+      while (other != movie && other->parent) {
+	swfdec_rect_transform (&movie_rect, &movie_rect, &movie->matrix);
+	movie = movie->parent;
+	swfdec_rect_transform (&other_rect, &other_rect, &other->matrix);
+	other = other->parent;
+      }
+    } else {
+      movie_rect = movie->extents;
+      other_rect = other->extents;
+    }
 #if 0
     g_print ("%g %g  %g %g --- %g %g  %g %g\n", 
 	SWFDEC_OBJECT (movie)->extents.x0, SWFDEC_OBJECT (movie)->extents.y0,
@@ -326,7 +355,7 @@ mc_hitTest (JSContext *cx, JSObject *obj
 	SWFDEC_OBJECT (other)->extents.x0, SWFDEC_OBJECT (other)->extents.y0,
 	SWFDEC_OBJECT (other)->extents.x1, SWFDEC_OBJECT (other)->extents.y1);
 #endif
-    if (swfdec_rect_intersect (NULL, &movie->extents, &other->extents)) {
+    if (swfdec_rect_intersect (NULL, &movie_rect, &other_rect)) {
       *rval = BOOLEAN_TO_JSVAL (JS_TRUE);
     } else {
       *rval = BOOLEAN_TO_JSVAL (JS_FALSE);
diff-tree ef3becaadc12e3167a7c02a4a8185bf02d9737e2 (from f2fadf23193be3fd4966809e4d0c34d288127b63)
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Apr 16 09:34:18 2007 +0200

    implement focal gradients

diff --git a/libswfdec/swfdec_pattern.c b/libswfdec/swfdec_pattern.c
index 0041aea..dc9282f 100644
--- a/libswfdec/swfdec_pattern.c
+++ b/libswfdec/swfdec_pattern.c
@@ -178,6 +178,7 @@ struct _SwfdecGradientPattern
   SwfdecGradient *	gradient;		/* gradient to paint */
   gboolean		radial;			/* TRUE for radial gradient, FALSE for linear gradient */
   gboolean		morph;			/* TRUE for morph gradients */
+  double		focus;			/* focus point */
 };
 
 struct _SwfdecGradientPatternClass
@@ -208,10 +209,12 @@ swfdec_gradient_pattern_get_pattern (Swf
   {
     cairo_matrix_t mat;
     swfdec_matrix_morph (&mat, &pat->start_transform, &pat->end_transform, ratio);
-    if (gradient->radial)
-      pattern = cairo_pattern_create_radial (0, 0, 0, 0, 0, 16384 / 256.0);
-    else
+    if (gradient->radial) {
+      pattern = cairo_pattern_create_radial ((16384.0 / 256.0) * gradient->focus, 
+	  0, 0, 0, 0, 16384 / 256.0);
+    } else {
       pattern = cairo_pattern_create_linear (-16384.0 / 256.0, 0, 16384.0 / 256.0, 0);
+    }
     cairo_matrix_scale (&mat, 1 / 256.0, 1 / 256.0);
     mat.x0 /= 256.0;
     mat.y0 /= 256.0;
@@ -289,16 +292,22 @@ swfdec_pattern_do_parse (SwfdecSwfDecode
     }
     SWFDEC_COLOR_PATTERN (pattern)->end_color = SWFDEC_COLOR_PATTERN (pattern)->start_color;
     SWFDEC_LOG ("    color %08x", SWFDEC_COLOR_PATTERN (pattern)->start_color);
-  } else if (paint_style_type == 0x10 || paint_style_type == 0x12) {
+  } else if (paint_style_type == 0x10 || paint_style_type == 0x12 || paint_style_type == 0x13) {
+    SwfdecGradientPattern *gradient;
     pattern = g_object_new (SWFDEC_TYPE_GRADIENT_PATTERN, NULL);
+    gradient = SWFDEC_GRADIENT_PATTERN (pattern);
     swfdec_bits_get_matrix (bits, &pattern->start_transform, NULL);
     pattern->end_transform = pattern->start_transform;
     if (rgba) {
-      SWFDEC_GRADIENT_PATTERN (pattern)->gradient = swfdec_bits_get_gradient_rgba (bits);
+      gradient->gradient = swfdec_bits_get_gradient_rgba (bits);
     } else {
-      SWFDEC_GRADIENT_PATTERN (pattern)->gradient = swfdec_bits_get_gradient (bits);
+      gradient->gradient = swfdec_bits_get_gradient (bits);
+    }
+    gradient->radial = (paint_style_type != 0x10);
+    /* FIXME: need a way to ensure 0x13 only happens in Flash 8 */
+    if (paint_style_type == 0x13) {
+      gradient->focus = swfdec_bits_get_s16 (bits) / 256.0;
     }
-    SWFDEC_GRADIENT_PATTERN (pattern)->radial = (paint_style_type == 0x12);
   } else if (paint_style_type >= 0x40 && paint_style_type <= 0x43) {
     guint paint_id = swfdec_bits_get_u16 (bits);
     SWFDEC_LOG ("   background paint id = %d (type 0x%02x)",
diff-tree f2fadf23193be3fd4966809e4d0c34d288127b63 (from a99f988c1777df84a2fe0b91a6f10292cba3d07a)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Apr 15 23:00:21 2007 +0200

    implement DefineShape4 in a very unsupported way

diff --git a/libswfdec/swfdec_font.c b/libswfdec/swfdec_font.c
index 9efe573..0aca1d5 100644
--- a/libswfdec/swfdec_font.c
+++ b/libswfdec/swfdec_font.c
@@ -192,7 +192,7 @@ swfdec_font_parse_shape (SwfdecSwfDecode
   shape->n_line_bits = swfdec_bits_getbits (&s->b, 4);
   SWFDEC_LOG ("n_line_bits = %d", shape->n_line_bits);
 
-  swfdec_shape_get_recs (s, shape);
+  swfdec_shape_get_recs (s, shape, swfdec_pattern_parse, swfdec_stroke_parse);
   swfdec_bits_syncbits (&s->b);
   if (swfdec_bits_skip_bytes (&save_bits, size) != size) {
     SWFDEC_ERROR ("invalid offset value, not enough bytes available");
@@ -336,7 +336,7 @@ tag_func_define_font_2 (SwfdecSwfDecoder
     shape->n_line_bits = swfdec_bits_getbits (&s->b, 4);
     SWFDEC_LOG ("n_line_bits = %d", shape->n_line_bits);
 
-    swfdec_shape_get_recs (s, shape);
+    swfdec_shape_get_recs (s, shape, swfdec_pattern_parse, swfdec_stroke_parse);
   }
   if (wide_codes) {
     swfdec_bits_skip_bytes (bits, 2 * n_glyphs);
diff --git a/libswfdec/swfdec_pattern.c b/libswfdec/swfdec_pattern.c
index 5efac10..0041aea 100644
--- a/libswfdec/swfdec_pattern.c
+++ b/libswfdec/swfdec_pattern.c
@@ -269,24 +269,13 @@ swfdec_gradient_pattern_init (SwfdecGrad
 
 /*** EXPORTED API ***/
 
-/**
- * swfdec_pattern_parse:
- * @dec: a #SwfdecDecoder to parse from
- * @rgba: TRUE if colors are RGBA, FALSE if they're just RGB
- *
- * Continues parsing @dec into a new #SwfdecPattern
- *
- * Returns: a new #SwfdecPattern or NULL on error
- **/
-SwfdecPattern *
-swfdec_pattern_parse (SwfdecSwfDecoder *dec, gboolean rgba)
+static SwfdecPattern *
+swfdec_pattern_do_parse (SwfdecSwfDecoder *dec, gboolean rgba)
 {
   guint paint_style_type;
   SwfdecBits *bits;
   SwfdecPattern *pattern;
 
-  g_return_val_if_fail (dec != NULL, NULL);
-
   bits = &dec->b;
   paint_style_type = swfdec_bits_get_u8 (bits);
   SWFDEC_LOG ("    type 0x%02x", paint_style_type);
@@ -356,6 +345,31 @@ swfdec_pattern_parse (SwfdecSwfDecoder *
 }
 
 /**
+ * swfdec_pattern_parse:
+ * @dec: a #SwfdecDecoder to parse from
+ * @rgba: TRUE if colors are RGBA, FALSE if they're just RGB
+ *
+ * Continues parsing @dec into a new #SwfdecPattern
+ *
+ * Returns: a new #SwfdecPattern or NULL on error
+ **/
+SwfdecPattern *
+swfdec_pattern_parse (SwfdecSwfDecoder *dec)
+{
+  g_return_val_if_fail (dec != NULL, NULL);
+
+  return swfdec_pattern_do_parse (dec, FALSE);
+}
+
+SwfdecPattern *
+swfdec_pattern_parse_rgba (SwfdecSwfDecoder *dec)
+{
+  g_return_val_if_fail (dec != NULL, NULL);
+
+  return swfdec_pattern_do_parse (dec, TRUE);
+}
+
+/**
  * swfdec_pattern_parse_morph:
  * @dec: a #SwfdecDecoder to parse from
  *
@@ -511,9 +525,6 @@ 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)) {
-    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));
   }
diff --git a/libswfdec/swfdec_pattern.h b/libswfdec/swfdec_pattern.h
index 6a0d2c7..cc63645 100644
--- a/libswfdec/swfdec_pattern.h
+++ b/libswfdec/swfdec_pattern.h
@@ -58,8 +58,8 @@ struct _SwfdecPatternClass
 GType		swfdec_pattern_get_type		(void);
 
 SwfdecPattern *	swfdec_pattern_new_color	(SwfdecColor			color);
-SwfdecPattern *	swfdec_pattern_parse		(SwfdecSwfDecoder *		dec,
-						 gboolean			rgba);
+SwfdecPattern *	swfdec_pattern_parse		(SwfdecSwfDecoder *		dec);
+SwfdecPattern *	swfdec_pattern_parse_rgba     	(SwfdecSwfDecoder *		dec);
 SwfdecPattern *	swfdec_pattern_parse_morph    	(SwfdecSwfDecoder *		dec);
 
 void		swfdec_pattern_paint		(SwfdecPattern *		pattern, 
diff --git a/libswfdec/swfdec_shape.c b/libswfdec/swfdec_shape.c
index 3d513cc..eb7161a 100644
--- a/libswfdec/swfdec_shape.c
+++ b/libswfdec/swfdec_shape.c
@@ -313,8 +313,6 @@ swfdec_shape_init (SwfdecShape * shape)
   shape->vecs = g_array_new (FALSE, TRUE, sizeof (SwfdecShapeVec));
 }
 
-typedef SwfdecPattern * (* SwfdecPatternFunc) (SwfdecSwfDecoder * s);
-typedef SwfdecStroke * (* SwfdecStrokeFunc) (SwfdecSwfDecoder * s);
 static void
 swfdec_shape_add_styles (SwfdecSwfDecoder * s, SwfdecShape * shape,
     SwfdecPatternFunc parse_fill, SwfdecStrokeFunc parse_stroke)
@@ -356,30 +354,6 @@ swfdec_shape_add_styles (SwfdecSwfDecode
   shape->n_line_bits = swfdec_bits_getbits (bits, 4);
 }
 
-static SwfdecPattern *
-parse_rgb (SwfdecSwfDecoder * s)
-{
-  return swfdec_pattern_parse (s, FALSE);
-}
-
-static SwfdecPattern *
-parse_rgba (SwfdecSwfDecoder * s)
-{
-  return swfdec_pattern_parse (s, TRUE);
-}
-
-static SwfdecStroke *
-parse_stroke_rgb (SwfdecSwfDecoder * s)
-{
-  return swfdec_stroke_parse (s, FALSE);
-}
-
-static SwfdecStroke *
-parse_stroke_rgba (SwfdecSwfDecoder * s)
-{
-  return swfdec_stroke_parse (s, TRUE);
-}
-
 int
 tag_define_shape (SwfdecSwfDecoder * s)
 {
@@ -397,9 +371,9 @@ tag_define_shape (SwfdecSwfDecoder * s)
 
   swfdec_bits_get_rect (bits, &SWFDEC_GRAPHIC (shape)->extents);
 
-  swfdec_shape_add_styles (s, shape, parse_rgb, parse_stroke_rgb);
+  swfdec_shape_add_styles (s, shape, swfdec_pattern_parse, swfdec_stroke_parse);
 
-  swfdec_shape_get_recs (s, shape);
+  swfdec_shape_get_recs (s, shape, swfdec_pattern_parse, swfdec_stroke_parse);
 
   return SWFDEC_STATUS_OK;
 }
@@ -418,11 +392,9 @@ tag_define_shape_3 (SwfdecSwfDecoder * s
 
   swfdec_bits_get_rect (bits, &SWFDEC_GRAPHIC (shape)->extents);
 
-  shape->rgba = 1;
-
-  swfdec_shape_add_styles (s, shape, parse_rgba, parse_stroke_rgba);
+  swfdec_shape_add_styles (s, shape, swfdec_pattern_parse_rgba, swfdec_stroke_parse_rgba);
 
-  swfdec_shape_get_recs (s, shape);
+  swfdec_shape_get_recs (s, shape, swfdec_pattern_parse_rgba, swfdec_stroke_parse_rgba);
 
   return SWFDEC_STATUS_OK;
 }
@@ -433,29 +405,39 @@ tag_define_shape_2 (SwfdecSwfDecoder * s
   return tag_define_shape (s);
 }
 
-#if 0
 int
 tag_define_shape_4 (SwfdecSwfDecoder *s)
 {
   SwfdecBits *bits = &s->b;
   SwfdecShape *shape;
   int id;
+  SwfdecRect tmp;
+  gboolean has_scale_strokes, has_noscale_strokes;
 
   id = swfdec_bits_get_u16 (bits);
   shape = swfdec_swf_decoder_create_character (s, id, SWFDEC_TYPE_SHAPE);
   if (!shape)
     return SWFDEC_STATUS_OK;
-  shape->rgba = 1;
 
   swfdec_bits_get_rect (bits, &SWFDEC_GRAPHIC (shape)->extents);
+  SWFDEC_LOG ("  extents: %g %g x %g %g", 
+      SWFDEC_GRAPHIC (shape)->extents.x0, SWFDEC_GRAPHIC (shape)->extents.y0,
+      SWFDEC_GRAPHIC (shape)->extents.x1, SWFDEC_GRAPHIC (shape)->extents.y1);
+  swfdec_bits_get_rect (bits, &tmp);
+  SWFDEC_LOG ("  extents: %g %g x %g %g", 
+      tmp.x0, tmp.y0, tmp.x1, tmp.y1);
+  swfdec_bits_getbits (bits, 6);
+  has_scale_strokes = swfdec_bits_getbit (bits);
+  has_noscale_strokes = swfdec_bits_getbit (bits);
+  SWFDEC_LOG ("  has scaling strokes: %d", has_scale_strokes);
+  SWFDEC_LOG ("  has non-scaling strokes: %d", has_noscale_strokes);
 
-  swfdec_shape_add_styles (s, shape, parse_rgba, swfdec_stroke_parse_extended);
+  swfdec_shape_add_styles (s, shape, swfdec_pattern_parse_rgba, swfdec_stroke_parse_extended);
 
-  swfdec_shape_get_recs (s, shape);
+  swfdec_shape_get_recs (s, shape, swfdec_pattern_parse_rgba, swfdec_stroke_parse_extended);
 
   return SWFDEC_STATUS_OK;
 }
-#endif
 
 /* The shape creation process is a bit complicated since it requires matching 
  * the Flash model to the cairo model. Note that this code is just random 
@@ -828,7 +810,8 @@ swfdec_shape_initialize_from_sub_paths (
 }
 
 void
-swfdec_shape_get_recs (SwfdecSwfDecoder * s, SwfdecShape * shape)
+swfdec_shape_get_recs (SwfdecSwfDecoder * s, SwfdecShape * shape,
+    SwfdecPatternFunc pattern_func, SwfdecStrokeFunc stroke_func)
 {
   int x = 0, y = 0;
   SubPath *path = NULL;
@@ -842,10 +825,7 @@ swfdec_shape_get_recs (SwfdecSwfDecoder 
   while ((type = swfdec_shape_peek_type (bits))) {
     switch (type) {
       case SWFDEC_SHAPE_TYPE_CHANGE:
-	if (shape->rgba)
-	  path = swfdec_shape_parse_change (s, shape, path_array, path, &x, &y, parse_rgba, parse_stroke_rgba);
-	else
-	  path = swfdec_shape_parse_change (s, shape, path_array, path, &x, &y, parse_rgb, parse_stroke_rgb);
+	path = swfdec_shape_parse_change (s, shape, path_array, path, &x, &y, pattern_func, stroke_func);
 	break;
       case SWFDEC_SHAPE_TYPE_LINE:
 	swfdec_shape_parse_line (bits, path, &x, &y, FALSE);
diff --git a/libswfdec/swfdec_shape.h b/libswfdec/swfdec_shape.h
index 9ee709e..d3d998d 100644
--- a/libswfdec/swfdec_shape.h
+++ b/libswfdec/swfdec_shape.h
@@ -27,6 +27,7 @@
 #include <libswfdec/swfdec_bits.h>
 #include <libswfdec/swfdec_graphic.h>
 #include <libswfdec/swfdec_pattern.h>
+#include <libswfdec/swfdec_stroke.h>
 #include <libswfdec/swfdec_swf_decoder.h>
 
 G_BEGIN_DECLS
@@ -34,6 +35,9 @@ G_BEGIN_DECLS
 //typedef struct _SwfdecShape SwfdecShape;
 typedef struct _SwfdecShapeClass SwfdecShapeClass;
 
+typedef SwfdecPattern * (* SwfdecPatternFunc) (SwfdecSwfDecoder * s);
+typedef SwfdecStroke * (* SwfdecStrokeFunc) (SwfdecSwfDecoder * s);
+
 #define SWFDEC_TYPE_SHAPE                    (swfdec_shape_get_type())
 #define SWFDEC_IS_SHAPE(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_SHAPE))
 #define SWFDEC_IS_SHAPE_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_SHAPE))
@@ -63,7 +67,6 @@ struct _SwfdecShape
   guint lines_offset;
   guint n_fill_bits;
   guint n_line_bits;
-  gboolean rgba;
 };
 
 struct _SwfdecShapeClass
@@ -76,7 +79,9 @@ GType swfdec_shape_get_type (void);
 int tag_define_shape (SwfdecSwfDecoder * s);
 int tag_define_shape_2 (SwfdecSwfDecoder * s);
 int tag_define_shape_3 (SwfdecSwfDecoder * s);
-void swfdec_shape_get_recs (SwfdecSwfDecoder * s, SwfdecShape * shape);
+int tag_define_shape_4 (SwfdecSwfDecoder * s);
+void swfdec_shape_get_recs (SwfdecSwfDecoder * s, SwfdecShape * shape,
+    SwfdecPatternFunc pattern_func, SwfdecStrokeFunc stroke_func);
 
 
 G_END_DECLS
diff --git a/libswfdec/swfdec_stroke.c b/libswfdec/swfdec_stroke.c
index 4f8e5d1..893380d 100644
--- a/libswfdec/swfdec_stroke.c
+++ b/libswfdec/swfdec_stroke.c
@@ -143,18 +143,29 @@ swfdec_stroke_init (SwfdecStroke *stroke
 /*** EXPORTED API ***/
 
 SwfdecStroke *
-swfdec_stroke_parse (SwfdecSwfDecoder *dec, gboolean rgba)
+swfdec_stroke_parse (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 = stroke->start_width;
-  if (rgba) {
-    stroke->start_color = swfdec_bits_get_rgba (bits);
-  } else {
-    stroke->start_color = swfdec_bits_get_color (bits);
-  }
+  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 stroke;
+}
+
+SwfdecStroke *
+swfdec_stroke_parse_rgba (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 = stroke->start_width;
+  stroke->start_color = swfdec_bits_get_rgba (bits);
   stroke->end_color = stroke->start_color;
   SWFDEC_LOG ("new stroke stroke: width %u color %08x", stroke->start_width, stroke->start_color);
 
@@ -269,7 +280,7 @@ swfdec_stroke_do_parse_extended (SwfdecS
     if (morph) {
       stroke->pattern = swfdec_pattern_parse_morph (dec);
     } else {
-      stroke->pattern = swfdec_pattern_parse (dec, TRUE);
+      stroke->pattern = swfdec_pattern_parse_rgba (dec);
     }
   } else {
     stroke->start_color = swfdec_bits_get_rgba (bits);
diff --git a/libswfdec/swfdec_stroke.h b/libswfdec/swfdec_stroke.h
index 016d3ca..9ad694c 100644
--- a/libswfdec/swfdec_stroke.h
+++ b/libswfdec/swfdec_stroke.h
@@ -70,8 +70,8 @@ void		swfdec_stroke_paint		(SwfdecStroke
 						 const SwfdecColorTransform *trans,
 						 guint			ratio);
 
-SwfdecStroke *	swfdec_stroke_parse		(SwfdecSwfDecoder *	dec,
-						 gboolean		rgba);
+SwfdecStroke *	swfdec_stroke_parse		(SwfdecSwfDecoder *	dec);
+SwfdecStroke *	swfdec_stroke_parse_rgba      	(SwfdecSwfDecoder *	dec);
 SwfdecStroke *	swfdec_stroke_parse_extended	(SwfdecSwfDecoder *	dec);
 SwfdecStroke *	swfdec_stroke_parse_morph    	(SwfdecSwfDecoder *	dec);
 SwfdecStroke *	swfdec_stroke_parse_morph_extended
diff --git a/libswfdec/swfdec_tag.c b/libswfdec/swfdec_tag.c
index c7373eb..e372fc1 100644
--- a/libswfdec/swfdec_tag.c
+++ b/libswfdec/swfdec_tag.c
@@ -567,7 +567,7 @@ static struct tag_func_struct tag_funcs[
   [SWFDEC_TAG_METADATA] = {"Metadata", NULL, 0},
   [SWFDEC_TAG_DEFINESCALINGGRID] = {"DefineScalingGrid", NULL, 0},
   [SWFDEC_TAG_AVM2ACTION] = {"AVM2Action", NULL, 0},
-  [SWFDEC_TAG_DEFINESHAPE4] = {"DefineShape4", NULL, 0},
+  [SWFDEC_TAG_DEFINESHAPE4] = {"DefineShape4", tag_define_shape_4, 0},
   [SWFDEC_TAG_DEFINEMORPHSHAPE2] = {"DefineMorphShape2", NULL, 0},
 };
 
diff --git a/test/dump.c b/test/dump.c
index 9c0475e..96f9328 100644
--- a/test/dump.c
+++ b/test/dump.c
@@ -188,17 +188,22 @@ dump_shape (SwfdecShape *shape)
     shapevec = &g_array_index (shape->vecs, SwfdecShapeVec, i);
 
     g_print("   %3u: ", shapevec->last_index);
-    if (shapevec->pattern == NULL) {
-      g_print ("not filled\n");
-    } else {
-      char *str = swfdec_pattern_to_string (shapevec->pattern);
+    if (SWFDEC_IS_PATTERN (shapevec->pattern)) {
+      SwfdecPattern *pattern = shapevec->pattern;
+      char *str = swfdec_pattern_to_string (pattern);
       g_print ("%s\n", str);
       g_free (str);
-      if (verbose)
-      g_print ("        %g %g  %g %g  %g %g\n", 
-	  shapevec->pattern->start_transform.xx, shapevec->pattern->start_transform.xy,
-	  shapevec->pattern->start_transform.yx, shapevec->pattern->start_transform.yy,
-	  shapevec->pattern->start_transform.x0, shapevec->pattern->start_transform.y0);
+      if (verbose) {
+	g_print ("        %g %g  %g %g  %g %g\n", 
+	    pattern->start_transform.xx, pattern->start_transform.xy,
+	    pattern->start_transform.yx, pattern->start_transform.yy,
+	    pattern->start_transform.x0, pattern->start_transform.y0);
+      }
+    } else if (SWFDEC_IS_STROKE (shapevec->pattern)) {
+      SwfdecStroke *line = SWFDEC_STROKE (shapevec->pattern);
+      g_print ("line (width %u, color #%08X)", line->start_width, line->start_color);
+    } else {
+      g_print ("not filled\n");
     }
     if (verbose) {
       dump_path (&shapevec->path);
diff-tree a99f988c1777df84a2fe0b91a6f10292cba3d07a (from 4997a85872e08b16e9a0283cd60242285cb51674)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Apr 15 22:56:45 2007 +0200

    oops, wrong order
    
    Read the depth before the new flags, which is wrong

diff --git a/libswfdec/swfdec_sprite.c b/libswfdec/swfdec_sprite.c
index 86f7997..f3ad17d 100644
--- a/libswfdec/swfdec_sprite.c
+++ b/libswfdec/swfdec_sprite.c
@@ -346,7 +346,6 @@ swfdec_spriteseg_do_place_object (Swfdec
   has_matrix = swfdec_bits_getbit (bits);
   has_character = swfdec_bits_getbit (bits);
   move = swfdec_bits_getbit (bits);
-  depth = swfdec_bits_get_u16 (bits);
 
   SWFDEC_LOG ("  has_clip_actions = %d", has_clip_actions);
   SWFDEC_LOG ("  has_clip_depth = %d", has_clip_depth);
@@ -356,18 +355,21 @@ swfdec_spriteseg_do_place_object (Swfdec
   SWFDEC_LOG ("  has_matrix = %d", has_matrix);
   SWFDEC_LOG ("  has_character = %d", has_character);
   SWFDEC_LOG ("  move = %d", move);
-  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 ("  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);
+  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, has_character || has_name);
   if (has_character) {
diff-tree 4997a85872e08b16e9a0283cd60242285cb51674 (from ab7ac15f7e1f4290125e5bd938541fc28ade5aed)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sat Apr 14 00:13:33 2007 +0200

    implement the Flash 8 linestyle reading
    
    This includes some shuffling around of code (like where
    line caps and joins are set)

diff --git a/libswfdec/swfdec_morph_movie.c b/libswfdec/swfdec_morph_movie.c
index 46ebd30..34b4d68 100644
--- a/libswfdec/swfdec_morph_movie.c
+++ b/libswfdec/swfdec_morph_movie.c
@@ -50,8 +50,6 @@ swfdec_morph_movie_render (SwfdecMovie *
 
   cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
   cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
-  cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
-  cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
 
   for (i = 0; i < shape->vecs->len; i++) {
     SwfdecShapeVec *vec = &g_array_index (shape->vecs, SwfdecShapeVec, i);
diff --git a/libswfdec/swfdec_shape.c b/libswfdec/swfdec_shape.c
index 34e85a9..3d513cc 100644
--- a/libswfdec/swfdec_shape.c
+++ b/libswfdec/swfdec_shape.c
@@ -238,8 +238,6 @@ swfdec_shape_render (SwfdecGraphic *grap
 
   cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
   cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
-  cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
-  cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
 
   for (i = 0; i < shape->vecs->len; i++) {
     SwfdecShapeVec *vec = &g_array_index (shape->vecs, SwfdecShapeVec, i);
diff --git a/libswfdec/swfdec_stroke.c b/libswfdec/swfdec_stroke.c
index 30adef9..4f8e5d1 100644
--- a/libswfdec/swfdec_stroke.c
+++ b/libswfdec/swfdec_stroke.c
@@ -99,6 +99,17 @@ swfdec_stroke_paint (SwfdecStroke *strok
   SwfdecColor color;
   double width;
 
+  g_return_if_fail (SWFDEC_IS_STROKE (stroke));
+  g_return_if_fail (cr != NULL);
+  g_return_if_fail (path != NULL);
+  g_return_if_fail (trans != NULL);
+  g_return_if_fail (ratio < 65536);
+
+  cairo_set_line_cap (cr, stroke->start_cap);
+  cairo_set_line_join (cr, stroke->join);
+  if (stroke->join == CAIRO_LINE_JOIN_MITER)
+    cairo_set_miter_limit (cr, stroke->miter_limit);
+
   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);
@@ -124,6 +135,9 @@ swfdec_stroke_class_init (SwfdecStrokeCl
 static void
 swfdec_stroke_init (SwfdecStroke *stroke)
 {
+  stroke->start_cap = CAIRO_LINE_CAP_ROUND;
+  stroke->end_cap = CAIRO_LINE_CAP_ROUND;
+  stroke->join = CAIRO_LINE_JOIN_ROUND;
 }
 
 /*** EXPORTED API ***/
@@ -177,32 +191,112 @@ swfdec_stroke_new (guint width, SwfdecCo
   return stroke;
 }
 
+static cairo_line_cap_t
+swfdec_line_cap_get (guint cap)
+{
+  switch (cap) {
+    case 0:
+      return CAIRO_LINE_CAP_ROUND;
+    case 1:
+      return CAIRO_LINE_CAP_BUTT;
+    case 2:
+      return CAIRO_LINE_CAP_SQUARE;
+    default:
+      SWFDEC_ERROR ("invalid line cap value %u", cap);
+      return CAIRO_LINE_CAP_ROUND;
+  }
+}
+static cairo_line_join_t
+swfdec_line_join_get (guint join)
+{
+  switch (join) {
+    case 0:
+      return CAIRO_LINE_JOIN_ROUND;
+    case 1:
+      return CAIRO_LINE_JOIN_BEVEL;
+    case 2:
+      return CAIRO_LINE_JOIN_MITER;
+    default:
+      SWFDEC_ERROR ("invalid line join value %u", join);
+      return CAIRO_LINE_JOIN_ROUND;
+  }
+}
+
 static SwfdecStroke *
-swfdec_stroke_do_parse_extended (SwfdecBits *bits, gboolean morph,
-    SwfdecPattern *fill_styles, guint n_fill_styles)
+swfdec_stroke_do_parse_extended (SwfdecSwfDecoder *dec, gboolean morph)
 {
+  SwfdecBits *bits = &dec->b;
+  guint tmp;
+  gboolean has_pattern;
   SwfdecStroke *stroke = g_object_new (SWFDEC_TYPE_STROKE, NULL);
 
-  SWFDEC_ERROR ("FIXME: implement");
+  stroke->start_width = swfdec_bits_get_u16 (bits);
+  if (morph) {
+    stroke->end_width = swfdec_bits_get_u16 (bits);
+    SWFDEC_LOG ("  width: %u => %u", stroke->start_width, stroke->end_width);
+  } else {
+    stroke->end_width = stroke->start_width;
+    SWFDEC_LOG ("  width: %u", stroke->start_width);
+  }
+  tmp = swfdec_bits_getbits (bits, 2);
+  SWFDEC_LOG ("  start cap: %u", tmp);
+  stroke->start_cap = swfdec_line_cap_get (tmp);
+  tmp = swfdec_bits_getbits (bits, 2);
+  SWFDEC_LOG ("  line join: %u", tmp);
+  stroke->join = swfdec_line_join_get (tmp);
+  has_pattern = swfdec_bits_getbit (bits);
+  SWFDEC_LOG ("  has pattern: %d", has_pattern);
+  stroke->no_hscale = swfdec_bits_getbit (bits);
+  SWFDEC_LOG ("  no hscale: %d", stroke->no_hscale);
+  stroke->no_vscale = swfdec_bits_getbit (bits);
+  SWFDEC_LOG ("  no vscale: %d", stroke->no_vscale);
+  stroke->align_pixel = swfdec_bits_getbit (bits);
+  SWFDEC_LOG ("  align pixels: %d", stroke->align_pixel);
+  tmp = swfdec_bits_getbits (bits, 5);
+  stroke->no_close = swfdec_bits_getbit (bits);
+  SWFDEC_LOG ("  no close: %d", stroke->no_close);
+  tmp = swfdec_bits_getbits (bits, 2);
+  SWFDEC_LOG ("  end cap: %u", tmp);
+  stroke->end_cap = swfdec_line_cap_get (tmp);
+  if (stroke->end_cap != stroke->start_cap) {
+    SWFDEC_WARNING ("FIXME: different caps on start and end of line are unsupported");
+  }
+  if (stroke->join == CAIRO_LINE_JOIN_MITER) {
+    stroke->miter_limit = swfdec_bits_get_u16 (bits);
+    SWFDEC_LOG ("  miter limit: %u", stroke->miter_limit);
+  }
+  if (has_pattern) {
+    if (morph) {
+      stroke->pattern = swfdec_pattern_parse_morph (dec);
+    } else {
+      stroke->pattern = swfdec_pattern_parse (dec, TRUE);
+    }
+  } else {
+    stroke->start_color = swfdec_bits_get_rgba (bits);
+    if (morph) {
+      stroke->end_color = swfdec_bits_get_rgba (bits);
+      SWFDEC_LOG ("  color: #%08X", stroke->start_color);
+    } else {
+      stroke->end_color = stroke->start_color;
+      SWFDEC_LOG ("  color: #%08X", stroke->start_color);
+    }
+  }
+
   return stroke;
 }
 
 SwfdecStroke *
-swfdec_stroke_parse_extended (SwfdecSwfDecoder *dec, SwfdecPattern *fill_styles,
-    guint n_fill_styles)
+swfdec_stroke_parse_extended (SwfdecSwfDecoder *dec)
 {
   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);
+  return swfdec_stroke_do_parse_extended (dec, FALSE);
 }
 
 SwfdecStroke *
-swfdec_stroke_parse_morph_extended (SwfdecSwfDecoder *dec, SwfdecPattern *fill_styles,
-    guint n_fill_styles)
+swfdec_stroke_parse_morph_extended (SwfdecSwfDecoder *dec)
 {
   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);
+  return swfdec_stroke_do_parse_extended (dec, TRUE);
 }
diff --git a/libswfdec/swfdec_stroke.h b/libswfdec/swfdec_stroke.h
index 37fd990..016d3ca 100644
--- a/libswfdec/swfdec_stroke.h
+++ b/libswfdec/swfdec_stroke.h
@@ -42,6 +42,16 @@ struct _SwfdecStroke
   SwfdecColor		start_color;		/* color to paint with */
   guint			end_width;		/* width of line */
   SwfdecColor		end_color;		/* color to paint with */
+  /* Flash 8 */
+  SwfdecPattern *	pattern;		/* pattern to use instead of color if not NULL */
+  cairo_line_cap_t	start_cap;
+  cairo_line_cap_t	end_cap;
+  cairo_line_join_t	join;
+  guint			miter_limit;		/* only set when join = MITER */
+  gboolean		no_vscale;		/* don't scale line in vertical direction */
+  gboolean		no_hscale;		/* don't scale line in horizontal direction */
+  gboolean		align_pixel;		/* align control points on pixel boundaries */
+  gboolean		no_close;		/* don't auto-close lines */
 };
 
 struct _SwfdecStrokeClass
@@ -62,14 +72,10 @@ void		swfdec_stroke_paint		(SwfdecStroke
 
 SwfdecStroke *	swfdec_stroke_parse		(SwfdecSwfDecoder *	dec,
 						 gboolean		rgba);
-SwfdecStroke *	swfdec_stroke_parse_extended	(SwfdecSwfDecoder *	dec,
-						 SwfdecPattern *	fill_styles,
-						 guint			n_fill_styles);
+SwfdecStroke *	swfdec_stroke_parse_extended	(SwfdecSwfDecoder *	dec);
 SwfdecStroke *	swfdec_stroke_parse_morph    	(SwfdecSwfDecoder *	dec);
 SwfdecStroke *	swfdec_stroke_parse_morph_extended
-						(SwfdecSwfDecoder *	dec,
-						 SwfdecPattern *	fill_styles,
-						 guint			n_fill_styles);
+						(SwfdecSwfDecoder *	dec);
 
 
 G_END_DECLS
diff-tree ab7ac15f7e1f4290125e5bd938541fc28ade5aed (from 9a64282b9188bf335b9be029fd91e8a66ffddc8d)
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Apr 13 22:36:15 2007 +0200

    Make stroke and pattern 2 different objects
    
    Also change the way drawing patterns is handled.
    Still preparation for Flash 8 strokes.

diff --git a/libswfdec/swfdec_morph_movie.c b/libswfdec/swfdec_morph_movie.c
index 85ccc96..46ebd30 100644
--- a/libswfdec/swfdec_morph_movie.c
+++ b/libswfdec/swfdec_morph_movie.c
@@ -23,6 +23,7 @@
 
 #include "swfdec_morph_movie.h"
 #include "swfdec_debug.h"
+#include "swfdec_stroke.h"
 
 G_DEFINE_TYPE (SwfdecMorphMovie, swfdec_morph_movie, SWFDEC_TYPE_MOVIE)
 
@@ -63,13 +64,18 @@ swfdec_morph_movie_render (SwfdecMovie *
       continue;
     
     /* hack to not append paths for lines */
-    if (!fill && vec->last_index % 2 != 0) 
+    if (!fill && SWFDEC_IS_STROKE (vec->pattern))
       continue;
 
-    if (fill)
-      swfdec_pattern_paint (vec->pattern, cr, path, trans, movie->content->ratio);
-    else
-      cairo_append_path (cr, &vec->path);
+    if (fill) {
+      if (SWFDEC_IS_PATTERN (vec->pattern)) {
+	swfdec_pattern_paint (vec->pattern, cr, path, trans, movie->content->ratio);
+      } else {
+	swfdec_stroke_paint (vec->pattern, cr, path, trans, movie->content->ratio);
+      }
+    } else {
+      cairo_append_path (cr, path);
+    }
   }
 }
 
diff --git a/libswfdec/swfdec_pattern.c b/libswfdec/swfdec_pattern.c
index 8a2bda7..5efac10 100644
--- a/libswfdec/swfdec_pattern.c
+++ b/libswfdec/swfdec_pattern.c
@@ -74,24 +74,24 @@ struct _SwfdecColorPatternClass
 
 G_DEFINE_TYPE (SwfdecColorPattern, swfdec_color_pattern, SWFDEC_TYPE_PATTERN);
 
-static void
-swfdec_color_pattern_paint (SwfdecPattern *pat, cairo_t *cr, const cairo_path_t *path,
+static cairo_pattern_t *
+swfdec_color_pattern_get_pattern (SwfdecPattern *pat, 
     const SwfdecColorTransform *trans, guint ratio)
 {
   SwfdecColorPattern *pattern = SWFDEC_COLOR_PATTERN (pat);
   SwfdecColor color;
 
-  cairo_append_path (cr, (cairo_path_t *) path);
   color = swfdec_color_apply_morph (pattern->start_color, pattern->end_color, ratio);
   color = swfdec_color_apply_transform (color, trans);
-  swfdec_color_set_source (cr, color);
-  cairo_fill (cr);
+  return cairo_pattern_create_rgba ( 
+      SWFDEC_COLOR_R (color) / 255.0, SWFDEC_COLOR_G (color) / 255.0,
+      SWFDEC_COLOR_B (color) / 255.0, SWFDEC_COLOR_A (color) / 255.0);
 }
 
 static void
 swfdec_color_pattern_class_init (SwfdecColorPatternClass *klass)
 {
-  SWFDEC_PATTERN_CLASS (klass)->paint = swfdec_color_pattern_paint;
+  SWFDEC_PATTERN_CLASS (klass)->get_pattern = swfdec_color_pattern_get_pattern;
 }
 
 static void
@@ -127,8 +127,8 @@ struct _SwfdecImagePatternClass
 
 G_DEFINE_TYPE (SwfdecImagePattern, swfdec_image_pattern, SWFDEC_TYPE_PATTERN);
 
-static void
-swfdec_image_pattern_paint (SwfdecPattern *pat, cairo_t *cr, const cairo_path_t *path,
+static cairo_pattern_t *
+swfdec_image_pattern_get_pattern (SwfdecPattern *pat, 
     const SwfdecColorTransform *trans, guint ratio)
 {
   SwfdecImagePattern *image = SWFDEC_IMAGE_PATTERN (pat);
@@ -138,23 +138,20 @@ swfdec_image_pattern_paint (SwfdecPatter
   
   surface = swfdec_image_create_surface_transformed (image->image, trans);
   if (surface == NULL)
-    return;
-  cairo_append_path (cr, (cairo_path_t *) path);
+    return NULL;
   pattern = cairo_pattern_create_for_surface (surface);
   cairo_surface_destroy (surface);
   swfdec_matrix_morph (&mat, &pat->start_transform, &pat->end_transform, ratio);
   cairo_pattern_set_matrix (pattern, &mat);
   cairo_pattern_set_extend (pattern, image->extend);
   cairo_pattern_set_filter (pattern, image->filter);
-  cairo_set_source (cr, pattern);
-  cairo_pattern_destroy (pattern);
-  cairo_fill (cr);
+  return pattern;
 }
 
 static void
 swfdec_image_pattern_class_init (SwfdecImagePatternClass *klass)
 {
-  SWFDEC_PATTERN_CLASS (klass)->paint = swfdec_image_pattern_paint;
+  SWFDEC_PATTERN_CLASS (klass)->get_pattern = swfdec_image_pattern_get_pattern;
 }
 
 static void
@@ -190,8 +187,8 @@ struct _SwfdecGradientPatternClass
 
 G_DEFINE_TYPE (SwfdecGradientPattern, swfdec_gradient_pattern, SWFDEC_TYPE_PATTERN);
 
-static void
-swfdec_gradient_pattern_paint (SwfdecPattern *pat, cairo_t *cr, const cairo_path_t *path,
+static cairo_pattern_t *
+swfdec_gradient_pattern_get_pattern (SwfdecPattern *pat, 
     const SwfdecColorTransform *trans, guint ratio)
 {
   guint i;
@@ -200,7 +197,6 @@ swfdec_gradient_pattern_paint (SwfdecPat
   double offset;
   SwfdecGradientPattern *gradient = SWFDEC_GRADIENT_PATTERN (pat);
 
-  cairo_append_path (cr, (cairo_path_t *) path);
 #if 0
   /* use this when https://bugs.freedesktop.org/show_bug.cgi?id=8341 is fixed */
   if (gradient->radial)
@@ -244,9 +240,7 @@ swfdec_gradient_pattern_paint (SwfdecPat
 	  SWFDEC_COLOR_B(color) / 255.0, SWFDEC_COLOR_A(color) / 255.0);
     }
   }
-  cairo_set_source (cr, pattern);
-  cairo_pattern_destroy (pattern);
-  cairo_fill (cr);
+  return pattern;
 }
 
 static void
@@ -265,7 +259,7 @@ swfdec_gradient_pattern_class_init (Swfd
 {
   G_OBJECT_CLASS (klass)->dispose = swfdec_gradient_pattern_dispose;
 
-  SWFDEC_PATTERN_CLASS (klass)->paint = swfdec_gradient_pattern_paint;
+  SWFDEC_PATTERN_CLASS (klass)->get_pattern = swfdec_gradient_pattern_get_pattern;
 }
 
 static void
@@ -458,7 +452,7 @@ void
 swfdec_pattern_paint (SwfdecPattern *pattern, cairo_t *cr, const cairo_path_t *path,
     const SwfdecColorTransform *trans, guint ratio)
 {
-  SwfdecPatternClass *klass;
+  cairo_pattern_t *cpattern;
 
   g_return_if_fail (SWFDEC_IS_PATTERN (pattern));
   g_return_if_fail (cr != NULL);
@@ -466,10 +460,13 @@ swfdec_pattern_paint (SwfdecPattern *pat
   g_return_if_fail (trans != NULL);
   g_return_if_fail (ratio < 65536);
 
-  klass = SWFDEC_PATTERN_GET_CLASS (pattern);
-  g_return_if_fail (klass->paint);
-
-  klass->paint (pattern, cr, path, trans, ratio);
+  cpattern = swfdec_pattern_get_pattern (pattern, trans, ratio);
+  if (cpattern == NULL)
+    return;
+  cairo_append_path (cr, path);
+  cairo_set_source (cr, cpattern);
+  cairo_pattern_destroy (cpattern);
+  cairo_fill (cr);
 }
 
 /**
@@ -613,3 +610,18 @@ swfdec_pattern_get_path_extents (SwfdecP
   }
 }
 
+cairo_pattern_t *
+swfdec_pattern_get_pattern (SwfdecPattern *pattern, 
+    const SwfdecColorTransform *trans, guint ratio)
+{
+  SwfdecPatternClass *klass;
+
+  g_return_val_if_fail (SWFDEC_IS_PATTERN (pattern), NULL);
+  g_return_val_if_fail (trans != NULL, NULL);
+  g_return_val_if_fail (ratio < 65536, NULL);
+
+  klass = SWFDEC_PATTERN_GET_CLASS (pattern);
+  g_assert (klass->get_pattern);
+  return klass->get_pattern (pattern, trans, ratio);
+}
+
diff --git a/libswfdec/swfdec_pattern.h b/libswfdec/swfdec_pattern.h
index 7ea97f5..6a0d2c7 100644
--- a/libswfdec/swfdec_pattern.h
+++ b/libswfdec/swfdec_pattern.h
@@ -49,11 +49,10 @@ struct _SwfdecPatternClass
 {
   GObjectClass		object_class;
 
-  void			(* paint)		(SwfdecPattern *		pattern, 
-					         cairo_t *			cr,
-						 const cairo_path_t *		path,
+  /* create a cairo pattern for the given values */
+  cairo_pattern_t *	(* get_pattern)		(SwfdecPattern *		pattern,
 						 const SwfdecColorTransform *	trans,
-						 guint			ratio);
+						 guint				ratio);
 };
 
 GType		swfdec_pattern_get_type		(void);
@@ -67,7 +66,10 @@ void		swfdec_pattern_paint		(SwfdecPatte
 						 cairo_t *			cr,
 						 const cairo_path_t *		path,
 						 const SwfdecColorTransform *	trans,
-						 guint			ratio);
+						 guint				ratio);
+cairo_pattern_t *swfdec_pattern_get_pattern	(SwfdecPattern *		pattern, 
+						 const SwfdecColorTransform *	trans,
+						 guint				ratio);
 void		swfdec_pattern_get_path_extents (SwfdecPattern *		pattern,
 						 const cairo_path_t *		path,
 						 SwfdecRect *			extents);
diff --git a/libswfdec/swfdec_shape.c b/libswfdec/swfdec_shape.c
index 65a5166..34e85a9 100644
--- a/libswfdec/swfdec_shape.c
+++ b/libswfdec/swfdec_shape.c
@@ -253,10 +253,15 @@ swfdec_shape_render (SwfdecGraphic *grap
     if (!fill && vec->last_index % 2 != 0) 
       continue;
 
-    if (fill)
-      swfdec_pattern_paint (vec->pattern, cr, &vec->path, trans, 0);
-    else
+    if (fill) {
+      if (SWFDEC_IS_PATTERN (vec->pattern)) {
+	swfdec_pattern_paint (vec->pattern, cr, &vec->path, trans, 0);
+      } else {
+	swfdec_stroke_paint (vec->pattern, cr, &vec->path, trans, 0);
+      }
+    } else {
       cairo_append_path (cr, &vec->path);
+    }
   }
 }
 
@@ -274,7 +279,7 @@ swfdec_shape_mouse_in (SwfdecGraphic *gr
     g_assert (shapevec->path.num_data);
     g_assert (shapevec->pattern);
     /* FIXME: handle strokes */
-    if (shapevec->last_index & 1)
+    if (SWFDEC_IS_STROKE (shapevec->pattern))
       continue;
     if (shapevec->fill_cr == NULL) {
       /* FIXME: do less memory intensive fill checking plz */
@@ -311,9 +316,10 @@ swfdec_shape_init (SwfdecShape * shape)
 }
 
 typedef SwfdecPattern * (* SwfdecPatternFunc) (SwfdecSwfDecoder * s);
+typedef SwfdecStroke * (* SwfdecStrokeFunc) (SwfdecSwfDecoder * s);
 static void
 swfdec_shape_add_styles (SwfdecSwfDecoder * s, SwfdecShape * shape,
-    SwfdecPatternFunc parse_fill, SwfdecPatternFunc parse_stroke)
+    SwfdecPatternFunc parse_fill, SwfdecStrokeFunc parse_stroke)
 {
   int n_fill_styles;
   int n_line_styles;
@@ -344,8 +350,7 @@ swfdec_shape_add_styles (SwfdecSwfDecode
   }
   SWFDEC_LOG ("   n_line_styles %d", n_line_styles);
   for (i = 0; i < n_line_styles; i++) {
-    SwfdecPattern *pattern = parse_stroke (s);
-    g_ptr_array_add (shape->lines, pattern);
+    g_ptr_array_add (shape->lines, parse_stroke (s));
   }
 
   swfdec_bits_syncbits (bits);
@@ -365,13 +370,13 @@ parse_rgba (SwfdecSwfDecoder * s)
   return swfdec_pattern_parse (s, TRUE);
 }
 
-static SwfdecPattern *
+static SwfdecStroke *
 parse_stroke_rgb (SwfdecSwfDecoder * s)
 {
   return swfdec_stroke_parse (s, FALSE);
 }
 
-static SwfdecPattern *
+static SwfdecStroke *
 parse_stroke_rgba (SwfdecSwfDecoder * s)
 {
   return swfdec_stroke_parse (s, TRUE);
@@ -430,6 +435,30 @@ tag_define_shape_2 (SwfdecSwfDecoder * s
   return tag_define_shape (s);
 }
 
+#if 0
+int
+tag_define_shape_4 (SwfdecSwfDecoder *s)
+{
+  SwfdecBits *bits = &s->b;
+  SwfdecShape *shape;
+  int id;
+
+  id = swfdec_bits_get_u16 (bits);
+  shape = swfdec_swf_decoder_create_character (s, id, SWFDEC_TYPE_SHAPE);
+  if (!shape)
+    return SWFDEC_STATUS_OK;
+  shape->rgba = 1;
+
+  swfdec_bits_get_rect (bits, &SWFDEC_GRAPHIC (shape)->extents);
+
+  swfdec_shape_add_styles (s, shape, parse_rgba, swfdec_stroke_parse_extended);
+
+  swfdec_shape_get_recs (s, shape);
+
+  return SWFDEC_STATUS_OK;
+}
+#endif
+
 /* The shape creation process is a bit complicated since it requires matching 
  * the Flash model to the cairo model. Note that this code is just random 
  * guessing and nothing substantial. Otherwise I'd have a testsuite. :)
@@ -709,7 +738,7 @@ swfdec_shape_parse_line (SwfdecBits *bit
 
 SubPath *
 swfdec_shape_parse_change (SwfdecSwfDecoder *s, SwfdecShape *shape, GArray *path_array, SubPath *path,
-    int *x, int *y, SwfdecPatternFunc parse_fill, SwfdecPatternFunc parse_stroke)
+    int *x, int *y, SwfdecPatternFunc parse_fill, SwfdecStrokeFunc parse_stroke)
 {
   int state_new_styles, state_line_styles, state_fill_styles1, state_fill_styles0, state_moveto;
   SwfdecBits *bits = &s->b;
diff --git a/libswfdec/swfdec_shape.h b/libswfdec/swfdec_shape.h
index cce6cf8..9ee709e 100644
--- a/libswfdec/swfdec_shape.h
+++ b/libswfdec/swfdec_shape.h
@@ -42,7 +42,7 @@ typedef struct _SwfdecShapeClass SwfdecS
 
 struct _SwfdecShapeVec
 {
-  SwfdecPattern *pattern;		/* pattern to display */
+  gpointer pattern;			/* pattern or stroke to display */
   cairo_path_t path;			/* accumulated path */
   SwfdecRect extents;			/* extents of path */
   guint last_index;			/* index of last segment that was added */
diff --git a/libswfdec/swfdec_stroke.c b/libswfdec/swfdec_stroke.c
index 7239479..30adef9 100644
--- a/libswfdec/swfdec_stroke.c
+++ b/libswfdec/swfdec_stroke.c
@@ -32,7 +32,7 @@
 
 #define MAX_ALIGN 10
 
-G_DEFINE_TYPE (SwfdecStroke, swfdec_stroke, SWFDEC_TYPE_PATTERN);
+G_DEFINE_TYPE (SwfdecStroke, swfdec_stroke, G_TYPE_OBJECT);
 
 static void
 swfdec_stroke_append_path_snapped (cairo_t *cr, const cairo_path_t *path)
@@ -92,13 +92,12 @@ swfdec_stroke_append_path_snapped (cairo
   }
 }
 
-static void
-swfdec_stroke_paint (SwfdecPattern *pattern, cairo_t *cr, const cairo_path_t *path,
+void
+swfdec_stroke_paint (SwfdecStroke *stroke, 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);
@@ -120,7 +119,6 @@ swfdec_stroke_paint (SwfdecPattern *patt
 static void
 swfdec_stroke_class_init (SwfdecStrokeClass *klass)
 {
-  SWFDEC_PATTERN_CLASS (klass)->paint = swfdec_stroke_paint;
 }
 
 static void
@@ -130,7 +128,7 @@ swfdec_stroke_init (SwfdecStroke *stroke
 
 /*** EXPORTED API ***/
 
-SwfdecPattern *
+SwfdecStroke *
 swfdec_stroke_parse (SwfdecSwfDecoder *dec, gboolean rgba)
 {
   SwfdecBits *bits = &dec->b;
@@ -146,10 +144,10 @@ swfdec_stroke_parse (SwfdecSwfDecoder *d
   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);
+  return stroke;
 }
 
-SwfdecPattern *
+SwfdecStroke *
 swfdec_stroke_parse_morph (SwfdecSwfDecoder *dec)
 {
   SwfdecBits *bits = &dec->b;
@@ -163,10 +161,10 @@ swfdec_stroke_parse_morph (SwfdecSwfDeco
       stroke->start_width, stroke->end_width,
       stroke->start_color, stroke->end_color);
 
-  return SWFDEC_PATTERN (stroke);
+  return stroke;
 }
 
-SwfdecPattern *
+SwfdecStroke *
 swfdec_stroke_new (guint width, SwfdecColor color)
 {
   SwfdecStroke *stroke = g_object_new (SWFDEC_TYPE_STROKE, NULL);
@@ -176,20 +174,20 @@ swfdec_stroke_new (guint width, SwfdecCo
   stroke->start_color = color;
   stroke->end_color = color;
 
-  return SWFDEC_PATTERN (stroke);
+  return stroke;
 }
 
-static SwfdecPattern *
+static SwfdecStroke *
 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);
+  return stroke;
 }
 
-SwfdecPattern *
+SwfdecStroke *
 swfdec_stroke_parse_extended (SwfdecSwfDecoder *dec, SwfdecPattern *fill_styles,
     guint n_fill_styles)
 {
@@ -199,7 +197,7 @@ swfdec_stroke_parse_extended (SwfdecSwfD
   return swfdec_stroke_do_parse_extended (&dec->b, FALSE, fill_styles, n_fill_styles);
 }
 
-SwfdecPattern *
+SwfdecStroke *
 swfdec_stroke_parse_morph_extended (SwfdecSwfDecoder *dec, SwfdecPattern *fill_styles,
     guint n_fill_styles)
 {
diff --git a/libswfdec/swfdec_stroke.h b/libswfdec/swfdec_stroke.h
index 51dbf07..37fd990 100644
--- a/libswfdec/swfdec_stroke.h
+++ b/libswfdec/swfdec_stroke.h
@@ -36,7 +36,7 @@ typedef struct _SwfdecStrokeClass Swfdec
 
 struct _SwfdecStroke
 {
-  SwfdecPattern		pattern;
+  GObject		object;
 
   guint			start_width;		/* width of line */
   SwfdecColor		start_color;		/* color to paint with */
@@ -46,20 +46,27 @@ struct _SwfdecStroke
 
 struct _SwfdecStrokeClass
 {
-  SwfdecPatternClass  	pattern_class;
+  GObjectClass		object_class;
 };
 
 GType		swfdec_stroke_get_type		(void);
 
-SwfdecPattern *	swfdec_stroke_new		(guint			width,
+SwfdecStroke *	swfdec_stroke_new		(guint			width,
 						 SwfdecColor		color);
-SwfdecPattern *	swfdec_stroke_parse		(SwfdecSwfDecoder *	dec,
+
+void		swfdec_stroke_paint		(SwfdecStroke *		stroke,
+						 cairo_t *		cr,
+						 const cairo_path_t *	path,
+						 const SwfdecColorTransform *trans,
+						 guint			ratio);
+
+SwfdecStroke *	swfdec_stroke_parse		(SwfdecSwfDecoder *	dec,
 						 gboolean		rgba);
-SwfdecPattern *	swfdec_stroke_parse_extended	(SwfdecSwfDecoder *	dec,
+SwfdecStroke *	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
+SwfdecStroke *	swfdec_stroke_parse_morph    	(SwfdecSwfDecoder *	dec);
+SwfdecStroke *	swfdec_stroke_parse_morph_extended
 						(SwfdecSwfDecoder *	dec,
 						 SwfdecPattern *	fill_styles,
 						 guint			n_fill_styles);
diff-tree 9a64282b9188bf335b9be029fd91e8a66ffddc8d (from 26ee7f5d85a1d809daa20b2f67cf4cb99420ed66)
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Apr 13 20:53:03 2007 +0200

    that function should be static

diff --git a/libswfdec/swfdec_codec_gst.c b/libswfdec/swfdec_codec_gst.c
index 64c335c..6c1ae37 100644
--- a/libswfdec/swfdec_codec_gst.c
+++ b/libswfdec/swfdec_codec_gst.c
@@ -176,7 +176,7 @@ swfdec_audio_decoder_gst_link (GstElemen
   }
 }
 
-GstBusSyncReply
+static GstBusSyncReply
 swfdec_audio_decoder_gst_handle_bus (GstBus *bus, GstMessage *message, gpointer data)
 {
   SwfdecGstAudio *player = data;


More information about the Swfdec mailing list