gimp r27314 - in trunk: . app app/core app/vectors



Author: neo
Date: Sat Oct 18 18:46:15 2008
New Revision: 27314
URL: http://svn.gnome.org/viewvc/gimp?rev=27314&view=rev

Log:
2008-10-18  Sven Neumann  <sven gimp org>

	Applied patch from Alexia Death as attached to bug #471344:
	
	* app/core/Makefile.am
	* app/core/gimpcoords-interpolate.[ch]: new files with
	interpolation code taken from ...

	* app/vectors/gimpbezierstroke.c: ... here.

	* app/Makefile.am (AM_LDFLAGS): make it link.



Added:
   trunk/app/core/gimpcoords-interpolate.c
   trunk/app/core/gimpcoords-interpolate.h
Modified:
   trunk/ChangeLog
   trunk/app/Makefile.am
   trunk/app/core/Makefile.am
   trunk/app/vectors/gimpbezierstroke.c

Modified: trunk/app/Makefile.am
==============================================================================
--- trunk/app/Makefile.am	(original)
+++ trunk/app/Makefile.am	Sat Oct 18 18:46:15 2008
@@ -99,7 +99,7 @@
 	$(CARBON_LDFLAGS)				\
 	-u $(SYMPREFIX)xcf_init				\
 	-u $(SYMPREFIX)internal_procs_init		\
-	-u $(SYMPREFIX)gimp_coords_mix			\
+	-u $(SYMPREFIX)gimp_coords_interpolate_bezier	\
 	-u $(SYMPREFIX)gimp_curve_map_pixels		\
 	-u $(SYMPREFIX)gimp_image_map_config_get_type	\
 	-u $(SYMPREFIX)gimp_plug_in_manager_restore

Modified: trunk/app/core/Makefile.am
==============================================================================
--- trunk/app/core/Makefile.am	(original)
+++ trunk/app/core/Makefile.am	Sat Oct 18 18:46:15 2008
@@ -88,6 +88,8 @@
 	gimpcontext.h				\
 	gimpcoords.c				\
 	gimpcoords.h				\
+	gimpcoords-interpolate.c		\
+	gimpcoords-interpolate.h		\
 	gimpcurve.c				\
 	gimpcurve.h				\
 	gimpcurve-load.c			\

