[gimp] app: implement gimp_brush_transform_boundary()



commit cf52b10e9bb9faaf1238e545a7a8c725fdea1ffd
Author: Michael Natterer <mitch gimp org>
Date:   Mon Apr 4 21:11:39 2011 +0200

    app: implement gimp_brush_transform_boundary()
    
    There is infinite room for optimization, but the API and pixel-perfect
    functionality is there, which is step one.

 app/core/Makefile.am          |    2 +
 app/core/gimpbrush-boundary.c |  204 +++++++++++++++++++++++++++++++++++++++++
 app/core/gimpbrush-boundary.h |   31 ++++++
 app/core/gimpbrush.c          |   14 +++-
 app/core/gimpbrush.h          |    8 +-
 5 files changed, 255 insertions(+), 4 deletions(-)
---
diff --git a/app/core/Makefile.am b/app/core/Makefile.am
index bded865..3e5632b 100644
--- a/app/core/Makefile.am
+++ b/app/core/Makefile.am
@@ -55,6 +55,8 @@ libappcore_a_sources = \
 	gimpbezierdesc.c			\
 	gimpbrush.c				\
 	gimpbrush.h				\
+	gimpbrush-boundary.c			\
+	gimpbrush-boundary.h			\
 	gimpbrush-header.h			\
 	gimpbrush-load.c			\
 	gimpbrush-load.h			\
diff --git a/app/core/gimpbrush-boundary.c b/app/core/gimpbrush-boundary.c
new file mode 100644
index 0000000..0adbcac
--- /dev/null
+++ b/app/core/gimpbrush-boundary.c
@@ -0,0 +1,204 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <cairo.h>
+
+#include "core-types.h"
+
+#include "base/boundary.h"
+#include "base/pixel-region.h"
+#include "base/temp-buf.h"
+
+#include "gimpbezierdesc.h"
+#include "gimpbrush.h"
+#include "gimpbrush-boundary.h"
+
+
+static void
+add_polyline (GArray            *path_data,
+              const GimpVector2 *points,
+              guint              n_points)
+{
+  GimpVector2       prev = { 0.0, 0.0, };
+  cairo_path_data_t pd;
+  gint              i;
+
+  for (i = 0; i < n_points; i++)
+    {
+      /* compress multiple identical coordinates */
+      if (i == 0 ||
+          prev.x != points[i].x ||
+          prev.y != points[i].y)
+        {
+          pd.header.type   = (i == 0) ? CAIRO_PATH_MOVE_TO : CAIRO_PATH_LINE_TO;
+          pd.header.length = 2;
+
+          g_array_append_val (path_data, pd);
+
+          pd.point.x = points[i].x;
+          pd.point.y = points[i].y;
+
+          g_array_append_val (path_data, pd);
+
+          prev = points[i];
+        }
+    }
+
+  /* close the polyline */
+  pd.header.type   = CAIRO_PATH_CLOSE_PATH;
+  pd.header.length = 1;
+
+  g_array_append_val (path_data, pd);
+}
+
+static GimpBezierDesc *
+gimp_brush_transform_boundary_exact (GimpBrush *brush,
+                                     gdouble    scale,
+                                     gdouble    aspect_ratio,
+                                     gdouble    angle,
+                                     gdouble    hardness)
+{
+  TempBuf *mask;
+
+  mask = gimp_brush_transform_mask (brush,
+                                    scale, aspect_ratio, angle, hardness);
+
+  if (mask)
+    {
+      PixelRegion   maskPR;
+      BoundSeg     *bound_segs;
+      gint          n_bound_segs;
+      BoundSeg     *stroke_segs;
+      gint          n_stroke_segs;
+      GArray       *path_data;
+
+      pixel_region_init_temp_buf (&maskPR, mask,
+                                  0, 0, mask->width, mask->height);
+
+      bound_segs = boundary_find (&maskPR, BOUNDARY_WITHIN_BOUNDS,
+                                  0, 0, maskPR.w, maskPR.h,
+                                  0,
+                                  &n_bound_segs);
+
+      temp_buf_free (mask);
+
+      if (! bound_segs)
+        return NULL;
+
+      stroke_segs = boundary_sort (bound_segs, n_bound_segs, &n_stroke_segs);
+
+      g_free (bound_segs);
+
+      if (! stroke_segs)
+        return NULL;
+
+      path_data = g_array_new (FALSE, FALSE, sizeof (cairo_path_data_t));
+
+      {
+        GimpVector2 *points;
+        gint         n_points;
+        gint         seg;
+        gint         i;
+
+        points = g_new0 (GimpVector2, n_bound_segs + 4);
+
+        seg = 0;
+        n_points = 0;
+
+        points[n_points].x = (gdouble) (stroke_segs[0].x1);
+        points[n_points].y = (gdouble) (stroke_segs[0].y1);
+
+        n_points++;
+
+        for (i = 0; i < n_stroke_segs; i++)
+          {
+            while (stroke_segs[seg].x1 != -1 ||
+                   stroke_segs[seg].x2 != -1 ||
+                   stroke_segs[seg].y1 != -1 ||
+                   stroke_segs[seg].y2 != -1)
+              {
+                points[n_points].x = (gdouble) (stroke_segs[seg].x1);
+                points[n_points].y = (gdouble) (stroke_segs[seg].y1);
+
+                n_points++;
+                seg++;
+              }
+
+            /* Close the stroke points up */
+            points[n_points] = points[0];
+
+            n_points++;
+
+            add_polyline (path_data, points, n_points);
+
+            n_points = 0;
+            seg++;
+
+            points[n_points].x = (gdouble) (stroke_segs[seg].x1);
+            points[n_points].y = (gdouble) (stroke_segs[seg].y1);
+
+            n_points++;
+          }
+
+        g_free (points);
+      }
+
+      g_free (stroke_segs);
+
+      return gimp_bezier_desc_new ((cairo_path_data_t *) g_array_free (path_data, FALSE),
+                                   path_data->len);
+    }
+
+  return NULL;
+}
+
+static GimpBezierDesc *
+gimp_brush_transform_boundary_approx (GimpBrush *brush,
+                                      gdouble    scale,
+                                      gdouble    aspect_ratio,
+                                      gdouble    angle,
+                                      gdouble    hardness)
+{
+  return NULL;
+}
+
+GimpBezierDesc *
+gimp_brush_real_transform_boundary (GimpBrush *brush,
+                                    gdouble    scale,
+                                    gdouble    aspect_ratio,
+                                    gdouble    angle,
+                                    gdouble    hardness,
+                                    gint      *width,
+                                    gint      *height)
+{
+  gimp_brush_transform_size (brush, scale, aspect_ratio, angle,
+                             width, height);
+
+  if (TRUE /* width < foo && height < bar */)
+    {
+      return gimp_brush_transform_boundary_exact (brush,
+                                                  scale, aspect_ratio,
+                                                  angle, hardness);
+    }
+
+  return gimp_brush_transform_boundary_approx (brush,
+                                               scale, aspect_ratio,
+                                               angle, hardness);
+}
diff --git a/app/core/gimpbrush-boundary.h b/app/core/gimpbrush-boundary.h
new file mode 100644
index 0000000..b276c83
--- /dev/null
+++ b/app/core/gimpbrush-boundary.h
@@ -0,0 +1,31 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_BRUSH_BOUNDARY_H__
+#define __GIMP_BRUSH_BOUNDARY_H__
+
+
+GimpBezierDesc * gimp_brush_real_transform_boundary (GimpBrush *brush,
+                                                     gdouble    scale,
+                                                     gdouble    aspect_ratio,
+                                                     gdouble    angle,
+                                                     gdouble    hardness,
+                                                     gint      *width,
+                                                     gint      *height);
+
+
+#endif /* __GIMP_BRUSH_BOUNDARY_H__ */
diff --git a/app/core/gimpbrush.c b/app/core/gimpbrush.c
index 5cb2b42..efb36d7 100644
--- a/app/core/gimpbrush.c
+++ b/app/core/gimpbrush.c
@@ -27,6 +27,7 @@
 #include "base/temp-buf.h"
 
 #include "gimpbrush.h"
