[gimp] app: refactor GimpCanvasTransformPreview to not know GimpTransformTool any more



commit 8a09fd1f342f6c5cf8cded6e580b3abc016894b4
Author: Michael Natterer <mitch gimp org>
Date:   Sun Mar 27 21:19:38 2011 +0200

    app: refactor GimpCanvasTransformPreview to not know GimpTransformTool any more
    
    Instead, add drawable, transform, x1, y1 etc. properties. This is
    cleaner and has the nice side effect of not leaving artifacts, because
    the changed state of the transform tool doesn't affect the extents
    calculation any longer.

 app/display/gimpcanvastransformpreview.c |  308 ++++++++++++++++++++++--------
 app/display/gimpcanvastransformpreview.h |    8 +-
 app/tools/gimptransformtool.c            |    9 +-
 3 files changed, 245 insertions(+), 80 deletions(-)
---
diff --git a/app/display/gimpcanvastransformpreview.c b/app/display/gimpcanvastransformpreview.c
index bb70fd3..2a9d9d5 100644
--- a/app/display/gimpcanvastransformpreview.c
+++ b/app/display/gimpcanvastransformpreview.c
@@ -23,18 +23,17 @@
 #include <gegl.h>
 #include <gtk/gtk.h>
 
+#include "libgimpbase/gimpbase.h"
 #include "libgimpmath/gimpmath.h"
 #include "libgimpwidgets/gimpwidgets.h"
 
-#include "tools/tools-types.h" /* eek */
+#include "display/display-types.h"
 
 #include "base/tile-manager.h"
 
 #include "core/gimpchannel.h"
 #include "core/gimpimage.h"
 
-#include "tools/gimpperspectivetool.h"
-
 #include "gimpcanvas.h"
 #include "gimpcanvastransformpreview.h"
 #include "gimpdisplayshell.h"
@@ -55,7 +54,13 @@
 enum
 {
   PROP_0,
-  PROP_TRANSFORM_TOOL,
+  PROP_DRAWABLE,
+  PROP_TRANSFORM,
+  PROP_X1,
+  PROP_Y1,
+  PROP_X2,
+  PROP_Y2,
+  PROP_PERSPECTIVE,
   PROP_OPACITY
 };
 
@@ -64,7 +69,11 @@ typedef struct _GimpCanvasTransformPreviewPrivate GimpCanvasTransformPreviewPriv
 
 struct _GimpCanvasTransformPreviewPrivate
 {
-  GimpTransformTool *transform_tool;
+  GimpDrawable      *drawable;
+  GimpMatrix3        transform;
+  gdouble            x1, y1;
+  gdouble            x2, y2;
+  gboolean           perspective;
   gdouble            opacity;
 };
 