Added: trunk/app/core/gimpcoords-interpolate.c
==============================================================================
--- (empty file)
+++ trunk/app/core/gimpcoords-interpolate.c	Sat Oct 18 18:46:15 2008
@@ -0,0 +1,210 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpcoords-interpolate.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+
+#include "libgimpmath/gimpmath.h"
+
+#include "core-types.h"
+
+#include "gimpcoords.h"
+#include "gimpcoords-interpolate.h"
+
+/* Local helper functions declarations*/
+static void     gimp_coords_interpolate_bezier_internal (const GimpCoords  bezier_pt1,
+                                                         const GimpCoords  bezier_pt2,
+                                                         const GimpCoords  bezier_pt3,
+                                                         const GimpCoords  bezier_pt4,
+                                                         const gdouble     start_t,
+                                                         const gdouble     end_t,
+                                                         const gdouble     precision,
+                                                         GArray          **ret_coords,
+                                                         GArray          **ret_params,
+                                                         gint              depth);
+
+/* Functions for bezier subdivision */
+
+void
+gimp_coords_interpolate_bezier (const GimpCoords   bezier_pt1,
+                                const GimpCoords   bezier_pt2,
+                                const GimpCoords   bezier_pt3,
+                                const GimpCoords   bezier_pt4,
+                                const gdouble      precision,
+                                GArray           **ret_coords,
+                                GArray           **ret_params)
+{
+  gimp_coords_interpolate_bezier_internal (bezier_pt1,
+                                           bezier_pt2,
+                                           bezier_pt3,
+                                           bezier_pt4,
+                                           0.0, 1.0,
+                                           precision,
+                                           ret_coords, ret_params, 10);
+}
+
+/* Recursive subdivision helper function */
+static void
+gimp_coords_interpolate_bezier_internal (const GimpCoords  bezier_pt1,
+                                         const GimpCoords  bezier_pt2,
+                                         const GimpCoords  bezier_pt3,
+                                         const GimpCoords  bezier_pt4,
+                                         const gdouble     start_t,
+                                         const gdouble     end_t,
+                                         const gdouble     precision,
+                                         GArray          **ret_coords,
+                                         GArray          **ret_params,
+                                         gint              depth)
+{
+  /*
+   * beziercoords has to contain four GimpCoords with the four control points
+   * of the bezier segment. We subdivide it at the parameter 0.5.
+   */
+
+  GimpCoords subdivided[8];
+  gdouble    middle_t = (start_t + end_t) / 2;
+
+  subdivided[0] = bezier_pt1;
+  subdivided[6] = bezier_pt4;
+
+  /* if (!depth) g_printerr ("Hit recursion depth limit!\n"); */
+
+  gimp_coords_average (&bezier_pt1, &bezier_pt2, &(subdivided[1]));
+
+  gimp_coords_average (&bezier_pt2, &bezier_pt3, &(subdivided[7]));
+
+  gimp_coords_average (&bezier_pt3, &bezier_pt4, &(subdivided[5]));
+
+  gimp_coords_average (&(subdivided[1]), &(subdivided[7]),
+                       &(subdivided[2]));
+
+  gimp_coords_average (&(subdivided[7]), &(subdivided[5]),
+                       &(subdivided[4]));
+
+  gimp_coords_average (&(subdivided[2]), &(subdivided[4]),
+                       &(subdivided[3]));
+
+  /*
+   * We now have the coordinates of the two bezier segments in
+   * subdivided [0-3] and subdivided [3-6]
+   */
+
+  /*
+   * Here we need to check, if we have sufficiently subdivided, i.e.
+   * if the stroke is sufficiently close to a straight line.
+   */
+
+  if (!depth || gimp_coords_bezier_is_straight (subdivided[0],
+                                                subdivided[1],
+                                                subdivided[2],
+                                                subdivided[3],
+                                                precision)) /* 1st half */
+    {
+      *ret_coords = g_array_append_vals (*ret_coords, &(subdivided[0]), 3);
+
+      if (ret_params)
+        {
+          gdouble params[3];
+
+          params[0] = start_t;
+          params[1] = (2 * start_t + middle_t) / 3;
+          params[2] = (start_t + 2 * middle_t) / 3;
+
+          *ret_params = g_array_append_vals (*ret_params, &(params[0]), 3);
+        }
+    }
+  else
+    {
+      gimp_coords_interpolate_bezier_internal (subdivided[0],
+                                               subdivided[1],
+                                               subdivided[2],
+                                               subdivided[3],
+                                               start_t, (start_t + end_t) / 2,
+                                               precision,
+                                               ret_coords, ret_params, depth-1);
+    }
+
+  if (!depth || gimp_coords_bezier_is_straight (subdivided[3],
+                                                subdivided[4],
+                                                subdivided[5],
+                                                subdivided[6],
+                                                precision)) /* 2nd half */
+    {
+      *ret_coords = g_array_append_vals (*ret_coords, &(subdivided[3]), 3);
+
+      if (ret_params)
+        {
+          gdouble params[3];
+
+          params[0] = middle_t;
+          params[1] = (2 * middle_t + end_t) / 3;
+          params[2] = (middle_t + 2 * end_t) / 3;
+
+          *ret_params = g_array_append_vals (*ret_params, &(params[0]), 3);
+        }
+    }
+  else
+    {
+      gimp_coords_interpolate_bezier_internal (subdivided[3],
+                                               subdivided[4],
+                                               subdivided[5],
+                                               subdivided[6],
+                                               (start_t + end_t) / 2, end_t,
+                                               precision,
+                                               ret_coords, ret_params, depth-1);
+    }
+}
+
+
+/*
+ * a helper function that determines if a bezier segment is "straight
+ * enough" to be approximated by a line.
+ *
+ * To be more exact, it also checks for the control points to be distributed
+ * evenly along the line. This makes it easier to reconstruct parameters for
+ * a given point along the segment.
+ *
+ * Needs four GimpCoords in an array.
+ */
+
+gboolean
+gimp_coords_bezier_is_straight (const GimpCoords bezier_pt1,
+                                const GimpCoords bezier_pt2,
+                                const GimpCoords bezier_pt3,
+                                const GimpCoords bezier_pt4,
+                                gdouble           precision)
+{
+  GimpCoords pt1, pt2;
+
+  /* calculate the "ideal" positions for the control points */
+
+  gimp_coords_mix (2.0 / 3.0, &bezier_pt1,
+                   1.0 / 3.0, &bezier_pt4,
+                   &pt1);
+  gimp_coords_mix (1.0 / 3.0, &bezier_pt1,
+                   2.0 / 3.0, &bezier_pt4,
+                   &pt2);
+
+  /* calculate the deviation of the actual control points */
+
+  return (gimp_coords_manhattan_dist (&bezier_pt2, &pt1) < precision &&
+          gimp_coords_manhattan_dist (&bezier_pt3, &pt2) < precision);
+}

