[Swfdec] 12 commits - libswfdec/Makefile.am libswfdec/swfdec_as_strings.c libswfdec/swfdec_as_types.c libswfdec/swfdec_as_types.h libswfdec/swfdec_gradient_pattern.c libswfdec/swfdec_gradient_pattern.h libswfdec/swfdec_movie_as_drawing.c libswfdec/swfdec_pattern.c test/image

Benjamin Otte company at kemper.freedesktop.org
Mon Dec 3 04:29:51 PST 2007


 libswfdec/Makefile.am                               |    2 
 libswfdec/swfdec_as_strings.c                       |   17 +
 libswfdec/swfdec_as_types.c                         |   16 +
 libswfdec/swfdec_as_types.h                         |    2 
 libswfdec/swfdec_gradient_pattern.c                 |  129 +++++++++++++++
 libswfdec/swfdec_gradient_pattern.h                 |   67 +++++++
 libswfdec/swfdec_movie_as_drawing.c                 |  172 +++++++++++++++++++-
 libswfdec/swfdec_pattern.c                          |  123 --------------
 test/image/Makefile.am                              |   23 ++
 test/image/empty-gradient.swf                       |binary
 test/image/empty-gradient.swf.png                   |binary
 test/image/empty-gradient.xml                       |   40 ++++
 test/image/gradient-beginGradientFill-5.swf         |binary
 test/image/gradient-beginGradientFill-5.swf.png     |binary
 test/image/gradient-beginGradientFill-6.swf         |binary
 test/image/gradient-beginGradientFill-6.swf.org.png |binary
 test/image/gradient-beginGradientFill-6.swf.png     |binary
 test/image/gradient-beginGradientFill-7.swf         |binary
 test/image/gradient-beginGradientFill-7.swf.org.png |binary
 test/image/gradient-beginGradientFill-7.swf.png     |binary
 test/image/gradient-beginGradientFill-8.swf         |binary
 test/image/gradient-beginGradientFill-8.swf.org.png |binary
 test/image/gradient-beginGradientFill-8.swf.png     |binary
 test/image/gradient-beginGradientFill.as            |   60 ++++++
 test/image/gradient-end-duplication.swf             |binary
 test/image/gradient-end-duplication.swf.org.png     |binary
 test/image/gradient-end-duplication.swf.png         |binary
 test/image/gradient-end-duplication.xml             |   59 ++++++
 test/image/gradient-ratios.swf                      |binary
 test/image/gradient-ratios.swf.org.png              |binary
 test/image/gradient-ratios.swf.png                  |binary
 test/image/gradient-ratios.xml                      |   54 ++++++
 32 files changed, 636 insertions(+), 128 deletions(-)

New commits:
commit b8e801500bc51e9f08433742a586cea8c6e66166
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Dec 3 13:15:03 2007 +0100

    add a gradient test

diff --git a/test/image/Makefile.am b/test/image/Makefile.am
index 5b870fb..1ae8261 100644
--- a/test/image/Makefile.am
+++ b/test/image/Makefile.am
@@ -73,6 +73,18 @@ EXTRA_DIST = \
 	fillstyle-order.swf \
 	fillstyle-order.swf.png \
 	fillstyle-order.xml \
+	gradient-beginGradientFill.as \
+	gradient-beginGradientFill-5.swf \
+	gradient-beginGradientFill-5.swf.png \
+	gradient-beginGradientFill-6.swf \
+	gradient-beginGradientFill-6.swf.png \
+	gradient-beginGradientFill-6.swf.org.png \
+	gradient-beginGradientFill-7.swf \
+	gradient-beginGradientFill-7.swf.png \
+	gradient-beginGradientFill-7.swf.org.png \
+	gradient-beginGradientFill-8.swf \
+	gradient-beginGradientFill-8.swf.org.png \
+	gradient-beginGradientFill-8.swf.png \
 	gradient-end-duplication.swf \
 	gradient-end-duplication.swf.png \
 	gradient-end-duplication.swf.org.png \
