[cairo-commit] goocanvas/src goocanvasitem.c, 1.17, 1.18 goocanvasitem.h, 1.12, 1.13 goocanvasitemmodel.c, 1.7, 1.8 goocanvasitemmodel.h, 1.6, 1.7

Damon Chaplin commit at pdx.freedesktop.org
Tue Feb 13 04:32:50 PST 2007


Committed by: damon

Update of /cvs/cairo/goocanvas/src
In directory kemper:/tmp/cvs-serv18111/src

Modified Files:
	goocanvasitem.c goocanvasitem.h goocanvasitemmodel.c 
	goocanvasitemmodel.h 
Log Message:
2007-02-13  Damon Chaplin  <damon at gnome.org>

	* src/goocanvasitemmodel.c (goo_canvas_item_model_animate): 
	* src/goocanvasitem.c (goo_canvas_item_animate): added "absolute"
	parameter, and rewrote the animation code, using the same code for
	GooCanvasItem and GooCanvasItemModel.

	* demo/demo-animation.c: 
	* demo/mv-demo-animation.c: new files for animation demo pages.

	* demo/mv-demo.c: 
	* demo/demo.c: added new animation pages and updated animation calls.



Index: goocanvasitem.c
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvasitem.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- goocanvasitem.c	12 Feb 2007 14:23:50 -0000	1.17
+++ goocanvasitem.c	13 Feb 2007 12:32:44 -0000	1.18
@@ -1030,8 +1030,12 @@
 {
   GooCanvasAnimateType type;
   GooCanvasItem *item;
-  int num_steps_left, total_steps;
-  cairo_matrix_t start, step;
+  GooCanvasItemModel *model;
+  int step, total_steps;
+  cairo_matrix_t start;
+  gdouble x_start, y_start, scale_start, radians_start;
+  gdouble x_step, y_step, scale_step, radians_step;
+  gboolean absolute;
   gboolean forward;
   guint timeout_id;
 };
@@ -1054,33 +1058,29 @@
 goo_canvas_item_animate_cb (GooCanvasItemAnimation *anim)
 {
   GooCanvasItemIface *iface;
-  cairo_matrix_t *matrix, new_matrix = { 1, 0, 0, 1, 0, 0 };
+  GooCanvasItemModelIface *model_iface;
+  cairo_matrix_t new_matrix;
   gboolean keep_source = TRUE;
+  gdouble scale;
+  gint step;
 
   GDK_THREADS_ENTER ();
 
-  iface = GOO_CANVAS_ITEM_GET_IFACE (anim->item);
-  matrix = iface->get_transform (anim->item);
-  if (matrix)
-    new_matrix = *matrix;
-
-  new_matrix.xx += anim->step.xx;
-  new_matrix.yx += anim->step.yx;
-  new_matrix.xy += anim->step.xy;
-  new_matrix.yy += anim->step.yy;
-  new_matrix.x0 += anim->step.x0;
-  new_matrix.y0 += anim->step.y0;
-
-  iface->set_transform (anim->item, &new_matrix);
+  if (anim->model)
+    model_iface = GOO_CANVAS_ITEM_MODEL_GET_IFACE (anim->model);
+  else
+    iface = GOO_CANVAS_ITEM_GET_IFACE (anim->item);
 
-  if (--anim->num_steps_left == 0)
+  if (++anim->step > anim->total_steps)
     {
       switch (anim->type)
 	{
 	case GOO_CANVAS_ANIMATE_RESET:
 	  /* Reset the transform to the initial value. */
-	  /* FIXME: Need to wait one cycle at finish position? */
-	  iface->set_transform (anim->item, &anim->start);
+	  if (anim->model)
+	    model_iface->set_transform (anim->model, &anim->start);
+	  else
+	    iface->set_transform (anim->item, &anim->start);
 
 	  /* Fall through.. */
 	case GOO_CANVAS_ANIMATE_FREEZE:
@@ -1088,31 +1088,52 @@
 	  anim->timeout_id = 0;
 	  /* This will result in a call to goo_canvas_item_free_animation()
 	     above. We've set the timeout_id to 0 so it isn't removed twice. */
-	  g_object_set_data (G_OBJECT (anim->item), animation_key, NULL);
+	  if (anim->model)
+	    g_object_set_data (G_OBJECT (anim->model), animation_key, NULL);
+	  else
+	    g_object_set_data (G_OBJECT (anim->item), animation_key, NULL);
 	  break;
 
 	case GOO_CANVAS_ANIMATE_RESTART:
-	  iface->set_transform (anim->item, &anim->start);
+	  anim->step = 0;
 	  break;
 
 	case GOO_CANVAS_ANIMATE_BOUNCE:
-	  /* Switch all the step values around. */
-	  anim->step.xx = -anim->step.xx;
-	  anim->step.yx = -anim->step.yx;
-	  anim->step.xy = -anim->step.xy;
-	  anim->step.yy = -anim->step.yy;
-	  anim->step.x0 = -anim->step.x0;
-	  anim->step.y0 = -anim->step.y0;
-
-	  /* FIXME: don't need this? Might be wise to reset to the initial
-	     transform each time we restart, to avoid little errors. */
 	  anim->forward = !anim->forward;
+	  anim->step = 1;
 	  break;
 	}
+    }
 
-      anim->num_steps_left = anim->total_steps;
+  step = anim->forward ? anim->step : anim->total_steps - anim->step;
+
+  if (anim->absolute)
+    {
+      cairo_matrix_init_identity (&new_matrix);
+      scale = anim->scale_start + anim->scale_step * step;
+      cairo_matrix_translate (&new_matrix,
+			      anim->x_start + anim->x_step * step,
+			      anim->y_start + anim->y_step * step);
+      cairo_matrix_scale (&new_matrix, scale, scale);
+      cairo_matrix_rotate (&new_matrix,
+			   anim->radians_start + anim->radians_step * step);
+    }
+  else
+    {
+      new_matrix = anim->start;
+      scale = 1 + anim->scale_step * step;
+      cairo_matrix_translate (&new_matrix, anim->x_step * step,
+			      anim->y_step * step);
+      cairo_matrix_scale (&new_matrix, scale, scale);
+      cairo_matrix_rotate (&new_matrix, anim->radians_step * step);
     }
 
+  if (anim->model)
+    model_iface->set_transform (anim->model, &new_matrix);
+  else
+    iface->set_transform (anim->item, &new_matrix);
+
+
   GDK_THREADS_LEAVE ();
 
   /* Return FALSE to remove the timeout handler when we are finished. */
@@ -1120,6 +1141,90 @@
 }
 
 