Added: trunk/app/core/gimpcoords-interpolate.h
==============================================================================
--- (empty file)
+++ trunk/app/core/gimpcoords-interpolate.h	Sat Oct 18 18:46:15 2008
@@ -0,0 +1,38 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpcoords-interpolate.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GIMP_COORDS_INTERPOLATE_H__
+#define __GIMP_COORDS_INTERPOLATE_H__
+
+void      gimp_coords_interpolate_bezier (const GimpCoords bezier_pt1,
+                                          const GimpCoords bezier_pt2,
+                                          const GimpCoords bezier_pt3,
+                                          const GimpCoords bezier_pt4,
+                                          gdouble          precision,
+                                          GArray           **ret_coords,
+                                          GArray           **ret_params);
+
+gboolean  gimp_coords_bezier_is_straight (const GimpCoords bezier_pt1,
+                                          const GimpCoords bezier_pt2,
+                                          const GimpCoords bezier_pt3,
+                                          const GimpCoords bezier_pt4,
+                                          gdouble           precision);
+
+#endif /* __GIMP_COORDS_INTERPOLATE_H__ */

Modified: trunk/app/vectors/gimpbezierstroke.c
==============================================================================
--- trunk/app/vectors/gimpbezierstroke.c	(original)
+++ trunk/app/vectors/gimpbezierstroke.c	Sat Oct 18 18:46:15 2008
@@ -29,6 +29,7 @@
 #include "vectors-types.h"
 
 #include "core/gimpcoords.h"
+#include "core/gimpcoords-interpolate.h"
 
 #include "gimpanchor.h"
 #include "gimpbezierstroke.h"
@@ -140,22 +141,6 @@
 static GList * gimp_bezier_stroke_get_anchor_listitem
                                            (GList                 *list);
 
-static void gimp_bezier_coords_subdivide   (const GimpCoords      *beziercoords,
-                                            const gdouble          precision,
-                                            GArray               **ret_coords,
-                                            GArray               **ret_params);
-static void gimp_bezier_coords_subdivide2  (const GimpCoords      *beziercoords,
-                                            const gdouble          start_t,
-                                            const gdouble          end_t,
-                                            const gdouble          precision,
-                                            GArray               **ret_coords,
-                                            GArray               **ret_params,
-                                            gint                   depth);
-
-static gboolean gimp_bezier_coords_is_straight
-                                           (const GimpCoords      *beziercoords,
-                                            const gdouble          precision);
-
 
 G_DEFINE_TYPE (GimpBezierStroke, gimp_bezier_stroke, GIMP_TYPE_STROKE)
 
@@ -691,7 +676,11 @@
   gimp_coords_difference (&beziercoords[1], &beziercoords[0], &point1);
   gimp_coords_difference (&beziercoords[3], &beziercoords[2], &point2);
 