@@ -168,12 +177,56 @@ gimp_canvas_transform_preview_class_init (GimpCanvasTransformPreviewClass *klass
   item_class->draw           = gimp_canvas_transform_preview_draw;
   item_class->get_extents    = gimp_canvas_transform_preview_get_extents;
 
-  g_object_class_install_property (object_class, PROP_TRANSFORM_TOOL,
-                                   g_param_spec_object ("transform-tool",
+  g_object_class_install_property (object_class, PROP_DRAWABLE,
+                                   g_param_spec_object ("drawable",
+                                                        NULL, NULL,
+                                                        GIMP_TYPE_DRAWABLE,
+                                                        GIMP_PARAM_READWRITE));
+
+  g_object_class_install_property (object_class, PROP_TRANSFORM,
+                                   gimp_param_spec_matrix3 ("transform",
+                                                            NULL, NULL,
+                                                            NULL,
+                                                            GIMP_PARAM_READWRITE));
+
+  g_object_class_install_property (object_class, PROP_X1,
+                                   g_param_spec_double ("x1",
+                                                        NULL, NULL,
+                                                        -GIMP_MAX_IMAGE_SIZE,
+                                                        GIMP_MAX_IMAGE_SIZE,
+                                                        0.0,
+                                                        GIMP_PARAM_READWRITE));
+
+  g_object_class_install_property (object_class, PROP_Y1,
+                                   g_param_spec_double ("y1",
                                                         NULL, NULL,
-                                                        GIMP_TYPE_TRANSFORM_TOOL,
+                                                        -GIMP_MAX_IMAGE_SIZE,
+                                                        GIMP_MAX_IMAGE_SIZE,
+                                                        0.0,
                                                         GIMP_PARAM_READWRITE));
 
+  g_object_class_install_property (object_class, PROP_X2,
+                                   g_param_spec_double ("x2",
+                                                        NULL, NULL,
+                                                        -GIMP_MAX_IMAGE_SIZE,
+                                                        GIMP_MAX_IMAGE_SIZE,
+                                                        0.0,
+                                                        GIMP_PARAM_READWRITE));
+
+  g_object_class_install_property (object_class, PROP_Y2,
+                                   g_param_spec_double ("y2",
+                                                        NULL, NULL,
+                                                        -GIMP_MAX_IMAGE_SIZE,
+                                                        GIMP_MAX_IMAGE_SIZE,
+                                                        0.0,
+                                                        GIMP_PARAM_READWRITE));
+
+  g_object_class_install_property (object_class, PROP_PERSPECTIVE,
+                                   g_param_spec_boolean ("perspective",
+                                                         NULL, NULL,
+                                                         FALSE,
+                                                         GIMP_PARAM_READWRITE));
+
   g_object_class_install_property (object_class, PROP_OPACITY,
                                    g_param_spec_double ("opacity",
                                                         NULL, NULL,
@@ -198,8 +251,39 @@ gimp_canvas_transform_preview_set_property (GObject      *object,
 
   switch (property_id)
     {
-    case PROP_TRANSFORM_TOOL:
-      private->transform_tool = g_value_get_object (value); /* don't ref */
+    case PROP_DRAWABLE:
+      private->drawable = g_value_get_object (value); /* don't ref */
+      break;
+
+    case PROP_TRANSFORM:
+      {
+        GimpMatrix3 *transform = g_value_get_boxed (value);
+
+        if (transform)
+          private->transform = *transform;
+        else
+          gimp_matrix3_identity (&private->transform);
+      }
+      break;
+
+    case PROP_X1:
+      private->x1 = g_value_get_double (value);
+      break;
+
+    case PROP_Y1:
+      private->y1 = g_value_get_double (value);
+      break;
+
+    case PROP_X2:
+      private->x2 = g_value_get_double (value);
+      break;
+
+    case PROP_Y2:
+      private->y2 = g_value_get_double (value);
+      break;
+
+    case PROP_PERSPECTIVE:
+      private->perspective = g_value_get_boolean (value);
       break;
 
     case PROP_OPACITY:
@@ -222,8 +306,32 @@ gimp_canvas_transform_preview_get_property (GObject    *object,
 
   switch (property_id)
     {
-    case PROP_TRANSFORM_TOOL:
-      g_value_set_object (value, private->transform_tool);
+    case PROP_DRAWABLE:
+      g_value_set_object (value, private->drawable);
+      break;
+
+    case PROP_TRANSFORM:
+      g_value_set_boxed (value, &private->transform);
+      break;
+
+    case PROP_PERSPECTIVE:
+      g_value_set_boolean (value, private->perspective);
+      break;
+
+    case PROP_X1:
+      g_value_set_double (value, private->x1);
+      break;
+
+    case PROP_Y1:
+      g_value_set_double (value, private->y1);
+      break;
+
+    case PROP_X2:
+      g_value_set_double (value, private->x2);
+      break;
+
+    case PROP_Y2:
+      g_value_set_double (value, private->y2);
       break;
 
     case PROP_OPACITY:
@@ -236,16 +344,82 @@ gimp_canvas_transform_preview_get_property (GObject    *object,
     }
 }
 
+static gboolean
+gimp_canvas_transform_preview_transform (GimpCanvasItem   *item,
+                                         GimpDisplayShell *shell,
+                                         GdkRectangle     *extents)
+{
+  GimpCanvasTransformPreviewPrivate *private = GET_PRIVATE (item);
+  gdouble                            tx1, ty1;
+  gdouble                            tx2, ty2;
+  gdouble                            tx3, ty3;
+  gdouble                            tx4, ty4;
+  gdouble                            z1, z2, z3, z4;
+
+  gimp_matrix3_transform_point (&private->transform,
+                                private->x1, private->y1,
+                                &tx1, &ty1);
+  gimp_matrix3_transform_point (&private->transform,
+                                private->x2, private->y1,
+                                &tx2, &ty2);
+  gimp_matrix3_transform_point (&private->transform,
+                                private->x1, private->y2,
+                                &tx3, &ty3);
+  gimp_matrix3_transform_point (&private->transform,
+                                private->x2, private->y2,
+                                &tx4, &ty4);
+
+  z1 = ((tx2 - tx1) * (ty4 - ty1) -
+        (tx4 - tx1) * (ty2 - ty1));
+  z2 = ((tx4 - tx1) * (ty3 - ty1) -
+        (tx3 - tx1) * (ty4 - ty1));
+  z3 = ((tx4 - tx2) * (ty3 - ty2) -
+        (tx3 - tx2) * (ty4 - ty2));
+  z4 = ((tx3 - tx2) * (ty1 - ty2) -
+        (tx1 - tx2) * (ty3 - ty2));
+
+  if (! ((z1 * z2 > 0) && (z3 * z4 > 0)))
+    return FALSE;
+
+  if (extents)
+    {
+      gdouble dx1, dy1;
+      gdouble dx2, dy2;
+      gdouble dx3, dy3;
+      gdouble dx4, dy4;
+
+      gimp_display_shell_transform_xy_f (shell,
+                                         tx1, ty1,
+                                         &dx1, &dy1);
+      gimp_display_shell_transform_xy_f (shell,
+                                         tx2, ty2,
+                                         &dx2, &dy2);
+      gimp_display_shell_transform_xy_f (shell,
+                                         tx3, ty3,
+                                         &dx3, &dy3);
+      gimp_display_shell_transform_xy_f (shell,
+                                         tx4, ty4,
+                                         &dx4, &dy4);
+
+      extents->x      = (gint) floor (MIN4 (dx1, dx2, dx3, dx4));
+      extents->y      = (gint) floor (MIN4 (dy1, dy2, dy3, dy4));
+      extents->width  = (gint) ceil (MAX4 (dx1, dx2, dx3, dx4));
+      extents->height = (gint) ceil (MAX4 (dy1, dy2, dy3, dy4));
+
+      extents->width  -= extents->x;
+      extents->height -= extents->y;
+    }
+
+  return TRUE;
+}
+
 static void
 gimp_canvas_transform_preview_draw (GimpCanvasItem   *item,
                                     GimpDisplayShell *shell,
                                     cairo_t          *cr)
 {
   GimpCanvasTransformPreviewPrivate *private = GET_PRIVATE (item);
-  GimpTransformTool                 *tr_tool;
-  GimpDrawable                      *drawable;
   GimpChannel                       *mask;
-  gdouble                            z1, z2, z3, z4;
   gint                               mask_x1, mask_y1;
   gint                               mask_x2, mask_y2;
   gint                               mask_offx, mask_offy;
@@ -263,38 +437,29 @@ gimp_canvas_transform_preview_draw (GimpCanvasItem   *item,
   gfloat                             v[MAX_SUB_COLS * MAX_SUB_ROWS][4];
   guchar                             opacity;
 
-  tr_tool = private->transform_tool;
   opacity = private->opacity * 255.999;
 
-  z1 = ((tr_tool->tx2 - tr_tool->tx1) * (tr_tool->ty4 - tr_tool->ty1) -
-        (tr_tool->tx4 - tr_tool->tx1) * (tr_tool->ty2 - tr_tool->ty1));
-  z2 = ((tr_tool->tx4 - tr_tool->tx1) * (tr_tool->ty3 - tr_tool->ty1) -
-        (tr_tool->tx3 - tr_tool->tx1) * (tr_tool->ty4 - tr_tool->ty1));
-  z3 = ((tr_tool->tx4 - tr_tool->tx2) * (tr_tool->ty3 - tr_tool->ty2) -
-        (tr_tool->tx3 - tr_tool->tx2) * (tr_tool->ty4 - tr_tool->ty2));
-  z4 = ((tr_tool->tx3 - tr_tool->tx2) * (tr_tool->ty1 - tr_tool->ty2) -
-        (tr_tool->tx1 - tr_tool->tx2) * (tr_tool->ty3 - tr_tool->ty2));
-
   /* only draw convex polygons */
-
-  if (! ((z1 * z2 > 0) && (z3 * z4 > 0)))
+  if (! gimp_canvas_transform_preview_transform (item, shell, NULL))
     return;
 
-  mask = NULL;
-  mask_offx = mask_offy = 0;
+  mask      = NULL;
+  mask_offx = 0;
+  mask_offy = 0;
 
-  drawable = GIMP_TOOL (tr_tool)->drawable;
-
-  if (gimp_item_mask_bounds (GIMP_ITEM (drawable),
+  if (gimp_item_mask_bounds (GIMP_ITEM (private->drawable),
                              &mask_x1, &mask_y1,
                              &mask_x2, &mask_y2))
     {
-      mask = gimp_image_get_mask (gimp_item_get_image (GIMP_ITEM (drawable)));
+      GimpImage *image = gimp_item_get_image (GIMP_ITEM (private->drawable));
+
+      mask = gimp_image_get_mask (image);
 
-      gimp_item_get_offset (GIMP_ITEM (drawable), &mask_offx, &mask_offy);
+      gimp_item_get_offset (GIMP_ITEM (private->drawable),
+                            &mask_offx, &mask_offy);
     }
 
-  if (GIMP_IS_PERSPECTIVE_TOOL (tr_tool))
+  if (private->perspective)
     {
       /* approximate perspective transform by subdivision
        *
@@ -311,8 +476,8 @@ gimp_canvas_transform_preview_draw (GimpCanvasItem   *item,
       rows    = 1;
     }
 
-  dx = (tr_tool->x2 - tr_tool->x1) / ((gfloat) columns);
-  dy = (tr_tool->y2 - tr_tool->y1) / ((gfloat) rows);
+  dx = (private->x2 - private->x1) / ((gfloat) columns);
+  dy = (private->y2 - private->y1) / ((gfloat) rows);
 
   du = (mask_x2 - mask_x1) / ((gfloat) columns);
   dv = (mask_y2 - mask_y1) / ((gfloat) rows);
@@ -322,10 +487,10 @@ gimp_canvas_transform_preview_draw (GimpCanvasItem   *item,
     gdouble tx1, ty1;                                           \
     gdouble tx2, ty2;                                           \
                                                                 \
-    u[sub][index] = tr_tool->x1 + (dx * (col + (index & 1)));   \
-    v[sub][index] = tr_tool->y1 + (dy * (row + (index >> 1)));  \
+    u[sub][index] = private->x1 + (dx * (col + (index & 1)));   \
+    v[sub][index] = private->y1 + (dy * (row + (index >> 1)));  \
                                                                 \
-    gimp_matrix3_transform_point (&tr_tool->transform,          \
+    gimp_matrix3_transform_point (&private->transform,          \
                                   u[sub][index], v[sub][index], \
                                   &tx1, &ty1);                  \
                                                                 \
@@ -400,7 +565,7 @@ gimp_canvas_transform_preview_draw (GimpCanvasItem   *item,
 
   k = columns * rows;
   for (j = 0; j < k; j++)
-    gimp_canvas_transform_preview_draw_quad (drawable, cr,
+    gimp_canvas_transform_preview_draw_quad (private->drawable, cr,
                                              mask, mask_offx, mask_offy,
                                              x[j], y[j], u[j], v[j],
                                              opacity);
@@ -410,52 +575,39 @@ static cairo_region_t *
 gimp_canvas_transform_preview_get_extents (GimpCanvasItem   *item,
                                            GimpDisplayShell *shell)
 {
-  GimpCanvasTransformPreviewPrivate *private = GET_PRIVATE (item);
-  GimpTransformTool                 *tr_tool;
-  gdouble                            dx1, dy1;
-  gdouble                            dx2, dy2;
-  gdouble                            dx3, dy3;
-  gdouble                            dx4, dy4;
-  GdkRectangle                       rectangle;
-
-  tr_tool = private->transform_tool;
-
-  gimp_display_shell_transform_xy_f (shell,
-                                     tr_tool->tx1, tr_tool->ty1,
-                                     &dx1, &dy1);
-  gimp_display_shell_transform_xy_f (shell,
-                                     tr_tool->tx2, tr_tool->ty2,
-                                     &dx2, &dy2);
-  gimp_display_shell_transform_xy_f (shell,
-                                     tr_tool->tx3, tr_tool->ty3,
-                                     &dx3, &dy3);
-  gimp_display_shell_transform_xy_f (shell,
-                                     tr_tool->tx4, tr_tool->ty4,
-                                     &dx4, &dy4);
-
-  rectangle.x      = (gint) floor (MIN4 (dx1, dx2, dx3, dx4));
-  rectangle.y      = (gint) floor (MIN4 (dy1, dy2, dy3, dy4));
-  rectangle.width  = (gint) ceil (MAX4 (dx1, dx2, dx3, dx4));
-  rectangle.height = (gint) ceil (MAX4 (dy1, dy2, dy3, dy4));
-
-  rectangle.width  -= rectangle.x;
-  rectangle.height -= rectangle.y;
-
-  return cairo_region_create_rectangle ((cairo_rectangle_int_t *) &rectangle);
+  GdkRectangle rectangle;
+
+  if (gimp_canvas_transform_preview_transform (item, shell, &rectangle))
+    return cairo_region_create_rectangle ((cairo_rectangle_int_t *) &rectangle);
+
+  return NULL;
 }
 
 GimpCanvasItem *
 gimp_canvas_transform_preview_new (GimpDisplayShell  *shell,
-                                   GimpTransformTool *transform_tool,
+                                   GimpDrawable      *drawable,
+                                   const GimpMatrix3 *transform,
+                                   gdouble            x1,
+                                   gdouble            y1,
+                                   gdouble            x2,
+                                   gdouble            y2,
+                                   gboolean           perspective,
                                    gdouble            opacity)
 {
   g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), NULL);
-  g_return_val_if_fail (GIMP_IS_TRANSFORM_TOOL (transform_tool), NULL);
+  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
+  g_return_val_if_fail (transform != NULL, NULL);
 
   return g_object_new (GIMP_TYPE_CANVAS_TRANSFORM_PREVIEW,
-                       "shell",          shell,
-                       "transform-tool", transform_tool,
-                       "opacity",        CLAMP (opacity, 0.0, 1.0),
+                       "shell",       shell,
+                       "drawable",    drawable,
+                       "transform",   transform,
+                       "x1",          x1,
+                       "y1",          y1,
+                       "x2",          x2,
+                       "y2",          y2,
+                       "perspective", perspective,
+                       "opacity",     CLAMP (opacity, 0.0, 1.0),
                        NULL);
 }
 
diff --git a/app/display/gimpcanvastransformpreview.h b/app/display/gimpcanvastransformpreview.h
index f03cca7..e49e0f9 100644
--- a/app/display/gimpcanvastransformpreview.h
+++ b/app/display/gimpcanvastransformpreview.h
@@ -50,7 +50,13 @@ struct _GimpCanvasTransformPreviewClass
 GType            gimp_canvas_transform_preview_get_type (void) G_GNUC_CONST;
 
 GimpCanvasItem * gimp_canvas_transform_preview_new      (GimpDisplayShell  *shell,
-                                                         GimpTransformTool *transform_tool,
+                                                         GimpDrawable      *drawable,
+                                                         const GimpMatrix3 *transform,
+                                                         gdouble            x1,
+                                                         gdouble            y1,
+                                                         gdouble            x2,
+                                                         gdouble            y2,
+                                                         gboolean           perspective,
                                                          gdouble            opacity);
 
 
diff --git a/app/tools/gimptransformtool.c b/app/tools/gimptransformtool.c
index 81d339d..5c8f2f1 100644
--- a/app/tools/gimptransformtool.c
+++ b/app/tools/gimptransformtool.c
@@ -58,6 +58,7 @@
 #include "display/gimptooldialog.h"
 
 #include "gimptoolcontrol.h"
+#include "gimpperspectivetool.h"
 #include "gimptransformoptions.h"
 #include "gimptransformtool.h"
 #include "gimptransformtoolundo.h"
@@ -759,7 +760,13 @@ gimp_transform_tool_draw (GimpDrawTool *draw_tool)
       GimpCanvasItem *item;
 
       item = gimp_canvas_transform_preview_new (gimp_display_get_shell (draw_tool->display),
-                                                tr_tool,
+                                                tool->drawable,
+                                                &tr_tool->transform,
+                                                tr_tool->x1,
+                                                tr_tool->y1,
+                                                tr_tool->x2,
+                                                tr_tool->y2,
+                                                GIMP_IS_PERSPECTIVE_TOOL (tr_tool),
                                                 options->preview_opacity);
       gimp_draw_tool_add_item (draw_tool, item);
       g_object_unref (item);



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