+void
+_goo_canvas_item_animate_internal (GooCanvasItem       *item,
+				   GooCanvasItemModel  *model,
+				   gdouble              x,
+				   gdouble              y,
+				   gdouble              scale,
+				   gdouble              degrees,
+				   gboolean             absolute,
+				   gint                 duration,
+				   gint                 step_time,
+				   GooCanvasAnimateType type)
+{
+  GObject *object;
+  cairo_matrix_t *matrix;
+  GooCanvasItemAnimation *anim;
+
+  if (item)
+    {
+      GooCanvasItemIface *iface = GOO_CANVAS_ITEM_GET_IFACE (item);
+      matrix = iface->get_transform (item);
+      object = (GObject*) item;
+    }
+  else
+    {
+      GooCanvasItemModelIface *iface = GOO_CANVAS_ITEM_MODEL_GET_IFACE (model);
+      matrix = iface->get_transform (model);
+      object = (GObject*) model;
+    }
+
+  anim = g_new (GooCanvasItemAnimation, 1);
+  anim->type = type;
+  anim->item = item;
+  anim->model = model;
+  anim->step = 0;
+  anim->total_steps = duration / step_time;
+  if (matrix)
+    anim->start = *matrix;
+  else
+    cairo_matrix_init_identity (&anim->start);
+  anim->absolute = absolute;
+  anim->forward = TRUE;
+
+  /* For absolute animation we have to try to calculate the current position,
+     scale and rotation. */
+  if (absolute)
+    {
+      cairo_matrix_t tmp_matrix = anim->start;
+      double x1 = 1.0, y1 = 0.0;
+
+      anim->x_start = tmp_matrix.x0;
+      anim->y_start = tmp_matrix.y0;
+
+      tmp_matrix.x0 = 0.0;
+      tmp_matrix.y0 = 0.0;
+
+      cairo_matrix_transform_point (&tmp_matrix, &x1, &y1);
+      anim->scale_start = sqrt (x1 * x1 + y1 * y1);
+      anim->radians_start = atan2 (y1, x1);
+
+      anim->x_step = (x - anim->x_start) / anim->total_steps;
+      anim->y_step = (y - anim->y_start) / anim->total_steps;
+      anim->scale_step = (scale - anim->scale_start) / anim->total_steps;
+      anim->radians_step = (degrees * (M_PI / 180) - anim->radians_start) / anim->total_steps;
+    }
+  else
+    {
+      anim->x_step = x / anim->total_steps;
+      anim->y_step = y / anim->total_steps;
+      anim->scale_step = (scale - 1.0) / anim->total_steps;
+      anim->radians_step = (degrees * (M_PI / 180)) / anim->total_steps;
+    }
+
+
+  /* Store a pointer to the new animation in the item. This will automatically
+     stop any current animation and free it. */
+  g_object_set_data_full (object, animation_key, anim,
+			  (GDestroyNotify) goo_canvas_item_free_animation);
+
+  anim->timeout_id = g_timeout_add (step_time,
+				    (GSourceFunc) goo_canvas_item_animate_cb,
+				    anim);
+}
+
+
 /**
  * goo_canvas_item_animate:
  * @item: an item.
@@ -1127,6 +1232,7 @@
  * @y: the final y offset from the current position.
  * @scale: the final scale of the item.
  * @degrees: the final rotation of the item.
+ * @absolute: if the values are absolute or relative to the current transform.
  * @duration: the duration of the animation, in milliseconds (1/1000ths of a
  *  second).
  * @step_time: the time between each animation step, in milliseconds.
@@ -1141,45 +1247,13 @@
 				gdouble        y,
 				gdouble        scale,
 				gdouble        degrees,
+				gboolean       absolute,
 				gint           duration,
 				gint           step_time,
 				GooCanvasAnimateType type)
 {
-  GooCanvasItemIface *iface = GOO_CANVAS_ITEM_GET_IFACE (item);
-  cairo_matrix_t *matrix, identity_matrix = { 1, 0, 0, 1, 0, 0 };
-  cairo_matrix_t new_matrix = { 1, 0, 0, 1, 0, 0 };
-  GooCanvasItemAnimation *anim;
-  double radians = degrees * (M_PI / 180);
-
-  matrix = iface->get_transform (item);
-  if (!matrix)
-    matrix = &identity_matrix;
-
-  cairo_matrix_translate (&new_matrix, x, y);
-  cairo_matrix_scale (&new_matrix, scale, scale);
-  cairo_matrix_rotate (&new_matrix, radians);
-
-  anim = g_new (GooCanvasItemAnimation, 1);
-  anim->type = type;
-  anim->item = item;
-  anim->total_steps = anim->num_steps_left = duration / step_time;
-  anim->start = *matrix;
-  anim->step.xx = (new_matrix.xx - matrix->xx) / anim->total_steps; 
-  anim->step.yx = (new_matrix.yx - matrix->yx) / anim->total_steps; 
-  anim->step.xy = (new_matrix.xy - matrix->xy) / anim->total_steps; 
-  anim->step.yy = (new_matrix.yy - matrix->yy) / anim->total_steps; 
-  anim->step.x0 = (new_matrix.x0 - matrix->x0) / anim->total_steps; 
-  anim->step.y0 = (new_matrix.y0 - matrix->y0) / anim->total_steps; 
-  anim->forward = TRUE;
-
-  /* Store a pointer to the new animation in the item. This will automatically
-     stop any current animation and free it. */
-  g_object_set_data_full (G_OBJECT (item), animation_key, anim,
-			  (GDestroyNotify) goo_canvas_item_free_animation);
-
-  anim->timeout_id = g_timeout_add (step_time,
-				    (GSourceFunc) goo_canvas_item_animate_cb,
-				    anim);
+  _goo_canvas_item_animate_internal (item, NULL, x, y, scale, degrees,
+				     absolute, duration, step_time, type);
 }
 
 