diff --git a/test/image/gradient-beginGradientFill-5.swf b/test/image/gradient-beginGradientFill-5.swf
new file mode 100644
index 0000000..756d2ef
Binary files /dev/null and b/test/image/gradient-beginGradientFill-5.swf differ
diff --git a/test/image/gradient-beginGradientFill-5.swf.png b/test/image/gradient-beginGradientFill-5.swf.png
new file mode 100644
index 0000000..9120be2
Binary files /dev/null and b/test/image/gradient-beginGradientFill-5.swf.png differ
diff --git a/test/image/gradient-beginGradientFill-6.swf b/test/image/gradient-beginGradientFill-6.swf
new file mode 100644
index 0000000..2bbb2b4
Binary files /dev/null and b/test/image/gradient-beginGradientFill-6.swf differ
diff --git a/test/image/gradient-beginGradientFill-6.swf.org.png b/test/image/gradient-beginGradientFill-6.swf.org.png
new file mode 100644
index 0000000..922e154
Binary files /dev/null and b/test/image/gradient-beginGradientFill-6.swf.org.png differ
diff --git a/test/image/gradient-beginGradientFill-6.swf.png b/test/image/gradient-beginGradientFill-6.swf.png
new file mode 100644
index 0000000..338d94a
Binary files /dev/null and b/test/image/gradient-beginGradientFill-6.swf.png differ
diff --git a/test/image/gradient-beginGradientFill-7.swf b/test/image/gradient-beginGradientFill-7.swf
new file mode 100644
index 0000000..07aa3d7
Binary files /dev/null and b/test/image/gradient-beginGradientFill-7.swf differ
diff --git a/test/image/gradient-beginGradientFill-7.swf.org.png b/test/image/gradient-beginGradientFill-7.swf.org.png
new file mode 100644
index 0000000..1ff6bdb
Binary files /dev/null and b/test/image/gradient-beginGradientFill-7.swf.org.png differ
diff --git a/test/image/gradient-beginGradientFill-7.swf.png b/test/image/gradient-beginGradientFill-7.swf.png
new file mode 100644
index 0000000..338d94a
Binary files /dev/null and b/test/image/gradient-beginGradientFill-7.swf.png differ
diff --git a/test/image/gradient-beginGradientFill-8.swf b/test/image/gradient-beginGradientFill-8.swf
new file mode 100644
index 0000000..89d4623
Binary files /dev/null and b/test/image/gradient-beginGradientFill-8.swf differ
diff --git a/test/image/gradient-beginGradientFill-8.swf.org.png b/test/image/gradient-beginGradientFill-8.swf.org.png
new file mode 100644
index 0000000..427323e
Binary files /dev/null and b/test/image/gradient-beginGradientFill-8.swf.org.png differ
diff --git a/test/image/gradient-beginGradientFill-8.swf.png b/test/image/gradient-beginGradientFill-8.swf.png
new file mode 100644
index 0000000..338d94a
Binary files /dev/null and b/test/image/gradient-beginGradientFill-8.swf.png differ
diff --git a/test/image/gradient-beginGradientFill.as b/test/image/gradient-beginGradientFill.as
new file mode 100644
index 0000000..a30717e
--- /dev/null
+++ b/test/image/gradient-beginGradientFill.as
@@ -0,0 +1,60 @@
+// makeswf -v 7 -s 200x150 -r 1 -o gradient-beginGradientFill.swf gradient-beginGradientFill.as
+
+x = 0;
+y = 0;
+
+function do_gradient (type, colors, alphas, ratios) {
+  var matrix = { a:0, b:-80, d:80, e:0, g: x * 100 + 50, h: y * 100 + 50 };
+  beginGradientFill (type, colors, alphas, ratios, matrix);
+  moveTo (x * 100 + 10, y * 100 + 10);
+  lineTo (x * 100 + 10, y * 100 + 90);
+  lineTo (x * 100 + 90, y * 100 + 90);
+  lineTo (x * 100 + 90, y * 100 + 10);
+  lineTo (x * 100 + 10, y * 100 + 10);
+  endFill ();
+  x++;
+  if (x > 3) {
+    x = 0;
+    y++;
+  }
+};
+
+// 1
+foo = function (o, s) {
+  if (!o.x)
+    o.x = 7;
+  else
+    o.x--;
+  trace (s + " valueof: " + o.x); 
+  return o.x;
+};
+c = { };
+c.length = { valueOf: function () { return foo (this, "color"); } };
+c[0] = c[2] = c[4] = c[6] = c[8] = 0xFF;
+c[1] = c[3] = c[5] = c[7] = c[9] = 0xFF00;
+a = { };
+a.length = { valueOf: function () { return foo (this, "alpha"); } };
+a[0] = a[2] = a[4] = a[6] = a[8] = 100;
+a[1] = a[3] = a[5] = a[7] = a[9] = 50;
+r = { };
+r.length = { valueOf: function () { return foo (this, "ratios"); } };
+for (i = 0; i < 10; i++)
+  r[i] = i / 9 * 255;
+do_gradient ("linear", c, a, r);
+
+// 2 - 4
+o = { };
+o.length = { valueOf: function () { trace ("length valueOf"); return 3; } };
+do_gradient ("linear", [0x40, 0xFF0000, 0xFF00], o, [0, 127, 255]);
+do_gradient ("linear", [0xFF, 0xFF0000, 0xFF00], [100, 100, 100], o);
+do_gradient ("linear", o, [100, 50, 100], [0, 127, 255]);
+
+// 5 - 12
+do_gradient ("Radial", [0xFF, 0xFF0000, 0xFF00], [255, 255, 255], [0, 127, 255]);
+do_gradient ("linear", ["255", {valueOf: function () { return 0xFF0000; }}, 0xFF00], [255, 255, 255], [0, 127, 255]);
+do_gradient ("linear", [ 0xFF, 0xFF00 ], [ undefined, 127 ], [ 0, 255 ]);
+do_gradient ("linear", [ ], [ ], [ ]);
+do_gradient ("linear", [ 0xFF ], [ 100 ], [ -1 ]);
+do_gradient ("linear", [ undefined ], [ 100 ], [ 255.8 ]);
+do_gradient ("linear", [ 0xFF ], [ 100 ], [ 256 ]);
+do_gradient ("radial", [0xFF, 0xFF0000, 0xFF00], [50, 100, 255], [undefined, 127, 255]);
commit dee7205ccdfdc5bbc514dc3b1de7313565c62222
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Dec 3 13:13:20 2007 +0100

    implement beginGradientFill
    
    It's not perfect, but good enough.
    Most notably is missing support for matrices constructed with new flash.geom.Matrix()
    and the Flash 8 parameters.

diff --git a/libswfdec/swfdec_as_strings.c b/libswfdec/swfdec_as_strings.c
index 7f0aeba..89896ce 100644
--- a/libswfdec/swfdec_as_strings.c
+++ b/libswfdec/swfdec_as_strings.c
@@ -466,5 +466,22 @@ const char swfdec_as_strings[] =
   SWFDEC_AS_CONSTANT_STRING ("hardlight")
   SWFDEC_AS_CONSTANT_STRING ("getTextExtent")
   SWFDEC_AS_CONSTANT_STRING ("domain")
+  SWFDEC_AS_CONSTANT_STRING ("linear")
+  SWFDEC_AS_CONSTANT_STRING ("radial")
+  SWFDEC_AS_CONSTANT_STRING ("matrixType")
+  SWFDEC_AS_CONSTANT_STRING ("box")
+  SWFDEC_AS_CONSTANT_STRING ("a")
+  SWFDEC_AS_CONSTANT_STRING ("b")
+  SWFDEC_AS_CONSTANT_STRING ("c")
+  SWFDEC_AS_CONSTANT_STRING ("d")
+  SWFDEC_AS_CONSTANT_STRING ("e")
+  SWFDEC_AS_CONSTANT_STRING ("f")
+  SWFDEC_AS_CONSTANT_STRING ("g")
+  SWFDEC_AS_CONSTANT_STRING ("h")
+  SWFDEC_AS_CONSTANT_STRING ("i")
+  SWFDEC_AS_CONSTANT_STRING ("r")
+  SWFDEC_AS_CONSTANT_STRING ("w")
+  SWFDEC_AS_CONSTANT_STRING ("x")
+  SWFDEC_AS_CONSTANT_STRING ("y")
   /* add more here */
 ;
diff --git a/libswfdec/swfdec_movie_as_drawing.c b/libswfdec/swfdec_movie_as_drawing.c
index b528fbd..f11810f 100644
--- a/libswfdec/swfdec_movie_as_drawing.c
+++ b/libswfdec/swfdec_movie_as_drawing.c
@@ -22,9 +22,11 @@
 #endif
 
 #include "swfdec_movie.h"
+#include "swfdec_as_internal.h"
+#include "swfdec_as_strings.h"
 #include "swfdec_color.h"
 #include "swfdec_debug.h"
-#include "swfdec_as_internal.h"
+#include "swfdec_gradient_pattern.h"
 #include "swfdec_path.h"
 #include "swfdec_pattern.h"
 #include "swfdec_stroke.h"
@@ -69,6 +71,9 @@ swfdec_sprite_movie_end_fill (SwfdecMovie *movie, SwfdecDraw *new)
   }
 }
 
