[gimp] GimpCageConfig: use a GArray to store cage's point, to make easier further improvement



commit 5d771014d40d4c5bff8813aea004235931f5d759
Author: Michael Muré <batolettre gmail com>
Date:   Wed Apr 20 18:40:13 2011 +0200

    GimpCageConfig: use a GArray to store cage's point, to make easier
    further improvement

 app/gegl/gimpcageconfig.c             |  314 ++++++++++++++++++++-------------
 app/gegl/gimpcageconfig.h             |    8 +-
 app/gegl/gimpoperationcagecoefcalc.c  |   29 ++-
 app/gegl/gimpoperationcagetransform.c |   41 +++--
 app/tools/gimpcagetool.c              |   26 ++-
 5 files changed, 248 insertions(+), 170 deletions(-)
---
diff --git a/app/gegl/gimpcageconfig.c b/app/gegl/gimpcageconfig.c
index ce91c76..b0816b8 100644
--- a/app/gegl/gimpcageconfig.c
+++ b/app/gegl/gimpcageconfig.c
@@ -60,29 +60,30 @@ G_DEFINE_TYPE_WITH_CODE (GimpCageConfig, gimp_cage_config,
 
 #define parent_class gimp_cage_config_parent_class
 
-
 #ifdef DEBUG_CAGE
 static void
 print_cage (GimpCageConfig *gcc)
 {
   gint i;
   GeglRectangle bounding_box;
+  GimpCagePoint *point;
 
   g_return_if_fail (GIMP_IS_CAGE_CONFIG (gcc));
 
   bounding_box = gimp_cage_config_get_bounding_box (gcc);
 
-  for (i = 0; i < gcc->n_cage_vertices; i++)
+  for (i = 0; i < gcc->cage_points->len; i++)
     {
+      point = &g_array_index (gcc->cage_points, GimpCagePoint, i);
       g_printerr ("cgx: %.0f    cgy: %.0f    cvdx: %.0f    cvdy: %.0f  sf: %.2f  normx: %.2f  normy: %.2f %s\n",
-                  gcc->cage_points[i].src_point.x + ((gcc->cage_mode==GIMP_CAGE_MODE_CAGE_CHANGE)?gcc->displacement_x:0),
-                  gcc->cage_points[i].src_point.y + ((gcc->cage_mode==GIMP_CAGE_MODE_CAGE_CHANGE)?gcc->displacement_y:0),
-                  gcc->cage_points[i].dest_point.x + ((gcc->cage_mode==GIMP_CAGE_MODE_DEFORM)?gcc->displacement_x:0),
-                  gcc->cage_points[i].dest_point.y + ((gcc->cage_mode==GIMP_CAGE_MODE_DEFORM)?gcc->displacement_y:0),
-                  gcc->cage_points[i].edge_scaling_factor,
-                  gcc->cage_points[i].edge_normal.x,
-                  gcc->cage_points[i].edge_normal.y,
-                  ((gcc->cage_points[i].selected) ? "S" : "NS"));
+                  point->src_point.x + ((gcc->cage_mode==GIMP_CAGE_MODE_CAGE_CHANGE)?gcc->displacement_x:0),
+                  point->src_point.y + ((gcc->cage_mode==GIMP_CAGE_MODE_CAGE_CHANGE)?gcc->displacement_y:0),
+                  point->dest_point.x + ((gcc->cage_mode==GIMP_CAGE_MODE_DEFORM)?gcc->displacement_x:0),
+                  point->dest_point.y + ((gcc->cage_mode==GIMP_CAGE_MODE_DEFORM)?gcc->displacement_y:0),
+                  point->edge_scaling_factor,
+                  point->edge_normal.x,
+                  point->edge_normal.y,
+                  ((point->selected) ? "S" : "NS"));
     }
 
   g_printerr ("bounding box: x: %d  y: %d  width: %d  height: %d\n", bounding_box.x, bounding_box.y, bounding_box.width, bounding_box.height);
@@ -105,10 +106,8 @@ gimp_cage_config_class_init (GimpCageConfigClass *klass)
 static void
 gimp_cage_config_init (GimpCageConfig *self)
 {
-  self->n_cage_vertices   = 0;
-  self->max_cage_vertices = 50; /*pre-allocation for 50 vertices for the cage.*/
-
-  self->cage_points   = g_new0 (GimpCagePoint, self->max_cage_vertices);
+  /*pre-allocation for 50 vertices for the cage.*/
+  self->cage_points = g_array_sized_new (FALSE, FALSE, sizeof(GimpCagePoint), 50);
 }
 
 static void
@@ -116,7 +115,7 @@ gimp_cage_config_finalize (GObject *object)
 {
   GimpCageConfig *gcc = GIMP_CAGE_CONFIG (object);
 
-  g_free (gcc->cage_points);
+  g_array_free (gcc->cage_points, TRUE);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -150,6 +149,18 @@ gimp_cage_config_set_property (GObject      *object,
 }
 
 /**
+ * gimp_cage_config_get_n_points:
+ * @gcc: the cage config
+ *
+ * Returns: the number of points of the cage
+ */
+guint
+gimp_cage_config_get_n_points (GimpCageConfig *gcc)
+{
+  return gcc->cage_points->len;
+}
+
+/**
  * gimp_cage_config_add_cage_point:
  * @gcc: the cage config
  * @x: x value of the new point
@@ -163,25 +174,17 @@ gimp_cage_config_add_cage_point (GimpCageConfig  *gcc,
                                  gdouble          x,
                                  gdouble          y)
 {
-  g_return_if_fail (GIMP_IS_CAGE_CONFIG (gcc));
-
-  /* reallocate memory if needed */
-  if (gcc->n_cage_vertices >= gcc->max_cage_vertices)
-    {
-      gcc->max_cage_vertices += N_ITEMS_PER_ALLOC;
+  GimpCagePoint point;
 
-      gcc->cage_points = g_renew (GimpCagePoint,
-                                  gcc->cage_points,
-                                  gcc->max_cage_vertices);
-    }
+  g_return_if_fail (GIMP_IS_CAGE_CONFIG (gcc));
 
-  gcc->cage_points[gcc->n_cage_vertices].src_point.x = x + DELTA;
-  gcc->cage_points[gcc->n_cage_vertices].src_point.y = y + DELTA;
+  point.src_point.x = x + DELTA;
+  point.src_point.y = y + DELTA;
 
-  gcc->cage_points[gcc->n_cage_vertices].dest_point.x = x + DELTA;
-  gcc->cage_points[gcc->n_cage_vertices].dest_point.y = y + DELTA;
+  point.dest_point.x = x + DELTA;
+  point.dest_point.y = y + DELTA;
 
-  gcc->n_cage_vertices++;
+  g_array_append_val (gcc->cage_points, point);
 
   gimp_cage_config_compute_scaling_factor (gcc);
   gimp_cage_config_compute_edges_normal (gcc);
@@ -198,8 +201,8 @@ gimp_cage_config_remove_last_cage_point (GimpCageConfig  *gcc)
 {
   g_return_if_fail (GIMP_IS_CAGE_CONFIG (gcc));
 
-  if (gcc->n_cage_vertices >= 1)
-    gcc->n_cage_vertices--;
+  if (gcc->cage_points->len > 0)
+    g_array_remove_index (gcc->cage_points, gcc->cage_points->len - 1);
 
   gimp_cage_config_compute_scaling_factor (gcc);
   gimp_cage_config_compute_edges_normal (gcc);
@@ -218,40 +221,43 @@ gimp_cage_config_get_point_coordinate (GimpCageConfig *gcc,
                                        GimpCageMode    mode,
                                        gint            point_number)
 {
-  GimpVector2 point = { 0.0, 0.0 };
+  GimpVector2     result = { 0.0, 0.0 };
+  GimpCagePoint  *point;
+
+  g_return_val_if_fail (GIMP_IS_CAGE_CONFIG (gcc), result);
+  g_return_val_if_fail (point_number < gcc->cage_points->len, result);
+  g_return_val_if_fail (point_number >= 0, result);
 
-  g_return_val_if_fail (GIMP_IS_CAGE_CONFIG (gcc), point);
-  g_return_val_if_fail (point_number < gcc->n_cage_vertices, point);
-  g_return_val_if_fail (point_number >= 0, point);
+  point = &g_array_index (gcc->cage_points, GimpCagePoint, point_number);
 
-  if (gcc->cage_points[point_number].selected)
+  if (point->selected)
     {
       if (mode == GIMP_CAGE_MODE_CAGE_CHANGE)
         {
-          point.x = gcc->cage_points[point_number].src_point.x + gcc->displacement_x;
-          point.y = gcc->cage_points[point_number].src_point.y + gcc->displacement_y;
+          result.x = point->src_point.x + gcc->displacement_x;
+          result.y = point->src_point.y + gcc->displacement_y;
         }
       else
         {
-          point.x = gcc->cage_points[point_number].dest_point.x + gcc->displacement_x;
-          point.y = gcc->cage_points[point_number].dest_point.y + gcc->displacement_y;
+          result.x = point->dest_point.x + gcc->displacement_x;
+          result.y = point->dest_point.y + gcc->displacement_y;
         }
     }
   else
     {
       if (mode == GIMP_CAGE_MODE_CAGE_CHANGE)
         {
-          point.x = gcc->cage_points[point_number].src_point.x;
-          point.y = gcc->cage_points[point_number].src_point.y;
+          result.x = point->src_point.x;
+          result.y = point->src_point.y;
         }
       else
         {
-          point.x = gcc->cage_points[point_number].dest_point.x;
-          point.y = gcc->cage_points[point_number].dest_point.y;
+          result.x = point->dest_point.x;
+          result.y = point->dest_point.y;
         }
     }
 
-  return point;
+  return result;
 }
 
 /**
@@ -295,21 +301,24 @@ gimp_cage_config_commit_displacement (GimpCageConfig *gcc)
 
   g_return_if_fail (GIMP_IS_CAGE_CONFIG (gcc));
 
-  for (i = 0; i < gcc->n_cage_vertices; i++)
+  for (i = 0; i < gcc->cage_points->len; i++)
     {
-      if (gcc->cage_points[i].selected)
+      GimpCagePoint *point;
+      point = &g_array_index (gcc->cage_points, GimpCagePoint, i);
+
+      if (point->selected)
         {
           if (gcc->cage_mode == GIMP_CAGE_MODE_CAGE_CHANGE)
             {
-              gcc->cage_points[i].src_point.x += gcc->displacement_x;
-              gcc->cage_points[i].src_point.y += gcc->displacement_y;
-              gcc->cage_points[i].dest_point.x += gcc->displacement_x;
-              gcc->cage_points[i].dest_point.y += gcc->displacement_y;
+              point->src_point.x += gcc->displacement_x;
+              point->src_point.y += gcc->displacement_y;
+              point->dest_point.x += gcc->displacement_x;
+              point->dest_point.y += gcc->displacement_y;
             }
           else
             {
-              gcc->cage_points[i].dest_point.x += gcc->displacement_x;
-              gcc->cage_points[i].dest_point.y += gcc->displacement_y;
+              point->dest_point.x += gcc->displacement_x;
+              point->dest_point.y += gcc->displacement_y;
             }
         }
     }
@@ -345,39 +354,43 @@ gimp_cage_config_reset_displacement (GimpCageConfig *gcc)
 GeglRectangle
 gimp_cage_config_get_bounding_box (GimpCageConfig *gcc)
 {
-  GeglRectangle bounding_box = { 0, };
-  gint          i;
+  GeglRectangle  bounding_box = { 0, 0, 0, 0};
+  gint           i;
+  GimpCagePoint *point;
 
   g_return_val_if_fail (GIMP_IS_CAGE_CONFIG (gcc), bounding_box);
-  g_return_val_if_fail (gcc->n_cage_vertices >= 0, bounding_box);
+  g_return_val_if_fail (gcc->cage_points->len >= 0, bounding_box);
+
+  if (gcc->cage_points->len == 0)
+    return bounding_box;
 
-  if (gcc->cage_points[0].selected)
+  point = &g_array_index (gcc->cage_points, GimpCagePoint, 0);
+
+  if (point->selected)
     {
-      bounding_box.x = gcc->cage_points[0].src_point.x + gcc->displacement_x;
-      bounding_box.y = gcc->cage_points[0].src_point.y + gcc->displacement_y;
+      bounding_box.x = point->src_point.x + gcc->displacement_x;
+      bounding_box.y = point->src_point.y + gcc->displacement_y;
     }
   else
     {
-      bounding_box.x = gcc->cage_points[0].src_point.x;
-      bounding_box.y = gcc->cage_points[0].src_point.y;
+      bounding_box.x = point->src_point.x;
+      bounding_box.y = point->src_point.y;
     }
 
-  bounding_box.height = 0;
-  bounding_box.width = 0;
-
-  for (i = 1; i < gcc->n_cage_vertices; i++)
+  for (i = 1; i < gcc->cage_points->len; i++)
     {
       gdouble x,y;
+      point = &g_array_index (gcc->cage_points, GimpCagePoint, i);
 
-      if (gcc->cage_points[i].selected)
+      if (point->selected)
         {
-          x = gcc->cage_points[i].src_point.x + gcc->displacement_x;
-          y = gcc->cage_points[i].src_point.y + gcc->displacement_y;
+          x = point->src_point.x + gcc->displacement_x;
+          y = point->src_point.y + gcc->displacement_y;
         }
       else
         {
-          x = gcc->cage_points[i].src_point.x;
-          y = gcc->cage_points[i].src_point.y;
+          x = point->src_point.x;
+          y = point->src_point.y;
         }
 
       if (x < bounding_box.x)
@@ -422,11 +435,14 @@ gimp_cage_config_reverse_cage (GimpCageConfig *gcc)
 
   g_return_if_fail (GIMP_IS_CAGE_CONFIG (gcc));
 
-  for (i = 0; i < gcc->n_cage_vertices / 2; i++)
+  for (i = 0; i < gcc->cage_points->len / 2; i++)
     {
-      temp = gcc->cage_points[i];
-      gcc->cage_points[i] = gcc->cage_points[gcc->n_cage_vertices - i - 1];
-      gcc->cage_points[gcc->n_cage_vertices - i - 1] = temp;
+      temp = g_array_index (gcc->cage_points, GimpCagePoint, i);
+
+      g_array_index (gcc->cage_points, GimpCagePoint, i) =
+        g_array_index (gcc->cage_points, GimpCagePoint, gcc->cage_points->len - i - 1);
+
+      g_array_index (gcc->cage_points, GimpCagePoint, gcc->cage_points->len - i - 1) = temp;
     }
 
   gimp_cage_config_compute_scaling_factor (gcc);
@@ -457,14 +473,14 @@ gimp_cage_config_reverse_cage_if_needed (GimpCageConfig *gcc)
   /* this is a bit crappy, but should works most of the case */
   /* we do the sum of the projection of each point to the previous
      segment, and see the final sign */
-  for (i = 0; i < gcc->n_cage_vertices ; i++)
+  for (i = 0; i < gcc->cage_points->len ; i++)
     {
       GimpVector2 P1, P2, P3;
       gdouble     z;
 
-      P1 = gcc->cage_points[i].src_point;
-      P2 = gcc->cage_points[(i+1) % gcc->n_cage_vertices].src_point;
-      P3 = gcc->cage_points[(i+2) % gcc->n_cage_vertices].src_point;
+      P1 = (g_array_index (gcc->cage_points, GimpCagePoint, i)).src_point;
+      P2 = (g_array_index (gcc->cage_points, GimpCagePoint, (i+1) % gcc->cage_points->len)).src_point;
+      P3 = (g_array_index (gcc->cage_points, GimpCagePoint, (i+2) % gcc->cage_points->len)).src_point;
 
       z = P1.x * (P2.y - P3.y) + P2.x * (P3.y - P1.y) + P3.x * (P1.y - P2.y);
 
@@ -488,25 +504,33 @@ gimp_cage_config_reverse_cage_if_needed (GimpCageConfig *gcc)
 static void
 gimp_cage_config_compute_scaling_factor (GimpCageConfig *gcc)
 {
-  GimpVector2 edge;
-  gdouble     length, length_d;
-  gint        i;
+  GimpVector2    edge;
+  gdouble        length, length_d;
+  gint           i;
+  GimpCagePoint *current, *last;
 
   g_return_if_fail (GIMP_IS_CAGE_CONFIG (gcc));
+  if (gcc->cage_points->len < 2)
+    return;
+
+  last = &g_array_index (gcc->cage_points, GimpCagePoint, 0);
 
-  for (i = 0; i < gcc->n_cage_vertices; i++)
+  for (i = 1; i <= gcc->cage_points->len; i++)
     {
+      current = &g_array_index (gcc->cage_points, GimpCagePoint, i % gcc->cage_points->len);
+
       gimp_vector2_sub (&edge,
-                        &gcc->cage_points[i].src_point,
-                        &gcc->cage_points[(i + 1) % gcc->n_cage_vertices].src_point);
+                        &(last->src_point),
+                        &(current->src_point));
       length = gimp_vector2_length (&edge);
 
       gimp_vector2_sub (&edge,
-                        &gcc->cage_points[i].dest_point,
-                        &gcc->cage_points[(i + 1) % gcc->n_cage_vertices].dest_point);
+                        &(last->dest_point),
+                        &(current->dest_point));
       length_d = gimp_vector2_length (&edge);
 
-      gcc->cage_points[i].edge_scaling_factor = length_d / length;
+      last->edge_scaling_factor = length_d / length;
+      last = current;
     }
 }
 
@@ -520,18 +544,24 @@ gimp_cage_config_compute_scaling_factor (GimpCageConfig *gcc)
 static void
 gimp_cage_config_compute_edges_normal (GimpCageConfig *gcc)
 {
-  GimpVector2 normal;
-  gint        i;
+  GimpVector2    normal;
+  gint           i;
+  GimpCagePoint *current, *last;
 
   g_return_if_fail (GIMP_IS_CAGE_CONFIG (gcc));
 
-  for (i = 0; i < gcc->n_cage_vertices; i++)
+  last = &g_array_index (gcc->cage_points, GimpCagePoint, 0);
+
+  for (i = 1; i <= gcc->cage_points->len; i++)
     {
+      current = &g_array_index (gcc->cage_points, GimpCagePoint, i % gcc->cage_points->len);
+
       gimp_vector2_sub (&normal,
-                        &gcc->cage_points[(i + 1) % gcc->n_cage_vertices].dest_point,
-                        &gcc->cage_points[i].dest_point);
+                        &(current->dest_point),
+                        &(last->dest_point));
 
-      gcc->cage_points[i].edge_normal = gimp_vector2_normal (&normal);
+      last->edge_normal = gimp_vector2_normal (&normal);
+      last = current;
     }
 }
 
@@ -552,25 +582,26 @@ gimp_cage_config_point_inside (GimpCageConfig *gcc,
                                gfloat          x,
                                gfloat          y)
 {
-  GimpVector2 *cpi, *cpj;
-  gboolean     inside = FALSE;
-  gint         i, j;
+  GimpVector2   *last, *current;
+  gboolean       inside = FALSE;
+  gint           i;
 
   g_return_val_if_fail (GIMP_IS_CAGE_CONFIG (gcc), FALSE);
 
-  for (i = 0, j = gcc->n_cage_vertices - 1;
-       i < gcc->n_cage_vertices;
-       j = i++)
+  last = &((g_array_index (gcc->cage_points, GimpCagePoint, gcc->cage_points->len - 1)).src_point);
+
+  for (i = 0; i < gcc->cage_points->len; i++)
     {
-      cpi = &(gcc->cage_points[i].src_point);
-      cpj = &(gcc->cage_points[j].src_point);
+      current = &((g_array_index (gcc->cage_points, GimpCagePoint, i)).src_point);
 
-      if ((((cpi->y <= y) && (y < cpj->y))
-           || ((cpj->y <= y) && (y < cpi->y)))
-          && (x < (cpj->x - cpi->x) * (y - cpi->y) / (cpj->y - cpi->y) + cpi->x))
+      if ((((current->y <= y) && (y < last->y))
+           || ((last->y <= y) && (y < current->y)))
+          && (x < (last->x - current->x) * (y - current->y) / (last->y - current->y) + current->x))
         {
           inside = !inside;
         }
+
+      last = current;
     }
 
   return inside;
@@ -587,21 +618,24 @@ void
 gimp_cage_config_select_point (GimpCageConfig  *gcc,
                                gint             point_number)
 {
-  gint  i;
+  gint           i;
+  GimpCagePoint *point;
 
   g_return_if_fail (GIMP_IS_CAGE_CONFIG (gcc));
-  g_return_if_fail (point_number < gcc->n_cage_vertices);
+  g_return_if_fail (point_number < gcc->cage_points->len);
   g_return_if_fail (point_number >= 0);
 
-  for (i = 0; i < gcc->n_cage_vertices; i++)
+  for (i = 0; i < gcc->cage_points->len; i++)
     {
+      point = &g_array_index (gcc->cage_points, GimpCagePoint, i);
+
       if (i == point_number)
         {
-          gcc->cage_points[i].selected = TRUE;
+          point->selected = TRUE;
         }
       else
         {
-          gcc->cage_points[i].selected = FALSE;
+          point->selected = FALSE;
         }
     }
 }
@@ -638,30 +672,33 @@ gimp_cage_config_select_add_area (GimpCageConfig *gcc,
                                   GimpCageMode    mode,
                                   GeglRectangle   area)
 {
-  gint  i;
+  gint           i;
+  GimpCagePoint *point;
 
   g_return_if_fail (GIMP_IS_CAGE_CONFIG (gcc));
 
-  for (i = 0; i < gcc->n_cage_vertices; i++)
+  for (i = 0; i < gcc->cage_points->len; i++)
     {
+      point = &g_array_index (gcc->cage_points, GimpCagePoint, i);
+
       if (mode == GIMP_CAGE_MODE_CAGE_CHANGE)
         {
-          if (gcc->cage_points[i].src_point.x >= area.x &&
-              gcc->cage_points[i].src_point.x <= area.x + area.width &&
-              gcc->cage_points[i].src_point.y >= area.y &&
-              gcc->cage_points[i].src_point.y <= area.y + area.height)
+          if (point->src_point.x >= area.x &&
+              point->src_point.x <= area.x + area.width &&
+              point->src_point.y >= area.y &&
+              point->src_point.y <= area.y + area.height)
             {
-              gcc->cage_points[i].selected = TRUE;
+              point->selected = TRUE;
             }
         }
       else
         {
-          if (gcc->cage_points[i].dest_point.x >= area.x &&
-              gcc->cage_points[i].dest_point.x <= area.x + area.width &&
-              gcc->cage_points[i].dest_point.y >= area.y &&
-              gcc->cage_points[i].dest_point.y <= area.y + area.height)
+          if (point->dest_point.x >= area.x &&
+              point->dest_point.x <= area.x + area.width &&
+              point->dest_point.y >= area.y &&
+              point->dest_point.y <= area.y + area.height)
             {
-              gcc->cage_points[i].selected = TRUE;
+              point->selected = TRUE;
             }
         }
     }
@@ -678,11 +715,14 @@ void
 gimp_cage_config_toggle_point_selection (GimpCageConfig *gcc,
                                          gint            point_number)
 {
+  GimpCagePoint *point;
+
   g_return_if_fail (GIMP_IS_CAGE_CONFIG (gcc));
-  g_return_if_fail (point_number < gcc->n_cage_vertices);
+  g_return_if_fail (point_number < gcc->cage_points->len);
   g_return_if_fail (point_number >= 0);
 
-  gcc->cage_points[point_number].selected = ! gcc->cage_points[point_number].selected;
+  point = &g_array_index (gcc->cage_points, GimpCagePoint, point_number);
+  point->selected = ! point->selected;
 }
 
 /**
@@ -698,8 +738,30 @@ gimp_cage_config_deselect_points (GimpCageConfig *gcc)
 
   g_return_if_fail (GIMP_IS_CAGE_CONFIG (gcc));
 
-  for (i = 0; i < gcc->n_cage_vertices; i++)
+  for (i = 0; i < gcc->cage_points->len; i++)
     {
-      gcc->cage_points[i].selected = FALSE;
+      (g_array_index (gcc->cage_points, GimpCagePoint, i)).selected = FALSE;
     }
 }
+
+/**
+ * gimp_cage_config_point_is_selected:
+ * @gcc: the cage config
+ * @point_number: the index of the point to test
+ *
+ * Returns: TRUE if the point is selected, FALSE otherwise.
+ */
+gboolean
+gimp_cage_config_point_is_selected (GimpCageConfig  *gcc,
+                                    gint             point_number)
+{
+  GimpCagePoint *point;
+
+  g_return_val_if_fail (GIMP_IS_CAGE_CONFIG (gcc), FALSE);
+  g_return_val_if_fail (point_number < gcc->cage_points->len, FALSE);
+  g_return_val_if_fail (point_number >= 0, FALSE);
+
+  point = &(g_array_index (gcc->cage_points, GimpCagePoint, point_number));
+
+  return point->selected;
+}
diff --git a/app/gegl/gimpcageconfig.h b/app/gegl/gimpcageconfig.h
index c553522..6d8c544 100644
--- a/app/gegl/gimpcageconfig.h
+++ b/app/gegl/gimpcageconfig.h
@@ -48,14 +48,11 @@ struct _GimpCageConfig
 {
   GimpImageMapConfig  parent_instance;
 
-  gint                n_cage_vertices;   /* vertices used by the cage */
-  gint                max_cage_vertices; /* vertices allocated        */
+  GArray             *cage_points;
 
   gdouble             displacement_x;
   gdouble             displacement_y;
   GimpCageMode        cage_mode;  /* Cage mode, used to commit displacement */
-
-  GimpCagePoint      *cage_points;
 };
 
 struct _GimpCageConfigClass
@@ -66,6 +63,7 @@ struct _GimpCageConfigClass
 
 GType           gimp_cage_config_get_type               (void) G_GNUC_CONST;
 
+guint           gimp_cage_config_get_n_points           (GimpCageConfig  *gcc);
 void            gimp_cage_config_add_cage_point         (GimpCageConfig  *gcc,
                                                          gdouble          x,
                                                          gdouble          y);
@@ -96,6 +94,8 @@ void            gimp_cage_config_select_add_area        (GimpCageConfig  *gcc,
 void            gimp_cage_config_toggle_point_selection (GimpCageConfig  *gcc,
                                                          gint             point_number);
 void            gimp_cage_config_deselect_points        (GimpCageConfig  *gcc);
+gboolean        gimp_cage_config_point_is_selected      (GimpCageConfig  *gcc,
+                                                         gint             point_number);
 
 
 #endif /* __GIMP_CAGE_CONFIG_H__ */
diff --git a/app/gegl/gimpoperationcagecoefcalc.c b/app/gegl/gimpoperationcagecoefcalc.c
index 5455577..e355068 100644
--- a/app/gegl/gimpoperationcagecoefcalc.c
+++ b/app/gegl/gimpoperationcagecoefcalc.c
@@ -96,7 +96,7 @@ gimp_operation_cage_coef_calc_prepare (GeglOperation *operation)
   gegl_operation_set_format (operation,
                              "output",
                              babl_format_n (babl_type ("float"),
-                                            2 * config->n_cage_vertices));
+                                            2 * gimp_cage_config_get_n_points (config)));
 }
 
 static void
@@ -193,13 +193,17 @@ gimp_operation_cage_coef_calc_process (GeglOperation       *operation,
   GimpOperationCageCoefCalc *occc   = GIMP_OPERATION_CAGE_COEF_CALC (operation);
   GimpCageConfig            *config = GIMP_CAGE_CONFIG (occc->config);
 
-  Babl *format = babl_format_n (babl_type ("float"), 2 * config->n_cage_vertices);
+  Babl *format = babl_format_n (babl_type ("float"), 2 * gimp_cage_config_get_n_points (config));
 
   GeglBufferIterator *it;
+  guint               n_cage_vertices;
+  GimpCagePoint      *current, *last;
 
   if (! config)
     return FALSE;
 
+  n_cage_vertices   = gimp_cage_config_get_n_points (config);
+
   it = gegl_buffer_iterator_new (output, roi, format, GEGL_BUFFER_READWRITE);
 
   while (gegl_buffer_iterator_next (it))
@@ -216,13 +220,16 @@ gimp_operation_cage_coef_calc_process (GeglOperation       *operation,
         {
           if (gimp_cage_config_point_inside(config, x, y))
             {
-              for( j = 0; j < config->n_cage_vertices; j++)
+              last = &(g_array_index (config->cage_points, GimpCagePoint, 0));
+
+              for( j = 0; j < n_cage_vertices; j++)
                 {
                   GimpVector2 v1,v2,a,b,p;
                   gdouble BA,SRT,L0,L1,A0,A1,A10,L10, Q,S,R, absa;
 
-                  v1 = config->cage_points[j].src_point;
-                  v2 = config->cage_points[(j+1)%config->n_cage_vertices].src_point;
+                  current = &(g_array_index (config->cage_points, GimpCagePoint, (j+1) % n_cage_vertices));
+                  v1 = last->src_point;
+                  v2 = current->src_point;
                   p.x = x;
                   p.y = y;
                   a.x = v2.x - v1.x;
@@ -245,23 +252,25 @@ gimp_operation_cage_coef_calc_process (GeglOperation       *operation,
                   L10 = L1 - L0;
 
                   /* edge coef */
-                  coef[j + config->n_cage_vertices] = (-absa / (4.0 * M_PI)) * ((4.0*S-(R*R)/Q) * A10 + (R / (2.0 * Q)) * L10 + L1 - 2.0);
+                  coef[j + n_cage_vertices] = (-absa / (4.0 * M_PI)) * ((4.0*S-(R*R)/Q) * A10 + (R / (2.0 * Q)) * L10 + L1 - 2.0);
 
-                  if (isnan(coef[j + config->n_cage_vertices]))
+                  if (isnan(coef[j + n_cage_vertices]))
                     {
-                      coef[j + config->n_cage_vertices] = 0.0;
+                      coef[j + n_cage_vertices] = 0.0;
                     }
 
                   /* vertice coef */
                   if (!gimp_operation_cage_coef_calc_is_on_straight (&v1, &v2, &p))
                     {
                       coef[j] += (BA / (2.0 * M_PI)) * (L10 /(2.0*Q) - A10 * (2.0 + R / Q));
-                      coef[(j+1)%config->n_cage_vertices] -= (BA / (2.0 * M_PI)) * (L10 / (2.0 * Q) - A10 * (R / Q));
+                      coef[(j+1)%n_cage_vertices] -= (BA / (2.0 * M_PI)) * (L10 / (2.0 * Q) - A10 * (R / Q));
                     }
+
+                  last = current;
                 }
             }
 
-          coef += 2 * config->n_cage_vertices;
+          coef += 2 * n_cage_vertices;
 
           /* update x and y coordinates */
           x++;
diff --git a/app/gegl/gimpoperationcagetransform.c b/app/gegl/gimpoperationcagetransform.c
index 64f613c..4affa9a 100644
--- a/app/gegl/gimpoperationcagetransform.c
+++ b/app/gegl/gimpoperationcagetransform.c
@@ -210,7 +210,7 @@ gimp_operation_cage_transform_prepare (GeglOperation *operation)
 
   gegl_operation_set_format (operation, "input",
                              babl_format_n (babl_type ("float"),
-                                            2 * config->n_cage_vertices));
+                                            2 * gimp_cage_config_get_n_points (config)));
   gegl_operation_set_format (operation, "output",
                              babl_format_n (babl_type ("float"), 2));
 }
@@ -232,13 +232,18 @@ gimp_operation_cage_transform_process (GeglOperation       *operation,
   GeglBufferIterator         *it;
   gint                        x, y;
   gboolean                    output_set;
+  GimpCagePoint              *point;
+  guint                       n_cage_vertices;
 
   /* pre-fill the out buffer with no-displacement coordinate */
   it      = gegl_buffer_iterator_new (out_buf, roi, NULL, GEGL_BUFFER_WRITE);
   cage_bb = gimp_cage_config_get_bounding_box (config);
 
-  plain_color.x = (gint) config->cage_points[0].src_point.x;
-  plain_color.y = (gint) config->cage_points[0].src_point.y;
+  point = &(g_array_index (config->cage_points, GimpCagePoint, 0));
+  plain_color.x = (gint) point->src_point.x;
+  plain_color.y = (gint) point->src_point.y;
+
+  n_cage_vertices   = gimp_cage_config_get_n_points (config);
 
   while (gegl_buffer_iterator_next (it))
     {
@@ -290,8 +295,8 @@ gimp_operation_cage_transform_process (GeglOperation       *operation,
 
   /* pre-allocate memory outside of the loop */
   coords      = g_slice_alloc (2 * sizeof (gfloat));
-  coef        = g_malloc (config->n_cage_vertices * 2 * sizeof (gfloat));
-  format_coef = babl_format_n (babl_type ("float"), 2 * config->n_cage_vertices);
+  coef        = g_malloc (n_cage_vertices * 2 * sizeof (gfloat));
+  format_coef = babl_format_n (babl_type ("float"), 2 * n_cage_vertices);
 
   /* compute, reverse and interpolate the transformation */
   for (y = cage_bb.y; y < cage_bb.y + cage_bb.height - 1; y++)
@@ -536,14 +541,14 @@ gimp_cage_transform_compute_destination (GimpCageConfig *config,
                                          GeglBuffer     *coef_buf,
                                          GimpVector2     coords)
 {
-  gdouble        pos_x, pos_y;
-  GimpVector2    result;
-  gint           cvn = config->n_cage_vertices;
+  GimpVector2    result = {0, 0};
+  gint           n_cage_vertices = gimp_cage_config_get_n_points (config);
   gint           i;
+  GimpCagePoint *point;
 
   /* When Gegl bug #645810 will be solved, this should be a good optimisation */
   #ifdef GEGL_BUG_645810_SOLVED
-    gegl_buffer_sample (coef_buf, coords.x, coords.y, 1.0, coef, format_coef, GEGL_INTERPOLATION_LANCZOS);
+    gegl_buffer_sample (coef_buf, coords.x, coords.y, 1.0, coef, format_coef, GEGL_INTERPOLATION_NEAREST);
   #else
     GeglRectangle  rect;
 
@@ -555,20 +560,16 @@ gimp_cage_transform_compute_destination (GimpCageConfig *config,
     gegl_buffer_get (coef_buf, 1, &rect, format_coef, coef, GEGL_AUTO_ROWSTRIDE);
   #endif
 
-  pos_x = 0;
-  pos_y = 0;
-
-  for (i = 0; i < cvn; i++)
+  for (i = 0; i < n_cage_vertices; i++)
     {
-      pos_x += coef[i] * config->cage_points[i].dest_point.x;
-      pos_y += coef[i] * config->cage_points[i].dest_point.y;
+      point = &g_array_index (config->cage_points, GimpCagePoint, i);
 
-      pos_x += coef[i + cvn] * config->cage_points[i].edge_scaling_factor * config->cage_points[i].edge_normal.x;
-      pos_y += coef[i + cvn] * config->cage_points[i].edge_scaling_factor * config->cage_points[i].edge_normal.y;
-    }
+      result.x += coef[i] * point->dest_point.x;
+      result.y += coef[i] * point->dest_point.y;
 
-  result.x = pos_x;
-  result.y = pos_y;
+      result.x += coef[i + n_cage_vertices] * point->edge_scaling_factor * point->edge_normal.x;
+      result.y += coef[i + n_cage_vertices] * point->edge_scaling_factor * point->edge_normal.y;
+    }
 
   return result;
 }
diff --git a/app/tools/gimpcagetool.c b/app/tools/gimpcagetool.c
index d8d8201..ee3b882 100644
--- a/app/tools/gimpcagetool.c
+++ b/app/tools/gimpcagetool.c
@@ -547,10 +547,10 @@ gimp_cage_tool_button_press (GimpTool            *tool,
                                                  coords->x - ct->offset_x,
                                                  coords->y - ct->offset_y);
                 gimp_cage_config_select_point (ct->config,
-                                               ct->config->n_cage_vertices - 1);
+                                               gimp_cage_config_get_n_points (ct->config) - 1);
                 ct->tool_state = CAGE_STATE_MOVE_HANDLE;
               }
-            else if (handle == 0 && ct->config->n_cage_vertices > 2)
+            else if (handle == 0 && gimp_cage_config_get_n_points (ct->config) > 2)
               {
                 /* User clicked on the first handle, we wait for
                  * release for closing the cage and switching to
@@ -573,7 +573,7 @@ gimp_cage_tool_button_press (GimpTool            *tool,
                   {
                     /* New selection */
 
-                    if (! ct->config->cage_points[handle].selected)
+                    if (! gimp_cage_config_point_is_selected (ct->config, handle))
                       {
                         gimp_cage_config_select_point (ct->config, handle);
                       }
@@ -610,7 +610,7 @@ gimp_cage_tool_button_press (GimpTool            *tool,
                   {
                     /* New selection */
 
-                    if (! ct->config->cage_points[handle].selected)
+                    if (! gimp_cage_config_point_is_selected (ct->config, handle))
                       {
                         gimp_cage_config_select_point (ct->config, handle);
                       }
@@ -646,7 +646,7 @@ gimp_cage_tool_button_press (GimpTool            *tool,
               {
                 /* New selection */
 
-                if (! ct->config->cage_points[handle].selected)
+                if (! gimp_cage_config_point_is_selected (ct->config, handle))
                   {
                     gimp_cage_config_select_point (ct->config, handle);
                   }
@@ -819,7 +819,10 @@ gimp_cage_tool_draw (GimpDrawTool *draw_tool)
   gint             i;
   GimpHandleType   handle;
 
-  n_vertices = config->n_cage_vertices;
+  n_vertices = gimp_cage_config_get_n_points (config);
+
+  if (n_vertices == 0)
+    return;
 
   if (ct->tool_state == CAGE_STATE_INIT)
     return;
@@ -896,7 +899,7 @@ gimp_cage_tool_draw (GimpDrawTool *draw_tool)
                                  GIMP_TOOL_HANDLE_SIZE_CIRCLE,
                                  GIMP_HANDLE_ANCHOR_CENTER);
 
-      if (ct->config->cage_points[i].selected)
+      if (gimp_cage_config_point_is_selected (ct->config, i))
         {
           gimp_draw_tool_add_handle (draw_tool,
                                      GIMP_HANDLE_SQUARE,
@@ -933,13 +936,16 @@ gimp_cage_tool_is_on_handle (GimpCageTool *ct,
   gdouble          dist    = G_MAXDOUBLE;
   gint             i;
   GimpVector2      cage_point;
+  guint            n_cage_vertices;
 
   g_return_val_if_fail (GIMP_IS_CAGE_TOOL (ct), -1);
 
-  if (config->n_cage_vertices == 0)
+  n_cage_vertices = gimp_cage_config_get_n_points (config);
+
+  if (n_cage_vertices == 0)
     return -1;
 
-  for (i = 0; i < config->n_cage_vertices; i++)
+  for (i = 0; i < n_cage_vertices; i++)
     {
       cage_point = gimp_cage_config_get_point_coordinate (config,
                                                           options->cage_mode,
@@ -996,7 +1002,7 @@ gimp_cage_tool_compute_coef (GimpCageTool *ct,
     }
 
   format = babl_format_n (babl_type ("float"),
-                          config->n_cage_vertices * 2);
+                          gimp_cage_config_get_n_points (config) * 2);
 
 
   gegl = gegl_node_new ();



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]