-  if (!depth || (gimp_bezier_coords_is_straight (beziercoords, precision)
+  if (!depth || (gimp_coords_bezier_is_straight (beziercoords[0],
+                                                 beziercoords[1],
+                                                 beziercoords[2],
+                                                 beziercoords[3],
+                                                 precision)
                  && gimp_coords_length_squared (&point1) < precision
                  && gimp_coords_length_squared (&point2) < precision))
     {
@@ -924,8 +913,12 @@
   g_printerr ("(%.2f, %.2f)-(%.2f,%.2f): ", coord1->x, coord1->y,
               coord2->x, coord2->y);
 
-  gimp_bezier_coords_subdivide (beziercoords, precision,
-                                &ret_coords, &ret_params);
+  gimp_coords_interpolate_bezier (beziercoords[0],
+                                  beziercoords[1],
+                                  beziercoords[2],
+                                  beziercoords[3],
+                                  precision,
+                                  &ret_coords, &ret_params);
 
   g_return_val_if_fail (ret_coords->len == ret_params->len, -1.0);
 
@@ -1591,8 +1584,12 @@
 
       if (count == 4)
         {
-          gimp_bezier_coords_subdivide (segmentcoords, precision,
-                                        &ret_coords, NULL);
+          gimp_coords_interpolate_bezier (segmentcoords[0],
+                                          segmentcoords[1],
+                                          segmentcoords[2],
+                                          segmentcoords[3],
+                                          precision,
+                                          &ret_coords, NULL);
           segmentcoords[0] = segmentcoords[3];
           count = 1;
           need_endpoint = TRUE;
@@ -1612,8 +1609,12 @@
       if (anchorlist)
         segmentcoords[3] = GIMP_ANCHOR (anchorlist->data)->position;
 
-      gimp_bezier_coords_subdivide (segmentcoords, precision,
-                                    &ret_coords, NULL);
+      gimp_coords_interpolate_bezier (segmentcoords[0],
+                                      segmentcoords[1],
+                                      segmentcoords[2],
+                                      segmentcoords[3],
+                                      precision,
+                                      &ret_coords, NULL);
       need_endpoint = TRUE;
 
     }
@@ -2110,149 +2111,3 @@
 
   return NULL;
 }
-
-
-/*
- * a helper function that determines if a bezier segment is "straight
- * enough" to be approximated by a line.
- *
- * To be more exact, it also checks for the control points to be distributed
- * evenly along the line. This makes it easier to reconstruct parameters for
- * a given point along the segment.
- *
- * Needs four GimpCoords in an array.
- */
-
-static gboolean
-gimp_bezier_coords_is_straight (const GimpCoords *beziercoords,
-                                gdouble           precision)
-{
-  GimpCoords pt1, pt2;
-
-  /* calculate the "ideal" positions for the control points */
-
-  gimp_coords_mix (2.0 / 3.0, &(beziercoords[0]),
-                   1.0 / 3.0, &(beziercoords[3]),
-                   &pt1);
-  gimp_coords_mix (1.0 / 3.0, &(beziercoords[0]),
-                   2.0 / 3.0, &(beziercoords[3]),
-                   &pt2);
-
-  /* calculate the deviation of the actual control points */
-
-  return (gimp_coords_manhattan_dist (&(beziercoords[1]), &pt1) < precision &&
-          gimp_coords_manhattan_dist (&(beziercoords[2]), &pt2) < precision);
-}
-
-
-/* local helper functions for bezier subdivision */
-
-static void
-gimp_bezier_coords_subdivide (const GimpCoords  *beziercoords,
-                              const gdouble      precision,
-                              GArray           **ret_coords,
-                              GArray           **ret_params)
-{
-  gimp_bezier_coords_subdivide2 (beziercoords, 0.0, 1.0,
-                                 precision, ret_coords, ret_params, 10);
-}
-
-
-static void
-gimp_bezier_coords_subdivide2 (const GimpCoords *beziercoords,
-                               const gdouble     start_t,
-                               const gdouble     end_t,
-                               const gdouble     precision,
-                               GArray          **ret_coords,
-                               GArray          **ret_params,
-                               gint              depth)
-{
-  /*
-   * beziercoords has to contain four GimpCoords with the four control points
-   * of the bezier segment. We subdivide it at the parameter 0.5.
-   */
-
-  GimpCoords subdivided[8];
-  gdouble    middle_t = (start_t + end_t) / 2;
-
-  subdivided[0] = beziercoords[0];
-  subdivided[6] = beziercoords[3];
-
-  /* if (!depth) g_printerr ("Hit recursion depth limit!\n"); */
-
-  gimp_coords_average (&(beziercoords[0]), &(beziercoords[1]),
-                       &(subdivided[1]));
-
-  gimp_coords_average (&(beziercoords[1]), &(beziercoords[2]),
-                       &(subdivided[7]));
-
-  gimp_coords_average (&(beziercoords[2]), &(beziercoords[3]),
-                       &(subdivided[5]));
-
-  gimp_coords_average (&(subdivided[1]), &(subdivided[7]),
-                       &(subdivided[2]));
-
-  gimp_coords_average (&(subdivided[7]), &(subdivided[5]),
-                       &(subdivided[4]));
-
-  gimp_coords_average (&(subdivided[2]), &(subdivided[4]),
-                       &(subdivided[3]));
-
-  /*
-   * We now have the coordinates of the two bezier segments in
-   * subdivided [0-3] and subdivided [3-6]
-   */
-
-  /*
-   * Here we need to check, if we have sufficiently subdivided, i.e.
-   * if the stroke is sufficiently close to a straight line.
-   */
-
-  if (!depth || gimp_bezier_coords_is_straight (&(subdivided[0]),
-                                                precision)) /* 1st half */
-    {
-      *ret_coords = g_array_append_vals (*ret_coords, &(subdivided[0]), 3);
-
-      if (ret_params)
-        {
-          gdouble params[3];
-
-          params[0] = start_t;
-          params[1] = (2 * start_t + middle_t) / 3;
-          params[2] = (start_t + 2 * middle_t) / 3;
-
-          *ret_params = g_array_append_vals (*ret_params, &(params[0]), 3);
-        }
-    }
-  else
-    {
-      gimp_bezier_coords_subdivide2 (&(subdivided[0]),
-                                     start_t, (start_t + end_t) / 2,
-                                     precision,
-                                     ret_coords, ret_params, depth-1);
-    }
-
-  if (!depth || gimp_bezier_coords_is_straight (&(subdivided[3]),
-                                                precision)) /* 2nd half */
-    {
-      *ret_coords = g_array_append_vals (*ret_coords, &(subdivided[3]), 3);
-
-      if (ret_params)
-        {
-          gdouble params[3];
-
-          params[0] = middle_t;
-          params[1] = (2 * middle_t + end_t) / 3;
-          params[2] = (middle_t + 2 * end_t) / 3;
-
-          *ret_params = g_array_append_vals (*ret_params, &(params[0]), 3);
-        }
-    }
-  else
-    {
-      gimp_bezier_coords_subdivide2 (&(subdivided[3]),
-                                     (start_t + end_t) / 2, end_t,
-                                     precision,
-                                     ret_coords, ret_params, depth-1);
-    }
-}



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