Index: goocanvasitem.h
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvasitem.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- goocanvasitem.h	9 Feb 2007 13:41:03 -0000	1.12
+++ goocanvasitem.h	13 Feb 2007 12:32:44 -0000	1.13
@@ -362,6 +362,7 @@
 						   gdouble           y,
 						   gdouble           scale,
 						   gdouble           degrees,
+						   gboolean          absolute,
 						   gint             duration,
 						   gint             step_time,
 						   GooCanvasAnimateType type);

Index: goocanvasitemmodel.c
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvasitemmodel.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- goocanvasitemmodel.c	12 Feb 2007 14:27:33 -0000	1.7
+++ goocanvasitemmodel.c	13 Feb 2007 12:32:44 -0000	1.8
@@ -28,7 +28,7 @@
 
 static GParamSpecPool       *_goo_canvas_item_model_child_property_pool = NULL;
 static GObjectNotifyContext *_goo_canvas_item_model_child_property_notify_context = NULL;
-static const char *animation_key = "GooCanvasItemModelAnimation";
+static const char *animation_key = "GooCanvasItemAnimation";
 
 enum {
   CHILD_ADDED,
@@ -752,100 +752,16 @@
 }
 
 
-typedef struct _GooCanvasItemModelAnimation  GooCanvasItemModelAnimation;
-struct _GooCanvasItemModelAnimation
-{
-  GooCanvasAnimateType type;
-  GooCanvasItemModel *model;
-  int num_steps_left, total_steps;
-  cairo_matrix_t start, step;
-  gboolean forward;
-  guint timeout_id;
-};
-
-
-static void
-goo_canvas_item_model_free_animation (GooCanvasItemModelAnimation *anim)
-{
-  if (anim->timeout_id)
-    {
-      g_source_remove (anim->timeout_id);
-      anim->timeout_id = 0;
-    }
-
-  g_free (anim);
-}
-
-
-static gboolean
-goo_canvas_item_model_animate_cb (GooCanvasItemModelAnimation *anim)
-{
-  GooCanvasItemModelIface *iface;
-  cairo_matrix_t *matrix, new_matrix = { 1, 0, 0, 1, 0, 0 };
-  gboolean keep_source = TRUE;
-
-  GDK_THREADS_ENTER ();
-
-  iface = GOO_CANVAS_ITEM_MODEL_GET_IFACE (anim->model);
-  matrix = iface->get_transform (anim->model);
-  if (matrix)
-    new_matrix = *matrix;
-
-  new_matrix.xx += anim->step.xx;
-  new_matrix.yx += anim->step.yx;
-  new_matrix.xy += anim->step.xy;
-  new_matrix.yy += anim->step.yy;
-  new_matrix.x0 += anim->step.x0;
-  new_matrix.y0 += anim->step.y0;
-
-  iface->set_transform (anim->model, &new_matrix);
-
-  if (--anim->num_steps_left == 0)
-    {
-      switch (anim->type)
-	{
-	case GOO_CANVAS_ANIMATE_RESET:
-	  /* Reset the transform to the initial value. */
-	  /* FIXME: Need to wait one cycle at finish position? */
-	  iface->set_transform (anim->model, &anim->start);
-
-	  /* Fall through.. */
-	case GOO_CANVAS_ANIMATE_FREEZE:
-	  keep_source = FALSE;
-	  anim->timeout_id = 0;
-	  /* This will result in call to goo_canvas_item_model_free_animation()
-	     above. We've set the timeout_id to 0 so it isn't removed twice. */
-	  g_object_set_data (G_OBJECT (anim->model), animation_key, NULL);
-	  break;
-
-	case GOO_CANVAS_ANIMATE_RESTART:
-	  iface->set_transform (anim->model, &anim->start);
-	  break;
-
-	case GOO_CANVAS_ANIMATE_BOUNCE:
-	  /* Switch all the step values around. */
-	  anim->step.xx = -anim->step.xx;
-	  anim->step.yx = -anim->step.yx;
-	  anim->step.xy = -anim->step.xy;
-	  anim->step.yy = -anim->step.yy;
-	  anim->step.x0 = -anim->step.x0;
-	  anim->step.y0 = -anim->step.y0;
-
-	  /* FIXME: don't need this? Might be wise to reset to the initial
-	     transform each time we restart, to avoid little errors. */
-	  anim->forward = !anim->forward;
-	  break;
-	}
-
-      anim->num_steps_left = anim->total_steps;
-    }
-
-  GDK_THREADS_LEAVE ();
-
-  /* Return FALSE to remove the timeout handler when we are finished. */
-  return keep_source;
-}
-
+extern void _goo_canvas_item_animate_internal (GooCanvasItem       *item,
+					       GooCanvasItemModel  *model,
+					       gdouble              x,
+					       gdouble              y,
+					       gdouble              scale,
+					       gdouble              degrees,
+					       gboolean             absolute,
+					       gint                 duration,
+					       gint                 step_time,
+					       GooCanvasAnimateType type);
 
 /**
  * goo_canvas_item_model_animate:
@@ -854,6 +770,10 @@
  * @y: the final y offset from the current position.
  * @scale: the final scale of the model.
  * @degrees: the final rotation of the model.
+ * @absolute: if the @x, @y, @scale and @degrees values are absolute, or
+ *  relative to the current transform. Note that absolute animations only work
+ *  if the model currently has a simple transform. If the model has a shear or
+ *  some other complicated transform it may result in strange animations.
  * @duration: the duration of the animation, in milliseconds (1/1000ths of a
  *  second).
  * @step_time: the time between each animation step, in milliseconds.
@@ -868,45 +788,13 @@
 				      gdouble              y,
 				      gdouble              scale,
 				      gdouble              degrees,
+				      gboolean             absolute,
 				      gint                 duration,
 				      gint                 step_time,
 				      GooCanvasAnimateType type)
 {
-  GooCanvasItemModelIface *iface = GOO_CANVAS_ITEM_MODEL_GET_IFACE (model);
-  cairo_matrix_t *matrix, identity_matrix = { 1, 0, 0, 1, 0, 0 };
-  cairo_matrix_t new_matrix = { 1, 0, 0, 1, 0, 0 };
-  GooCanvasItemModelAnimation *anim;
-  double radians = degrees * (M_PI / 180);
-
-  matrix = iface->get_transform (model);
-  if (!matrix)
-    matrix = &identity_matrix;
-
-  cairo_matrix_translate (&new_matrix, x, y);
-  cairo_matrix_scale (&new_matrix, scale, scale);
-  cairo_matrix_rotate (&new_matrix, radians);
-
-  anim = g_new (GooCanvasItemModelAnimation, 1);
-  anim->type = type;
-  anim->model = model;
-  anim->total_steps = anim->num_steps_left = duration / step_time;
-  anim->start = *matrix;
-  anim->step.xx = (new_matrix.xx - matrix->xx) / anim->total_steps; 
-  anim->step.yx = (new_matrix.yx - matrix->yx) / anim->total_steps; 
-  anim->step.xy = (new_matrix.xy - matrix->xy) / anim->total_steps; 
-  anim->step.yy = (new_matrix.yy - matrix->yy) / anim->total_steps; 
-  anim->step.x0 = (new_matrix.x0 - matrix->x0) / anim->total_steps; 
-  anim->step.y0 = (new_matrix.y0 - matrix->y0) / anim->total_steps; 
-  anim->forward = TRUE;
-
-  /* Store a pointer to the new animation in the item. This will automatically
-     stop any current animation and free it. */
-  g_object_set_data_full (G_OBJECT (model), animation_key, anim,
-			  (GDestroyNotify) goo_canvas_item_model_free_animation);
-
-  anim->timeout_id = g_timeout_add (step_time,
-				    (GSourceFunc) goo_canvas_item_model_animate_cb,
-				    anim);
+  _goo_canvas_item_animate_internal (NULL, model, x, y, scale, degrees,
+				     absolute, duration, step_time, type);
 }
 
 
@@ -920,7 +808,7 @@
 void
 goo_canvas_item_model_stop_animation (GooCanvasItemModel *model)
 {
-  /* This will result in a call to goo_canvas_item_model_free_animation(). */
+  /* This will result in a call to goo_canvas_item_free_animation() above. */
   g_object_set_data (G_OBJECT (model), animation_key, NULL);
 }
 

Index: goocanvasitemmodel.h
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvasitemmodel.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- goocanvasitemmodel.h	12 Feb 2007 14:27:33 -0000	1.6
+++ goocanvasitemmodel.h	13 Feb 2007 12:32:44 -0000	1.7
@@ -228,6 +228,7 @@
 							  gdouble             y,
 							  gdouble             scale,
 							  gdouble             degrees,
+							  gboolean            absolute,
 							  gint                duration,
 							  gint                step_time,
 							  GooCanvasAnimateType type);



More information about the cairo-commit mailing list