+#include "gimpbrush-boundary.h"
 #include "gimpbrush-load.h"
 #include "gimpbrush-transform.h"
 #include "gimpbrushgenerated.h"
@@ -129,6 +130,7 @@ gimp_brush_class_init (GimpBrushClass *klass)
   klass->transform_size            = gimp_brush_real_transform_size;
   klass->transform_mask            = gimp_brush_real_transform_mask;
   klass->transform_pixmap          = gimp_brush_real_transform_pixmap;
+  klass->transform_boundary        = gimp_brush_real_transform_boundary;
   klass->spacing_changed           = NULL;
 
   g_object_class_install_property (object_class, PROP_SPACING,
@@ -536,11 +538,19 @@ gimp_brush_transform_boundary (GimpBrush *brush,
                                gdouble    scale,
                                gdouble    aspect_ratio,
                                gdouble    angle,
-                               gdouble    hardness)
+                               gdouble    hardness,
+                               gint      *width,
+                               gint      *height)
 {
   g_return_val_if_fail (GIMP_IS_BRUSH (brush), NULL);
+  g_return_val_if_fail (scale > 0.0, NULL);
+  g_return_val_if_fail (width != NULL, NULL);
+  g_return_val_if_fail (height != NULL, NULL);
 
-  return NULL;
+  return GIMP_BRUSH_GET_CLASS (brush)->transform_boundary (brush,
+                                                           scale, aspect_ratio,
+                                                           angle, hardness,
+                                                           width, height);
 }
 
 gdouble
diff --git a/app/core/gimpbrush.h b/app/core/gimpbrush.h
index 31fcfbb..99db5f5 100644
--- a/app/core/gimpbrush.h
+++ b/app/core/gimpbrush.h
@@ -76,7 +76,9 @@ struct _GimpBrushClass
                                            gdouble           scale,
                                            gdouble           aspect_ratio,
                                            gdouble           angle,
-                                           gdouble           hardness);
+                                           gdouble           hardness,
+                                           gint             *width,
+                                           gint             *height);
 
   /*  signals  */
   void             (* spacing_changed)    (GimpBrush        *brush);
@@ -119,7 +121,9 @@ GimpBezierDesc * gimp_brush_transform_boundary (GimpBrush        *brush,
                                                 gdouble           scale,
                                                 gdouble           aspect_ratio,
                                                 gdouble           angle,
-                                                gdouble           hardness);
+                                                gdouble           hardness,
+                                                gint             *width,
+                                                gint             *height);
 
 gdouble          gimp_brush_clamp_scale        (GimpBrush        *brush,
                                                 gdouble           scale);



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