+#define SWFDEC_COLOR_FROM_COLOR_ALPHA(color, alpha) \
+  (((color) & 0xFFFFFF) | SWFDEC_COLOR_COMBINE (0, 0, 0, CLAMP ((alpha), 0, 100) * 255 / 100))
+
 SWFDEC_AS_NATIVE (901, 1, swfdec_sprite_movie_beginFill)
 void
 swfdec_sprite_movie_beginFill (SwfdecAsContext *cx, SwfdecAsObject *object,
@@ -84,24 +89,175 @@ swfdec_sprite_movie_beginFill (SwfdecAsContext *cx, SwfdecAsObject *object,
   if (argc == 0)
     return;
   color = color & 0xFFFFFF;
-  if (argc > 1) {
-    alpha = CLAMP (alpha, 0, 100);
-    alpha = SWFDEC_COLOR_COMBINE (0, 0, 0, alpha * 255 / 100);
-  } else {
-    alpha = SWFDEC_COLOR_COMBINE (0, 0, 0, 255);
+  if (argc <= 1) {
+    alpha = 255;
   }
-  color = color | alpha;
+  color = SWFDEC_COLOR_FROM_COLOR_ALPHA (color, alpha);
   draw = SWFDEC_DRAW (swfdec_pattern_new_color (color));
   swfdec_path_move_to (&draw->path, movie->draw_x, movie->draw_y);
   swfdec_sprite_movie_end_fill (movie, draw);
 }
 
+static inline guint
+swfdec_sprite_movie_gradient_fill_get_length (SwfdecAsObject *o)
+{
+  int length;
+  SwfdecAsValue val;
+
+  swfdec_as_object_get_variable (o, SWFDEC_AS_STR_length, &val);
+  length = swfdec_as_value_to_integer (o->context, &val);
+  return MAX (length, 0);
+}
+
+static int
+swfdec_sprite_movie_gradient_fill_check_length (SwfdecAsObject *colors, SwfdecAsObject *alphas, SwfdecAsObject *ratios)
+{
+  guint c, a, r;
+
+  c = swfdec_sprite_movie_gradient_fill_get_length (colors);
+  a = swfdec_sprite_movie_gradient_fill_get_length (alphas);
+  r = swfdec_sprite_movie_gradient_fill_get_length (ratios);
+  if (c != a || a != r)
+    return -1;
+  return c;
+}
+
+static void
+swfdec_sprite_movie_extract_matrix (SwfdecAsObject *o, cairo_matrix_t *mat)
+{
+  SwfdecAsContext *cx = o->context;
+  SwfdecAsValue val;
+
+  /* FIXME: This function does not call valueOf in the right order */
+  if (swfdec_as_object_get_variable (o, SWFDEC_AS_STR_matrixType, &val)) {
+    const char *s = swfdec_as_value_to_string (cx, &val);
+    cairo_matrix_init_translate (mat, SWFDEC_TWIPS_SCALE_FACTOR / 2.0, SWFDEC_TWIPS_SCALE_FACTOR / 2.0);
+    cairo_matrix_scale (mat, SWFDEC_TWIPS_SCALE_FACTOR / 32768.0, SWFDEC_TWIPS_SCALE_FACTOR / 32768.0);
+    if (s == SWFDEC_AS_STR_box) {
+      double x, y, w, h, r;
+      cairo_matrix_t input;
+      swfdec_as_object_get_variable (o, SWFDEC_AS_STR_x, &val);
+      x = swfdec_as_value_to_number (cx, &val);
+      swfdec_as_object_get_variable (o, SWFDEC_AS_STR_y, &val);
+      y = swfdec_as_value_to_number (cx, &val);
+      swfdec_as_object_get_variable (o, SWFDEC_AS_STR_w, &val);
+      w = swfdec_as_value_to_number (cx, &val);
+      swfdec_as_object_get_variable (o, SWFDEC_AS_STR_h, &val);
+      h = swfdec_as_value_to_number (cx, &val);
+      swfdec_as_object_get_variable (o, SWFDEC_AS_STR_r, &val);
+      r = swfdec_as_value_to_number (cx, &val);
+      cairo_matrix_init_translate (&input, (x + w) / 2, (y + h) / 2);
+      cairo_matrix_scale (&input, w, h);
+      cairo_matrix_rotate (&input, r);
+      cairo_matrix_multiply (mat, mat, &input);
+    } else {
+      SWFDEC_WARNING ("my friend, there's no other matrixType than \"box\"");
+    }
+  } else {
+    cairo_matrix_t input;
+    swfdec_as_object_get_variable (o, SWFDEC_AS_STR_a, &val);
+    input.xx = swfdec_as_value_to_number (cx, &val);
+    swfdec_as_object_get_variable (o, SWFDEC_AS_STR_b, &val);
+    input.yx = swfdec_as_value_to_number (cx, &val);
+    swfdec_as_object_get_variable (o, SWFDEC_AS_STR_d, &val);
+    input.xy = swfdec_as_value_to_number (cx, &val);
+    swfdec_as_object_get_variable (o, SWFDEC_AS_STR_e, &val);
+    input.yy = swfdec_as_value_to_number (cx, &val);
+    swfdec_as_object_get_variable (o, SWFDEC_AS_STR_g, &val);
+    input.x0 = swfdec_as_value_to_number (cx, &val) * SWFDEC_TWIPS_SCALE_FACTOR;
+    swfdec_as_object_get_variable (o, SWFDEC_AS_STR_h, &val);
+    input.y0 = swfdec_as_value_to_number (cx, &val) * SWFDEC_TWIPS_SCALE_FACTOR;
+    cairo_matrix_init_scale (mat, SWFDEC_TWIPS_SCALE_FACTOR / 32768.0, SWFDEC_TWIPS_SCALE_FACTOR / 32768.0);
+    cairo_matrix_multiply (mat, mat, &input);
+  }
+}
+
 SWFDEC_AS_NATIVE (901, 2, swfdec_sprite_movie_beginGradientFill)
 void
 swfdec_sprite_movie_beginGradientFill (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
 {
-  SWFDEC_FIXME ("implement");
+  SwfdecGradientPattern *gradient;
+  SwfdecPattern *pattern;
+  SwfdecMovie *movie;
+  SwfdecDraw *draw;
+  SwfdecAsObject *colors, *alphas, *ratios, *matrix;
+  const char *s;
+  gboolean radial;
+  int i, len;
+
+  SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE, &movie, "|sOOOO", &s, &colors, &alphas, &ratios, &matrix);
+  movie->draw_fill = NULL;
+  
+  if (colors == NULL || alphas == NULL || ratios == NULL || matrix == NULL) {
+    SWFDEC_ERROR ("could not convert one of the parameters to an object");
+    return;
+  }
+  if (s == SWFDEC_AS_STR_linear) {
+    radial = FALSE;
+  } else if (s == SWFDEC_AS_STR_radial) {
+    radial = TRUE;
+  } else {
+    SWFDEC_WARNING ("invalid fill type %s", s);
+    return;
+  }
+  len = swfdec_sprite_movie_gradient_fill_check_length (colors, alphas, ratios);
+  if (len < 0) {
+    SWFDEC_ERROR ("different lengths for colors, alphas and ratios, aborting");
+    return;
+  }
+  draw = swfdec_gradient_pattern_new ();
+  pattern = SWFDEC_PATTERN (draw);
+  gradient = SWFDEC_GRADIENT_PATTERN (draw);
+  gradient->radial = radial;
+  len = MIN (len, 8);
+  gradient->n_gradients = len;
+  for (i = 0; i < len; i++) {
+    int c, a, r;
+    SwfdecAsValue v;
+    int check = swfdec_sprite_movie_gradient_fill_check_length (colors, alphas, ratios);
+    if (check > i) {
+      const char *name = swfdec_as_integer_to_string (cx, i);
+      if (swfdec_as_object_get_variable (colors, name, &v)
+	  && SWFDEC_AS_VALUE_IS_NUMBER (&v))
+	c = swfdec_as_value_to_integer (cx, &v);
+      else
+	c = 0;
+      if (!swfdec_as_object_get_variable (alphas, name, &v)) {
+	a = c;
+      } else if (!SWFDEC_AS_VALUE_IS_NUMBER (&v)) {
+	a = 0;
+      } else {
+	a = swfdec_as_value_to_integer (cx, &v);
+      }
+      if (!swfdec_as_object_get_variable (ratios, name, &v))
+	r = CLAMP (a, 0, 255);
+      else if (!SWFDEC_AS_VALUE_IS_NUMBER (&v))
+	r = 0;
+      else
+	r = swfdec_as_value_to_integer (cx, &v);
+    } else {
+      c = a = r = 0;
+    }
+    if (r > 255 || r < 0) {
+      SWFDEC_WARNING ("ratio %d not in [0, 255], ignoring gradient", r);
+      g_object_unref (draw);
+      return;
+    } else if (r < 0) {
+      r = 0;
+    }
+    gradient->gradient[i].color = SWFDEC_COLOR_FROM_COLOR_ALPHA (c, a);
+    gradient->gradient[i].ratio = r;
+  }
+  swfdec_sprite_movie_extract_matrix (matrix, &pattern->start_transform);
+  pattern->transform = pattern->start_transform;
+  if (cairo_matrix_invert (&pattern->transform)) {
+    SWFDEC_ERROR ("gradient transform matrix not invertible, resetting");
+    cairo_matrix_init_identity (&pattern->transform);
+  }
+
+  swfdec_path_move_to (&draw->path, movie->draw_x, movie->draw_y);
+  swfdec_sprite_movie_end_fill (movie, draw);
 }
 
 SWFDEC_AS_NATIVE (901, 3, swfdec_sprite_movie_moveTo)
commit d005031cfccf975ca0d98ee0a6dae83964edbd36
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Dec 3 12:37:42 2007 +0100

    add swfdec_as_integer_to_string()

diff --git a/libswfdec/swfdec_as_types.c b/libswfdec/swfdec_as_types.c
index 34cbbc5..d4bbfb9 100644
--- a/libswfdec/swfdec_as_types.c
+++ b/libswfdec/swfdec_as_types.c
@@ -216,6 +216,22 @@ swfdec_as_str_concat (SwfdecAsContext *cx, const char * s1, const char *s2)
 /**
  * swfdec_as_double_to_string:
  * @context: a #SwfdecAsContext
+ * @i: an integer that fits into 32 bits
+ *
+ * Converts @d into a string using the same conversion algorithm as the 
+ * official Flash player.
+ *
+ * Returns: a garbage-collected string
+ **/
+const char *
+swfdec_as_integer_to_string (SwfdecAsContext *context, int i)
+{
+  return swfdec_as_context_give_string (context, g_strdup_printf ("%d", i));
+}
+
+/**
+ * swfdec_as_double_to_string:
+ * @context: a #SwfdecAsContext
  * @d: a double
  *
  * Converts @d into a string using the same conversion algorithm as the 
diff --git a/libswfdec/swfdec_as_types.h b/libswfdec/swfdec_as_types.h
index 3501fac..e90174d 100644
--- a/libswfdec/swfdec_as_types.h
+++ b/libswfdec/swfdec_as_types.h
@@ -125,6 +125,8 @@ const char *	swfdec_as_value_to_string	(SwfdecAsContext *	context,
 char *		swfdec_as_value_to_debug	(const SwfdecAsValue *	value);
 
 /* special conversion functions */
+const char *	swfdec_as_integer_to_string	(SwfdecAsContext *      context,
+						 int			i);
 const char *	swfdec_as_double_to_string	(SwfdecAsContext *	context,
 						 double			d);
 const char *	swfdec_as_str_concat		(SwfdecAsContext *	cx,
commit 472aa34b00d9a7643de4c42eefae7cffecba094e
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Dec 3 12:37:17 2007 +0100

    add another test for gradients
    
    And this one too, doesn't work 100% perfect

diff --git a/test/image/Makefile.am b/test/image/Makefile.am
index bc9c292..5b870fb 100644
--- a/test/image/Makefile.am
+++ b/test/image/Makefile.am
@@ -73,6 +73,10 @@ EXTRA_DIST = \
 	fillstyle-order.swf \
 	fillstyle-order.swf.png \
 	fillstyle-order.xml \
+	gradient-end-duplication.swf \
+	gradient-end-duplication.swf.png \
+	gradient-end-duplication.swf.org.png \
+	gradient-end-duplication.xml \
 	gradient-ratios.swf \
 	gradient-ratios.swf.png \
 	gradient-ratios.swf.org.png \
diff --git a/test/image/gradient-end-duplication.swf b/test/image/gradient-end-duplication.swf
new file mode 100644
index 0000000..bb0cb1d
Binary files /dev/null and b/test/image/gradient-end-duplication.swf differ
diff --git a/test/image/gradient-end-duplication.swf.org.png b/test/image/gradient-end-duplication.swf.org.png
new file mode 100644
index 0000000..afcf1f8
Binary files /dev/null and b/test/image/gradient-end-duplication.swf.org.png differ
diff --git a/test/image/gradient-end-duplication.swf.png b/test/image/gradient-end-duplication.swf.png
new file mode 100644
index 0000000..fcf6a3b
Binary files /dev/null and b/test/image/gradient-end-duplication.swf.png differ
diff --git a/test/image/gradient-end-duplication.xml b/test/image/gradient-end-duplication.xml
new file mode 100644
index 0000000..7eeb9ee
--- /dev/null
+++ b/test/image/gradient-end-duplication.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0"?>
+<swf version="7" compressed="1">
+  <Header framerate="30" frames="1">
+    <size>
+      <Rectangle left="0" right="6120" top="0" bottom="3000"/>
+    </size>
+    <tags>
+      <DefineShape2 objectID="1">
+        <bounds>
+          <Rectangle left="500" right="5620" top="500" bottom="2500"/>
+        </bounds>
+        <styles>
+          <StyleList>
+            <fillStyles>
+	      <LinearGradient spreadMode="1" interpolationMode="0">
+		<matrix>
+		  <Transform scaleX="0.05625" scaleY="1" skewX="0" skewY="0" transX="3060" transY="1500"/>
+		</matrix>
+		<gradientColors>
+		  <GradientItem position="254">
+		    <color>
+		      <Color red="255" green="0" blue="0" alpha="255"/>
+		    </color>
+		  </GradientItem>
+		  <GradientItem position="0">
+		    <color>
+		      <Color red="0" green="0" blue="255" alpha="255"/>
+		    </color>
+		  </GradientItem>
+		  <GradientItem position="0">
+		    <color>
+		      <Color red="0" green="255" blue="0" alpha="255"/>
+		    </color>
+		  </GradientItem>
+		</gradientColors>
+	      </LinearGradient>
+            </fillStyles>
+	    <lineStyles />
+          </StyleList>
+        </styles>
+        <shapes>
+          <Shape>
+            <edges>
+              <ShapeSetup x="500" y="500" fillStyle0="1"/>
+              <LineTo x="0" y="2000"/>
+              <LineTo x="5120" y="0"/>
+              <LineTo x="0" y="-2000"/>
+	      <LineTo x="-5120" y="0"/>
+              <ShapeSetup/>
+            </edges>
+          </Shape>
+        </shapes>
+      </DefineShape2>
+      <PlaceObject2 replace="0" depth="0" objectID="1" />
+      <ShowFrame/>
+      <End/>
+    </tags>
+  </Header>
+</swf>
commit 1c94cb756031ebcd939f82120469b56911866a38
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Dec 3 12:35:49 2007 +0100

    update reference image to work with Swfdec for now

diff --git a/test/image/Makefile.am b/test/image/Makefile.am
index e7b60f0..bc9c292 100644
--- a/test/image/Makefile.am
+++ b/test/image/Makefile.am
@@ -75,6 +75,7 @@ EXTRA_DIST = \
 	fillstyle-order.xml \
 	gradient-ratios.swf \
 	gradient-ratios.swf.png \
+	gradient-ratios.swf.org.png \
 	gradient-ratios.xml \
 	image-jpeg-alpha.swf \
 	image-jpeg-alpha.swf.png \
diff --git a/test/image/gradient-ratios.swf.org.png b/test/image/gradient-ratios.swf.org.png
new file mode 100644
index 0000000..76c1bcc
Binary files /dev/null and b/test/image/gradient-ratios.swf.org.png differ
diff --git a/test/image/gradient-ratios.swf.png b/test/image/gradient-ratios.swf.png
index 76c1bcc..cb3c43f 100644
Binary files a/test/image/gradient-ratios.swf.png and b/test/image/gradient-ratios.swf.png differ
commit a04781850be00b7fa87d974d888c60c8dd763526
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Dec 3 12:27:50 2007 +0100

    ratios must be increasing - if they're not, we force them to be

diff --git a/libswfdec/swfdec_gradient_pattern.c b/libswfdec/swfdec_gradient_pattern.c
index ca5f8c4..2f63634 100644
--- a/libswfdec/swfdec_gradient_pattern.c
+++ b/libswfdec/swfdec_gradient_pattern.c
@@ -56,7 +56,7 @@ swfdec_gradient_pattern_morph (SwfdecDraw *dest, SwfdecDraw *source, guint ratio
 static cairo_pattern_t *
 swfdec_gradient_pattern_get_pattern (SwfdecPattern *pat, const SwfdecColorTransform *trans)
 {
-  guint i;
+  guint i, ratio;
   cairo_pattern_t *pattern;
   SwfdecColor color;
   double offset;
@@ -89,13 +89,20 @@ swfdec_gradient_pattern_get_pattern (SwfdecPattern *pat, const SwfdecColorTransf
   }
 #endif
   cairo_pattern_set_extend (pattern, gradient->extend);
+  /* we check here that ratios increase linearly, because both gradients parsed 
+   * from the SWF and gradients created with beginGradientFill have this 
+   * behavior */
+  ratio = 0;
   for (i = 0; i < gradient->n_gradients; i++){
     color = swfdec_color_apply_transform (gradient->gradient[i].color,
 	trans);
-    offset = gradient->gradient[i].ratio / 255.0;
+    ratio = MAX (ratio, gradient->gradient[i].ratio);
+    offset = ratio / 255.0;
     cairo_pattern_add_color_stop_rgba (pattern, offset,
 	SWFDEC_COLOR_R(color) / 255.0, SWFDEC_COLOR_G(color) / 255.0,
 	SWFDEC_COLOR_B(color) / 255.0, SWFDEC_COLOR_A(color) / 255.0);
+    if (++ratio > 255)
+      break;
   }
   return pattern;
 }
commit fbcffb9baba0ab49f24886787f8ace22131fa0e5
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Dec 3 11:46:56 2007 +0100

    add a test that ensures non-increasing gradient ratios work

diff --git a/test/image/Makefile.am b/test/image/Makefile.am
index bf08ce2..e7b60f0 100644
--- a/test/image/Makefile.am
+++ b/test/image/Makefile.am
@@ -73,6 +73,9 @@ EXTRA_DIST = \
 	fillstyle-order.swf \
 	fillstyle-order.swf.png \
 	fillstyle-order.xml \
+	gradient-ratios.swf \
+	gradient-ratios.swf.png \
+	gradient-ratios.xml \
 	image-jpeg-alpha.swf \
 	image-jpeg-alpha.swf.png \
 	image-lossless-alpha.swf \
diff --git a/test/image/gradient-ratios.swf b/test/image/gradient-ratios.swf
new file mode 100644
index 0000000..8248060
Binary files /dev/null and b/test/image/gradient-ratios.swf differ
diff --git a/test/image/gradient-ratios.swf.png b/test/image/gradient-ratios.swf.png
new file mode 100644
index 0000000..76c1bcc
Binary files /dev/null and b/test/image/gradient-ratios.swf.png differ
diff --git a/test/image/gradient-ratios.xml b/test/image/gradient-ratios.xml
new file mode 100644
index 0000000..5e2c6ec
--- /dev/null
+++ b/test/image/gradient-ratios.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0"?>
+<swf version="7" compressed="1">
+  <Header framerate="30" frames="1">
+    <size>
+      <Rectangle left="0" right="4000" top="0" bottom="3000"/>
+    </size>
+    <tags>
+      <DefineShape2 objectID="1">
+        <bounds>
+          <Rectangle left="500" right="3500" top="500" bottom="2500"/>
+        </bounds>
+        <styles>
+          <StyleList>
+            <fillStyles>
+	      <LinearGradient spreadMode="1" interpolationMode="0">
+		<matrix>
+		  <Transform scaleX="0.091552734" scaleY="1" skewX="0" skewY="0" transX="2000" transY="1500"/>
+		</matrix>
+		<gradientColors>
+		  <GradientItem position="127">
+		    <color>
+		      <Color red="255" green="0" blue="0" alpha="255"/>
+		    </color>
+		  </GradientItem>
+		  <GradientItem position="0">
+		    <color>
+		      <Color red="0" green="255" blue="0" alpha="255"/>
+		    </color>
+		  </GradientItem>
+		</gradientColors>
+	      </LinearGradient>
+            </fillStyles>
+	    <lineStyles />
+          </StyleList>
+        </styles>
+        <shapes>
+          <Shape>
+            <edges>
+              <ShapeSetup x="500" y="500" fillStyle0="1"/>
+              <LineTo x="0" y="2000"/>
+              <LineTo x="3000" y="0"/>
+              <LineTo x="0" y="-2000"/>
+	      <LineTo x="-3000" y="0"/>
+              <ShapeSetup/>
+            </edges>
+          </Shape>
+        </shapes>
+      </DefineShape2>
+      <PlaceObject2 replace="0" depth="0" objectID="1" />
+      <ShowFrame/>
+      <End/>
+    </tags>
+  </Header>
+</swf>
commit b4966ebfcb734200030b8db95a07274c9fb60354
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Dec 3 11:36:21 2007 +0100

    empty gradients are solid black

diff --git a/libswfdec/swfdec_gradient_pattern.c b/libswfdec/swfdec_gradient_pattern.c
index ed206cc..ca5f8c4 100644
--- a/libswfdec/swfdec_gradient_pattern.c
+++ b/libswfdec/swfdec_gradient_pattern.c
@@ -62,6 +62,10 @@ swfdec_gradient_pattern_get_pattern (SwfdecPattern *pat, const SwfdecColorTransf
   double offset;
   SwfdecGradientPattern *gradient = SWFDEC_GRADIENT_PATTERN (pat);
 
+  if (gradient->n_gradients == 0) {
+    /* cairo interprets an empty gradient as translucent, not as solid black */
+    return cairo_pattern_create_rgb (0, 0, 0);
+  }
 #if 0
   /* use this when https://bugs.freedesktop.org/show_bug.cgi?id=8341 is fixed */
   if (gradient->radial)
commit da2103799165cc57165a2ef9fa486eff330f3d79
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Dec 3 11:35:50 2007 +0100

    gradients (like images) pad by default

diff --git a/libswfdec/swfdec_gradient_pattern.c b/libswfdec/swfdec_gradient_pattern.c
index b87fc1a..ed206cc 100644
--- a/libswfdec/swfdec_gradient_pattern.c
+++ b/libswfdec/swfdec_gradient_pattern.c
@@ -105,8 +105,9 @@ swfdec_gradient_pattern_class_init (SwfdecGradientPatternClass *klass)
 }
 
 static void
-swfdec_gradient_pattern_init (SwfdecGradientPattern *pattern)
+swfdec_gradient_pattern_init (SwfdecGradientPattern *gradient)
 {
+  gradient->extend = CAIRO_EXTEND_PAD;
 }
 
 SwfdecDraw *
commit 9660a4b24a464585adc7f228bb5e058d0463e6a5
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Dec 2 15:29:49 2007 +0100

    add test for empty gradients

diff --git a/test/image/Makefile.am b/test/image/Makefile.am
index 9993ebc..bf08ce2 100644
--- a/test/image/Makefile.am
+++ b/test/image/Makefile.am
@@ -67,6 +67,9 @@ EXTRA_DIST = \
 	drawing-zorder-8.swf \
 	drawing-zorder-8.swf.org.png \
 	drawing-zorder-8.swf.png \
+	empty-gradient.swf \
+	empty-gradient.swf.png \
+	empty-gradient.xml \
 	fillstyle-order.swf \
 	fillstyle-order.swf.png \
 	fillstyle-order.xml \
diff --git a/test/image/empty-gradient.swf b/test/image/empty-gradient.swf
new file mode 100644
index 0000000..8aa5404
Binary files /dev/null and b/test/image/empty-gradient.swf differ
diff --git a/test/image/empty-gradient.swf.png b/test/image/empty-gradient.swf.png
new file mode 100644
index 0000000..08d2512
Binary files /dev/null and b/test/image/empty-gradient.swf.png differ
diff --git a/test/image/empty-gradient.xml b/test/image/empty-gradient.xml
new file mode 100644
index 0000000..7bf74ce
--- /dev/null
+++ b/test/image/empty-gradient.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<swf version="7" compressed="1">
+  <Header framerate="30" frames="1">
+    <size>
+      <Rectangle left="0" right="4000" top="0" bottom="3000"/>
+    </size>
+    <tags>
+      <DefineShape2 objectID="1">
+        <bounds>
+          <Rectangle left="500" right="3500" top="500" bottom="2500"/>
+        </bounds>
+        <styles>
+          <StyleList>
+            <fillStyles>
+	      <LinearGradient spreadMode="1" interpolationMode="0">
+		<gradientColors/>
+	      </LinearGradient>
+            </fillStyles>
+	    <lineStyles />
+          </StyleList>
+        </styles>
+        <shapes>
+          <Shape>
+            <edges>
+              <ShapeSetup x="500" y="500" fillStyle0="1"/>
+              <LineTo x="0" y="2000"/>
+              <LineTo x="3000" y="0"/>
+              <LineTo x="0" y="-2000"/>
+	      <LineTo x="-3000" y="0"/>
+              <ShapeSetup/>
+            </edges>
+          </Shape>
+        </shapes>
+      </DefineShape2>
+      <PlaceObject2 replace="0" depth="0" objectID="1" />
+      <ShowFrame/>
+      <End/>
+    </tags>
+  </Header>
+</swf>
commit ecd4f9072a0d8e778b44b26f70491eb5cddf6a0e
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Dec 2 15:25:57 2007 +0100

    add swfdec_gradient_pattern_new()

diff --git a/libswfdec/swfdec_gradient_pattern.c b/libswfdec/swfdec_gradient_pattern.c
index d8d9738..b87fc1a 100644
--- a/libswfdec/swfdec_gradient_pattern.c
+++ b/libswfdec/swfdec_gradient_pattern.c
@@ -108,3 +108,10 @@ static void
 swfdec_gradient_pattern_init (SwfdecGradientPattern *pattern)
 {
 }
+
+SwfdecDraw *
+swfdec_gradient_pattern_new (void)
+{
+  return g_object_new (SWFDEC_TYPE_GRADIENT_PATTERN, NULL);
+}
+
diff --git a/libswfdec/swfdec_gradient_pattern.h b/libswfdec/swfdec_gradient_pattern.h
index b845104..6b85608 100644
--- a/libswfdec/swfdec_gradient_pattern.h
+++ b/libswfdec/swfdec_gradient_pattern.h
@@ -60,6 +60,8 @@ struct _SwfdecGradientPatternClass
 
 GType		swfdec_gradient_pattern_get_type	(void);
 
+SwfdecDraw *	swfdec_gradient_pattern_new		(void);
+							 
 
 G_END_DECLS
 #endif
diff --git a/libswfdec/swfdec_pattern.c b/libswfdec/swfdec_pattern.c
index 49db137..d641556 100644
--- a/libswfdec/swfdec_pattern.c
+++ b/libswfdec/swfdec_pattern.c
@@ -262,7 +262,7 @@ swfdec_pattern_do_parse (SwfdecBits *bits, SwfdecSwfDecoder *dec, gboolean rgba)
   } else if (paint_style_type == 0x10 || paint_style_type == 0x12 || paint_style_type == 0x13) {
     SwfdecGradientPattern *gradient;
     guint i, interpolation;
-    pattern = g_object_new (SWFDEC_TYPE_GRADIENT_PATTERN, NULL);
+    pattern = SWFDEC_PATTERN (swfdec_gradient_pattern_new ());
     gradient = SWFDEC_GRADIENT_PATTERN (pattern);
     swfdec_bits_get_matrix (bits, &pattern->start_transform, NULL);
     pattern->end_transform = pattern->start_transform;
@@ -409,7 +409,7 @@ swfdec_pattern_parse_morph (SwfdecBits *bits, SwfdecSwfDecoder *dec)
   } else if (paint_style_type == 0x10 || paint_style_type == 0x12 || paint_style_type == 0x13) {
     SwfdecGradientPattern *gradient;
     guint i, interpolation;
-    pattern = g_object_new (SWFDEC_TYPE_GRADIENT_PATTERN, NULL);
+    pattern = SWFDEC_PATTERN (swfdec_gradient_pattern_new ());
     gradient = SWFDEC_GRADIENT_PATTERN (pattern);
     swfdec_bits_get_matrix (bits, &pattern->start_transform, NULL);
     swfdec_bits_get_matrix (bits, &pattern->end_transform, NULL);
commit f98b8cd67045b92bd7ee79aa12d99a7b8c8669cf
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Dec 2 15:17:58 2007 +0100

    split out graident pattern code into its own file
    
    This is to ease implementation of beginGradientFill

diff --git a/libswfdec/Makefile.am b/libswfdec/Makefile.am
index 6c42eb0..aad0e05 100644
--- a/libswfdec/Makefile.am
+++ b/libswfdec/Makefile.am
@@ -89,6 +89,7 @@ libswfdec_ at SWFDEC_MAJORMINOR@_la_SOURCES = \
 	swfdec_font.c \
 	swfdec_glow_filter.c \
 	swfdec_gradient_filter.c \
+	swfdec_gradient_pattern.c \
 	swfdec_graphic.c \
 	swfdec_graphic_movie.c \
 	swfdec_image.c \
@@ -231,6 +232,7 @@ noinst_HEADERS = \
 	swfdec_flash_security.h \
 	swfdec_flv_decoder.h \
 	swfdec_font.h \
+	swfdec_gradient_pattern.h \
 	swfdec_graphic.h \
 	swfdec_graphic_movie.h \
 	swfdec_image.h \
diff --git a/libswfdec/swfdec_gradient_pattern.c b/libswfdec/swfdec_gradient_pattern.c
new file mode 100644
index 0000000..d8d9738
--- /dev/null
+++ b/libswfdec/swfdec_gradient_pattern.c
@@ -0,0 +1,110 @@
+/* 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_gradient_pattern.h"
+#include "swfdec_color.h"
+#include "swfdec_debug.h"
+#include "swfdec_path.h"
+
+G_DEFINE_TYPE (SwfdecGradientPattern, swfdec_gradient_pattern, SWFDEC_TYPE_PATTERN);
+
+static void
+swfdec_gradient_pattern_morph (SwfdecDraw *dest, SwfdecDraw *source, guint ratio)
+{
+  guint i;
+
+  SwfdecGradientPattern *dpattern = SWFDEC_GRADIENT_PATTERN (dest);
+  SwfdecGradientPattern *spattern = SWFDEC_GRADIENT_PATTERN (source);
+
+  g_return_if_fail (spattern->end_gradient != NULL);
+  dpattern->radial = spattern->radial;
+  dpattern->focus = spattern->focus;
+  dpattern->extend = spattern->extend;
+  dpattern->n_gradients = spattern->n_gradients;
+  for (i = 0; i < spattern->n_gradients; i++) {
+    dpattern->gradient[i].color = swfdec_color_apply_morph (spattern->gradient[i].color,
+	spattern->end_gradient[i].color, ratio);
+    dpattern->gradient[i].ratio = (spattern->gradient[i].ratio * (65535 - ratio) +
+	spattern->end_gradient[i].ratio * ratio) / 65535;
+  }
+
+  SWFDEC_DRAW_CLASS (swfdec_gradient_pattern_parent_class)->morph (dest, source, ratio);
+}
+
+static cairo_pattern_t *
+swfdec_gradient_pattern_get_pattern (SwfdecPattern *pat, const SwfdecColorTransform *trans)
+{
+  guint i;
+  cairo_pattern_t *pattern;
+  SwfdecColor color;
+  double offset;
+  SwfdecGradientPattern *gradient = SWFDEC_GRADIENT_PATTERN (pat);
+
+#if 0
+  /* use this when https://bugs.freedesktop.org/show_bug.cgi?id=8341 is fixed */
+  if (gradient->radial)
+    pattern = cairo_pattern_create_radial (0, 0, 0, 0, 0, 16384);
+  else
+    pattern = cairo_pattern_create_linear (-16384.0, 0, 16384.0, 0);
+  cairo_pattern_set_matrix (pattern, &pat->transform);
+#else
+  {
+    cairo_matrix_t mat = pat->transform;
+    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;
+    cairo_pattern_set_matrix (pattern, &mat);
+  }
+#endif
+  cairo_pattern_set_extend (pattern, gradient->extend);
+  for (i = 0; i < gradient->n_gradients; i++){
+    color = swfdec_color_apply_transform (gradient->gradient[i].color,
+	trans);
+    offset = gradient->gradient[i].ratio / 255.0;
+    cairo_pattern_add_color_stop_rgba (pattern, offset,
+	SWFDEC_COLOR_R(color) / 255.0, SWFDEC_COLOR_G(color) / 255.0,
+	SWFDEC_COLOR_B(color) / 255.0, SWFDEC_COLOR_A(color) / 255.0);
+  }
+  return pattern;
+}
+
+static void
+swfdec_gradient_pattern_class_init (SwfdecGradientPatternClass *klass)
+{
+  SWFDEC_DRAW_CLASS (klass)->morph = swfdec_gradient_pattern_morph;
+
+  SWFDEC_PATTERN_CLASS (klass)->get_pattern = swfdec_gradient_pattern_get_pattern;
+}
+
+static void
+swfdec_gradient_pattern_init (SwfdecGradientPattern *pattern)
+{
+}
diff --git a/libswfdec/swfdec_gradient_pattern.h b/libswfdec/swfdec_gradient_pattern.h
new file mode 100644
index 0000000..b845104
--- /dev/null
+++ b/libswfdec/swfdec_gradient_pattern.h
@@ -0,0 +1,65 @@
+/* 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_GRADIENT_PATTERN_H_
+#define _SWFDEC_GRADIENT_PATTERN_H_
+
+#include <libswfdec/swfdec_pattern.h>
+
+G_BEGIN_DECLS
+
+typedef struct _SwfdecGradientPattern SwfdecGradientPattern;
+typedef struct _SwfdecGradientPatternClass SwfdecGradientPatternClass;
+
+typedef struct _SwfdecGradientEntry SwfdecGradientEntry;
+
+#define SWFDEC_TYPE_GRADIENT_PATTERN                    (swfdec_gradient_pattern_get_type())
+#define SWFDEC_IS_GRADIENT_PATTERN(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_GRADIENT_PATTERN))
+#define SWFDEC_IS_GRADIENT_PATTERN_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_GRADIENT_PATTERN))
+#define SWFDEC_GRADIENT_PATTERN(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_GRADIENT_PATTERN, SwfdecGradientPattern))
+#define SWFDEC_GRADIENT_PATTERN_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_GRADIENT_PATTERN, SwfdecGradientPatternClass))
+#define SWFDEC_GRADIENT_PATTERN_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_GRADIENT_PATTERN, SwfdecGradientPatternClass))
+
+struct _SwfdecGradientEntry {
+  guint ratio;
+  SwfdecColor color;
+};
+
+struct _SwfdecGradientPattern
+{
+  SwfdecPattern		pattern;
+
+  SwfdecGradientEntry	gradient[16];		/* gradient to paint */
+  SwfdecGradientEntry	end_gradient[16];     	/* end gradient for morphs */
+  guint			n_gradients;		/* number of gradients */
+  cairo_extend_t	extend;			/* extend of gradient */
+  gboolean		radial;			/* TRUE for radial gradient, FALSE for linear gradient */
+  double		focus;			/* focus point */
+};
+
+struct _SwfdecGradientPatternClass
+{
+  SwfdecPatternClass	pattern_class;
+};
+
+GType		swfdec_gradient_pattern_get_type	(void);
+
+
+G_END_DECLS
+#endif
diff --git a/libswfdec/swfdec_pattern.c b/libswfdec/swfdec_pattern.c
index d5aaaaa..49db137 100644
--- a/libswfdec/swfdec_pattern.c
+++ b/libswfdec/swfdec_pattern.c
@@ -28,6 +28,7 @@
 #include "swfdec_color.h"
 #include "swfdec_debug.h"
 #include "swfdec_decoder.h"
+#include "swfdec_gradient_pattern.h"
 #include "swfdec_image.h"
 #include "swfdec_path.h"
 #include "swfdec_stroke.h"
@@ -238,124 +239,6 @@ swfdec_image_pattern_init (SwfdecImagePattern *pattern)
 {
 }
 
-/*** GRADIENT PATTERN ***/
-
-typedef struct _SwfdecGradientPattern SwfdecGradientPattern;
-typedef struct _SwfdecGradientPatternClass SwfdecGradientPatternClass;
-
-typedef struct _SwfdecGradientEntry SwfdecGradientEntry;
-
-#define SWFDEC_TYPE_GRADIENT_PATTERN                    (swfdec_gradient_pattern_get_type())
-#define SWFDEC_IS_GRADIENT_PATTERN(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_GRADIENT_PATTERN))
-#define SWFDEC_IS_GRADIENT_PATTERN_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_GRADIENT_PATTERN))
-#define SWFDEC_GRADIENT_PATTERN(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_GRADIENT_PATTERN, SwfdecGradientPattern))
-#define SWFDEC_GRADIENT_PATTERN_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_GRADIENT_PATTERN, SwfdecGradientPatternClass))
-#define SWFDEC_GRADIENT_PATTERN_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_GRADIENT_PATTERN, SwfdecGradientPatternClass))
-
-struct _SwfdecGradientEntry {
-  guint ratio;
-  SwfdecColor color;
-};
-
-struct _SwfdecGradientPattern
-{
-  SwfdecPattern		pattern;
-
-  SwfdecGradientEntry	gradient[16];		/* gradient to paint */
-  SwfdecGradientEntry	end_gradient[16];     	/* end gradient for morphs */
-  guint			n_gradients;		/* number of gradients */
-  cairo_extend_t	extend;			/* extend of gradient */
-  gboolean		radial;			/* TRUE for radial gradient, FALSE for linear gradient */
-  double		focus;			/* focus point */
-};
-
-struct _SwfdecGradientPatternClass
-{
-  SwfdecPatternClass	pattern_class;
-};
-
-GType swfdec_gradient_pattern_get_type (void);
-G_DEFINE_TYPE (SwfdecGradientPattern, swfdec_gradient_pattern, SWFDEC_TYPE_PATTERN);
-
-static void
-swfdec_gradient_pattern_morph (SwfdecDraw *dest, SwfdecDraw *source, guint ratio)
-{
-  guint i;
-
-  SwfdecGradientPattern *dpattern = SWFDEC_GRADIENT_PATTERN (dest);
-  SwfdecGradientPattern *spattern = SWFDEC_GRADIENT_PATTERN (source);
-
-  g_return_if_fail (spattern->end_gradient != NULL);
-  dpattern->radial = spattern->radial;
-  dpattern->focus = spattern->focus;
-  dpattern->extend = spattern->extend;
-  dpattern->n_gradients = spattern->n_gradients;
-  for (i = 0; i < spattern->n_gradients; i++) {
-    dpattern->gradient[i].color = swfdec_color_apply_morph (spattern->gradient[i].color,
-	spattern->end_gradient[i].color, ratio);
-    dpattern->gradient[i].ratio = (spattern->gradient[i].ratio * (65535 - ratio) +
-	spattern->end_gradient[i].ratio * ratio) / 65535;
-  }
-
-  SWFDEC_DRAW_CLASS (swfdec_gradient_pattern_parent_class)->morph (dest, source, ratio);
-}
-
-static cairo_pattern_t *
-swfdec_gradient_pattern_get_pattern (SwfdecPattern *pat, const SwfdecColorTransform *trans)
-{
-  guint i;
-  cairo_pattern_t *pattern;
-  SwfdecColor color;
-  double offset;
-  SwfdecGradientPattern *gradient = SWFDEC_GRADIENT_PATTERN (pat);
-
-#if 0
-  /* use this when https://bugs.freedesktop.org/show_bug.cgi?id=8341 is fixed */
-  if (gradient->radial)
-    pattern = cairo_pattern_create_radial (0, 0, 0, 0, 0, 16384);
-  else
-    pattern = cairo_pattern_create_linear (-16384.0, 0, 16384.0, 0);
-  cairo_pattern_set_matrix (pattern, &pat->transform);
-#else
-  {
-    cairo_matrix_t mat = pat->transform;
-    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;
-    cairo_pattern_set_matrix (pattern, &mat);
-  }
-#endif
-  cairo_pattern_set_extend (pattern, gradient->extend);
-  for (i = 0; i < gradient->n_gradients; i++){
-    color = swfdec_color_apply_transform (gradient->gradient[i].color,
-	trans);
-    offset = gradient->gradient[i].ratio / 255.0;
-    cairo_pattern_add_color_stop_rgba (pattern, offset,
-	SWFDEC_COLOR_R(color) / 255.0, SWFDEC_COLOR_G(color) / 255.0,
-	SWFDEC_COLOR_B(color) / 255.0, SWFDEC_COLOR_A(color) / 255.0);
-  }
-  return pattern;
-}
-
-static void
-swfdec_gradient_pattern_class_init (SwfdecGradientPatternClass *klass)
-{
-  SWFDEC_DRAW_CLASS (klass)->morph = swfdec_gradient_pattern_morph;
-
-  SWFDEC_PATTERN_CLASS (klass)->get_pattern = swfdec_gradient_pattern_get_pattern;
-}
-
-static void
-swfdec_gradient_pattern_init (SwfdecGradientPattern *pattern)
-{
-}
-
 /*** EXPORTED API ***/
 
 static SwfdecDraw *


More information about the Swfdec mailing list