[gimp] app: turn the transform preview into a GimpCanvasItem



commit f09be52c1b19188ef20170dd9c6cd927db94630b
Author: Michael Natterer <mitch gimp org>
Date:   Sun Mar 27 16:40:41 2011 +0200

    app: turn the transform preview into a GimpCanvasItem
    
    And remove all the complicated handling code entirely. This makes
    GimpTransformTool a lot less complex. As a nice side effect, the
    preview is now always 100% in sync with the grid and handles.

 app/display/Makefile.am                            |    4 +-
 ...hell-preview.c => gimpcanvastransformpreview.c} |  629 ++++++++++++--------
 app/display/gimpcanvastransformpreview.h           |   59 ++
 app/display/gimpdisplayshell-appearance.c          |   17 -
 app/display/gimpdisplayshell-appearance.h          |    4 -
 app/display/gimpdisplayshell-callbacks.c           |    6 -
 app/display/gimpdisplayshell-preview.h             |   26 -
 app/display/gimpdisplayshell.h                     |    1 -
 app/tools/gimprotatetool.c                         |    4 -
 app/tools/gimpscaletool.c                          |    2 -
 app/tools/gimpsheartool.c                          |    4 -
 app/tools/gimptransformtool.c                      |  206 +------
 app/tools/gimptransformtool.h                      |    7 +-
 13 files changed, 470 insertions(+), 499 deletions(-)
---
diff --git a/app/display/Makefile.am b/app/display/Makefile.am
index cbaa3da..5d8e3c7 100644
--- a/app/display/Makefile.am
+++ b/app/display/Makefile.am
@@ -61,6 +61,8 @@ libappdisplay_a_sources = \
 	gimpcanvassamplepoint.h			\
 	gimpcanvastextcursor.c			\
 	gimpcanvastextcursor.h			\
+	gimpcanvastransformpreview.c		\
+	gimpcanvastransformpreview.h		\
 	gimpcursorview.c			\
 	gimpcursorview.h			\
 	gimpdisplay.c				\
@@ -103,8 +105,6 @@ libappdisplay_a_sources = \
 	gimpdisplayshell-icon.h			\
 	gimpdisplayshell-items.c		\
 	gimpdisplayshell-items.h		\
-	gimpdisplayshell-preview.c		\
-	gimpdisplayshell-preview.h		\
 	gimpdisplayshell-progress.c		\
 	gimpdisplayshell-progress.h		\
 	gimpdisplayshell-render.c		\
diff --git a/app/display/gimpdisplayshell-preview.c b/app/display/gimpcanvastransformpreview.c
similarity index 53%
rename from app/display/gimpdisplayshell-preview.c
rename to app/display/gimpcanvastransformpreview.c
index d80bd14..8f0d6a4 100644
--- a/app/display/gimpdisplayshell-preview.c
+++ b/app/display/gimpcanvastransformpreview.c
@@ -1,6 +1,9 @@
 /* GIMP - The GNU Image Manipulation Program
  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  *
+ * gimpcanvastransformpreview.c
+ * Copyright (C) 2011 Michael Natterer <mitch gimp org>
+ *
  * 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
@@ -20,26 +23,20 @@
 #include <gegl.h>
 #include <gtk/gtk.h>
 
-#include "libgimpmath/gimpmath.h"
 #include "libgimpwidgets/gimpwidgets.h"
 
-#include "display-types.h"
-#include "tools/tools-types.h"
+#include "tools/tools-types.h" /* eek */
+
+#include "base/tile-manager.h"
 
 #include "core/gimpchannel.h"
-#include "core/gimpdrawable.h"
 #include "core/gimpimage.h"
 
-#include "base/tile-manager.h"
-
 #include "tools/gimpperspectivetool.h"
-#include "tools/gimptransformtool.h"
-#include "tools/tool_manager.h"
 
-#include "gimpdisplay.h"
+#include "gimpcanvas.h"
+#include "gimpcanvastransformpreview.h"
 #include "gimpdisplayshell.h"
-#include "gimpdisplayshell-appearance.h"
-#include "gimpdisplayshell-preview.h"
 #include "gimpdisplayshell-transform.h"
 
 
@@ -51,101 +48,208 @@
 #define MAX_SUB_COLS 6     /* number of columns and  */
 #define MAX_SUB_ROWS 6     /* rows to use in perspective preview subdivision */
 
+
+enum
+{
+  PROP_0,
+  PROP_TRANSFORM_TOOL,
+  PROP_OPACITY
+};
+
+
+typedef struct _GimpCanvasTransformPreviewPrivate GimpCanvasTransformPreviewPrivate;
+
+struct _GimpCanvasTransformPreviewPrivate
+{
+  GimpTransformTool *transform_tool;
+  gdouble            opacity;
+};
+
+#define GET_PRIVATE(transform_preview) \
+        G_TYPE_INSTANCE_GET_PRIVATE (transform_preview, \
+                                     GIMP_TYPE_CANVAS_TRANSFORM_PREVIEW, \
+                                     GimpCanvasTransformPreviewPrivate)
+
+
 /*  local function prototypes  */
 
-static void    gimp_display_shell_draw_quad          (GimpDrawable    *texture,
-                                                      cairo_t         *cr,
-                                                      GimpChannel     *mask,
-                                                      gint             mask_offx,
-                                                      gint             mask_offy,
-                                                      gint            *x,
-                                                      gint            *y,
-                                                      gfloat          *u,
-                                                      gfloat          *v,
-                                                      guchar           opacity);
-static void    gimp_display_shell_draw_tri           (GimpDrawable    *texture,
-                                                      cairo_t         *cr,
-                                                      cairo_surface_t *area,
-                                                      gint             area_offx,
-                                                      gint             area_offy,
-                                                      GimpChannel     *mask,
-                                                      gint             mask_offx,
-                                                      gint             mask_offy,
-                                                      gint            *x,
-                                                      gint            *y,
-                                                      gfloat          *u,
-                                                      gfloat          *v,
-                                                      guchar           opacity);
-static void    gimp_display_shell_draw_tri_row       (GimpDrawable    *texture,
-                                                      cairo_t         *cr,
-                                                      cairo_surface_t *area,
-                                                      gint             area_offx,
-                                                      gint             area_offy,
-                                                      gint             x1,
-                                                      gfloat           u1,
-                                                      gfloat           v1,
-                                                      gint             x2,
-                                                      gfloat           u2,
-                                                      gfloat           v2,
-                                                      gint             y,
-                                                      guchar           opacity);
-static void    gimp_display_shell_draw_tri_row_mask  (GimpDrawable    *texture,
-                                                      cairo_t         *cr,
-                                                      cairo_surface_t *area,
-                                                      gint             area_offx,
-                                                      gint             area_offy,
-                                                      GimpChannel     *mask,
-                                                      gint             mask_offx,
-                                                      gint             mask_offy,
-                                                      gint             x1,
-                                                      gfloat           u1,
-                                                      gfloat           v1,
-                                                      gint             x2,
-                                                      gfloat           u2,
-                                                      gfloat           v2,
-                                                      gint             y,
-                                                      guchar           opacity);
-static void    gimp_display_shell_trace_tri_edge     (gint            *dest,
-                                                      gint             x1,
-                                                      gint             y1,
-                                                      gint             x2,
-                                                      gint             y2);
-
-/*  public functions  */
+static void             gimp_canvas_transform_preview_set_property (GObject          *object,
+                                                                    guint             property_id,
+                                                                    const GValue     *value,
+                                                                    GParamSpec       *pspec);
+static void             gimp_canvas_transform_preview_get_property (GObject          *object,
+                                                                    guint             property_id,
+                                                                    GValue           *value,
+                                                                    GParamSpec       *pspec);
+static void             gimp_canvas_transform_preview_draw         (GimpCanvasItem   *item,
+                                                                    GimpDisplayShell *shell,
+                                                                    cairo_t          *cr);
+static cairo_region_t * gimp_canvas_transform_preview_get_extents  (GimpCanvasItem   *item,
+                                                                    GimpDisplayShell *shell);
 
-/**
- * gimp_display_shell_preview_transform:
- * @shell: the #GimpDisplayShell
- *
- * If the active tool as reported by tool_manager_get_active() is a
- * #GimpTransformTool and the tool has a valid drawable, and the tool
- * has use_grid true (which, incidentally, is not the same thing as
- * the preview type), and the area of the transformed preview is
- * convex, then proceed with drawing the preview.
- *
- * The preview area is divided into 1 or more quadrilaterals, and
- * drawn with gimp_display_shell_draw_quad(), which in turn breaks it
- * down into 2 triangles, and draws row by row. If the tool is the
- * Perspective tool, then more small quadrilaterals are used to
- * compensate for the little rectangles not being the same size. In
- * other words, all the transform tools are affine transformations
- * except perspective, so approximate it with a few subdivisions.
- **/
-void
-gimp_display_shell_preview_transform (GimpDisplayShell *shell,
-                                      cairo_t          *cr)
+
+/*  local function prototypes  */
+
+static void   gimp_canvas_transform_preview_draw_quad         (GimpDrawable    *texture,
+                                                               cairo_t         *cr,
+                                                               GimpChannel     *mask,
+                                                               gint             mask_offx,
+                                                               gint             mask_offy,
+                                                               gint            *x,
+                                                               gint            *y,
+                                                               gfloat          *u,
+                                                               gfloat          *v,
+                                                               guchar           opacity);
+static void   gimp_canvas_transform_preview_draw_tri          (GimpDrawable    *texture,
+                                                               cairo_t         *cr,
+                                                               cairo_surface_t *area,
+                                                               gint             area_offx,
+                                                               gint             area_offy,
+                                                               GimpChannel     *mask,
+                                                               gint             mask_offx,
+                                                               gint             mask_offy,
+                                                               gint            *x,
+                                                               gint            *y,
+                                                               gfloat          *u,
+                                                               gfloat          *v,
+                                                               guchar           opacity);
+static void   gimp_canvas_transform_preview_draw_tri_row      (GimpDrawable    *texture,
+                                                               cairo_t         *cr,
+                                                               cairo_surface_t *area,
+                                                               gint             area_offx,
+                                                               gint             area_offy,
+                                                               gint             x1,
+                                                               gfloat           u1,
+                                                               gfloat           v1,
+                                                               gint             x2,
+                                                               gfloat           u2,
+                                                               gfloat           v2,
+                                                               gint             y,
+                                                               guchar           opacity);
+static void   gimp_canvas_transform_preview_draw_tri_row_mask (GimpDrawable    *texture,
+                                                               cairo_t         *cr,
+                                                               cairo_surface_t *area,
+                                                               gint             area_offx,
+                                                               gint             area_offy,
+                                                               GimpChannel     *mask,
+                                                               gint             mask_offx,
+                                                               gint             mask_offy,
+                                                               gint             x1,
+                                                               gfloat           u1,
+                                                               gfloat           v1,
+                                                               gint             x2,
+                                                               gfloat           u2,
+                                                               gfloat           v2,
+                                                               gint             y,
+                                                               guchar           opacity);
+static void   gimp_canvas_transform_preview_trace_tri_edge    (gint            *dest,
+                                                               gint             x1,
+                                                               gint             y1,
+                                                               gint             x2,
+                                                               gint             y2);
+
+
+G_DEFINE_TYPE (GimpCanvasTransformPreview, gimp_canvas_transform_preview,
+               GIMP_TYPE_CANVAS_ITEM)
+
+#define parent_class gimp_canvas_transform_preview_parent_class
+
+
+static void
+gimp_canvas_transform_preview_class_init (GimpCanvasTransformPreviewClass *klass)
+{
+  GObjectClass        *object_class = G_OBJECT_CLASS (klass);
+  GimpCanvasItemClass *item_class   = GIMP_CANVAS_ITEM_CLASS (klass);
+
+  object_class->set_property = gimp_canvas_transform_preview_set_property;
+  object_class->get_property = gimp_canvas_transform_preview_get_property;
+
+  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",
+                                                        NULL, NULL,
+                                                        GIMP_TYPE_TRANSFORM_TOOL,
+                                                        GIMP_PARAM_READWRITE));
+
+  g_object_class_install_property (object_class, PROP_OPACITY,
+                                   g_param_spec_double ("opacity",
+                                                        NULL, NULL,
+                                                        0.0, 1.0, 1.0,
+                                                        GIMP_PARAM_READWRITE));
+
+  g_type_class_add_private (klass, sizeof (GimpCanvasTransformPreviewPrivate));
+}
+
+static void
+gimp_canvas_transform_preview_init (GimpCanvasTransformPreview *transform_preview)
+{
+}
+
+static void
+gimp_canvas_transform_preview_set_property (GObject      *object,
+                                            guint         property_id,
+                                            const GValue *value,
+                                            GParamSpec   *pspec)
+{
+  GimpCanvasTransformPreviewPrivate *private = GET_PRIVATE (object);
+
+  switch (property_id)
+    {
+    case PROP_TRANSFORM_TOOL:
+      private->transform_tool = g_value_get_object (value); /* don't ref */
+      break;
+    case PROP_OPACITY:
+      private->opacity = g_value_get_double (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gimp_canvas_transform_preview_get_property (GObject    *object,
+                                            guint       property_id,
+                                            GValue     *value,
+                                            GParamSpec *pspec)
 {
-  GimpTool          *tool;
-  GimpTransformTool *tr_tool;
-  gdouble            z1, z2, z3, z4;
+  GimpCanvasTransformPreviewPrivate *private = GET_PRIVATE (object);
 
-  GimpChannel *mask;
-  gint         mask_x1, mask_y1;
-  gint         mask_x2, mask_y2;
-  gint         mask_offx, mask_offy;
+  switch (property_id)
+    {
+    case PROP_TRANSFORM_TOOL:
+      g_value_set_object (value, private->transform_tool);
+      break;
+    case PROP_OPACITY:
+      g_value_set_double (value, private->opacity);
+      break;
 
-  gint         columns, rows;
-  gint         j, k, sub;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gimp_canvas_transform_preview_draw (GimpCanvasItem   *item,
+                                    GimpDisplayShell *shell,
+                                    cairo_t          *cr)
+{
+  GimpCanvasTransformPreviewPrivate *private = GET_PRIVATE (item);
+  GimpTransformTool                 *tr_tool;
+  gdouble                            z1, z2, z3, z4;
+
+  GimpDrawable *drawable;
+  GimpChannel  *mask;
+  gint          mask_x1, mask_y1;
+  gint          mask_x2, mask_y2;
+  gint          mask_offx, mask_offy;
+
+  gint          columns, rows;
+  gint          j, k, sub;
 
    /* x and y get filled with the screen coordinates of each corner of
     * each quadrilateral subdivision of the transformed area. u and v
@@ -158,22 +262,8 @@ gimp_display_shell_preview_transform (GimpDisplayShell *shell,
                v[MAX_SUB_COLS * MAX_SUB_ROWS][4];
   guchar       opacity = 255;
 
-  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
-  g_return_if_fail (cr != NULL);
-
-  if (! gimp_display_shell_get_show_transform (shell) || ! shell->canvas)
-    return;
-
-  tool = tool_manager_get_active (shell->display->gimp);
-
-  if (! GIMP_IS_TRANSFORM_TOOL (tool) ||
-      ! GIMP_IS_DRAWABLE (tool->drawable))
-    return;
-
-  tr_tool = GIMP_TRANSFORM_TOOL (tool);
-
-  if (! tr_tool->use_grid)
-    return;
+  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));
@@ -189,28 +279,18 @@ gimp_display_shell_preview_transform (GimpDisplayShell *shell,
   if (! ((z1 * z2 > 0) && (z3 * z4 > 0)))
     return;
 
-  /* take opacity from the tool options */
-  {
-    gdouble value;
-
-    g_object_get (gimp_tool_get_options (tool),
-                  "preview-opacity", &value,
-                  NULL);
-
-    opacity = value * 255.999;
-  }
-
   mask = NULL;
   mask_offx = mask_offy = 0;
 
-  if (gimp_item_mask_bounds (GIMP_ITEM (tool->drawable),
+  drawable = GIMP_TOOL (tr_tool)->drawable;
+
+  if (gimp_item_mask_bounds (GIMP_ITEM (drawable),
                              &mask_x1, &mask_y1,
                              &mask_x2, &mask_y2))
     {
-      mask = gimp_image_get_mask (gimp_display_get_image (shell->display));
+      mask = gimp_image_get_mask (gimp_item_get_image (GIMP_ITEM (drawable)));
 
-      gimp_item_get_offset (GIMP_ITEM (tool->drawable),
-                            &mask_offx, &mask_offy);
+      gimp_item_get_offset (GIMP_ITEM (drawable), &mask_offx, &mask_offy);
     }
 
   if (GIMP_IS_PERSPECTIVE_TOOL (tr_tool))
@@ -319,36 +399,95 @@ gimp_display_shell_preview_transform (GimpDisplayShell *shell,
 
   k = columns * rows;
   for (j = 0; j < k; j++)
-    gimp_display_shell_draw_quad (tool->drawable, cr,
-                                  mask, mask_offx, mask_offy,
-                                  x[j], y[j], u[j], v[j],
-                                  opacity);
+    gimp_canvas_transform_preview_draw_quad (drawable, cr,
+                                             mask, mask_offx, mask_offy,
+                                             x[j], y[j], u[j], v[j],
+                                             opacity);
+}
+
+static cairo_region_t *
+gimp_canvas_transform_preview_get_extents (GimpCanvasItem   *item,
+                                           GimpDisplayShell *shell)
+{
+  GimpCanvasTransformPreviewPrivate *private = GET_PRIVATE (item);
+  GimpTransformTool                 *tr_tool;
+  gdouble                            dx[4], dy[4];
+  GdkRectangle                       rectangle;
+  gint                               i;
+
+  tr_tool = private->transform_tool;
+
+  gimp_display_shell_transform_xy_f (shell, tr_tool->tx1, tr_tool->ty1,
+                                     dx + 0, dy + 0);
+  gimp_display_shell_transform_xy_f (shell, tr_tool->tx2, tr_tool->ty2,
+                                     dx + 1, dy + 1);
+  gimp_display_shell_transform_xy_f (shell, tr_tool->tx3, tr_tool->ty3,
+                                     dx + 2, dy + 2);
+  gimp_display_shell_transform_xy_f (shell, tr_tool->tx4, tr_tool->ty4,
+                                     dx + 3, dy + 3);
+
+  /* find bounding box around preview */
+  rectangle.x = rectangle.width  = (gint) dx[0];
+  rectangle.y = rectangle.height = (gint) dy[0];
+
+  for (i = 1; i < 4; i++)
+    {
+      if (dx[i] < rectangle.x)
+        rectangle.x = (gint) dx[i];
+      else if (dx[i] > rectangle.width)
+        rectangle.width = (gint) dx[i];
+
+      if (dy[i] < rectangle.y)
+        rectangle.y = (gint) dy[i];
+      else if (dy[i] > rectangle.height)
+        rectangle.height = (gint) dy[i];
+    }
+
+  rectangle.width  -= rectangle.x;
+  rectangle.height -= rectangle.y;
+
+  return cairo_region_create_rectangle ((cairo_rectangle_int_t *) &rectangle);
+}
+
+GimpCanvasItem *
+gimp_canvas_transform_preview_new (GimpDisplayShell  *shell,
+                                   GimpTransformTool *transform_tool,
+                                   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);
+
+  return g_object_new (GIMP_TYPE_CANVAS_TRANSFORM_PREVIEW,
+                       "shell",          shell,
+                       "transform-tool", transform_tool,
+                       "opacity",        CLAMP (opacity, 0.0, 1.0),
+                       NULL);
 }
 
 
 /*  private functions  */
 
 /**
- * gimp_display_shell_draw_quad:
+ * gimp_canvas_transform_preview_draw_quad:
  * @texture:   the #GimpDrawable to be previewed
  * @cr:        the #cairo_t to draw to
  * @mask:      a #GimpChannel
  * @opacity:   the opacity of the preview
  *
  * Take a quadrilateral, divide it into two triangles, and draw those
- * with gimp_display_shell_draw_tri().
+ * with gimp_canvas_transform_preview_draw_tri().
  **/
 static void
-gimp_display_shell_draw_quad (GimpDrawable *texture,
-                              cairo_t      *cr,
-                              GimpChannel  *mask,
-                              gint          mask_offx,
-                              gint          mask_offy,
-                              gint         *x,
-                              gint         *y,
-                              gfloat       *u,
-                              gfloat       *v,
-                              guchar        opacity)
+gimp_canvas_transform_preview_draw_quad (GimpDrawable *texture,
+                                         cairo_t      *cr,
+                                         GimpChannel  *mask,
+                                         gint          mask_offx,
+                                         gint          mask_offy,
+                                         gint         *x,
+                                         gint         *y,
+                                         gfloat       *u,
+                                         gfloat       *v,
+                                         guchar        opacity)
 {
   gint    x2[3], y2[3];
   gfloat  u2[3], v2[3];
@@ -393,19 +532,19 @@ gimp_display_shell_draw_quad (GimpDrawable *texture,
 
       g_return_if_fail (area != NULL);
 
-      gimp_display_shell_draw_tri (texture, cr, area, minx, miny,
-                                   mask, mask_offx, mask_offy,
-                                   x, y, u, v, opacity);
-      gimp_display_shell_draw_tri (texture, cr, area, minx, miny,
-                                   mask, mask_offx, mask_offy,
-                                   x2, y2, u2, v2, opacity);
+      gimp_canvas_transform_preview_draw_tri (texture, cr, area, minx, miny,
+                                              mask, mask_offx, mask_offy,
+                                              x, y, u, v, opacity);
+      gimp_canvas_transform_preview_draw_tri (texture, cr, area, minx, miny,
+                                              mask, mask_offx, mask_offy,
+                                              x2, y2, u2, v2, opacity);
 
       cairo_surface_destroy (area);
     }
 }
 
 /**
- * gimp_display_shell_draw_tri:
+ * gimp_canvas_transform_preview_draw_tri:
  * @texture:   the thing being transformed
  * @cr:        the #cairo_t to draw to
  * @area:      has prefetched pixel data of dest
@@ -414,24 +553,25 @@ gimp_display_shell_draw_quad (GimpDrawable *texture,
  * @x:         Array of the three x coords of triangle
  * @y:         Array of the three y coords of triangle
  *
- * This draws a triangle onto dest by breaking it down into pixel rows, and
- * then calling gimp_display_shell_draw_tri_row() and
- * gimp_display_shell_draw_tri_row_mask() to do the actual pixel changing.
+ * This draws a triangle onto dest by breaking it down into pixel
+ * rows, and then calling gimp_canvas_transform_preview_draw_tri_row()
+ * and gimp_canvas_transform_preview_draw_tri_row_mask() to do the
+ * actual pixel changing.
  **/
 static void
-gimp_display_shell_draw_tri (GimpDrawable    *texture,
-                             cairo_t         *cr,
-                             cairo_surface_t *area,
-                             gint             area_offx,
-                             gint             area_offy,
-                             GimpChannel     *mask,
-                             gint             mask_offx,
-                             gint             mask_offy,
-                             gint            *x,
-                             gint            *y,
-                             gfloat          *u, /* texture coords */
-                             gfloat          *v, /* 0.0 ... tex width, height */
-                             guchar           opacity)
+gimp_canvas_transform_preview_draw_tri (GimpDrawable    *texture,
+                                        cairo_t         *cr,
+                                        cairo_surface_t *area,
+                                        gint             area_offx,
+                                        gint             area_offy,
+                                        GimpChannel     *mask,
+                                        gint             mask_offx,
+                                        gint             mask_offy,
+                                        gint            *x,
+                                        gint            *y,
+                                        gfloat          *u, /* texture coords */
+                                        gfloat          *v, /* 0.0 ... tex width, height */
+                                        guchar           opacity)
 {
   gdouble      clip_x1, clip_y1, clip_x2, clip_y2;
   gint         j, k;
@@ -475,7 +615,7 @@ gimp_display_shell_draw_tri (GimpDrawable    *texture,
 
   /* draw the triangle */
 
-  gimp_display_shell_trace_tri_edge (l_edge, x[0], y[0], x[2], y[2]);
+  gimp_canvas_transform_preview_trace_tri_edge (l_edge, x[0], y[0], x[2], y[2]);
 
   left = l_edge;
   dul  = (u[2] - u[0]) / (y[2] - y[0]);
@@ -485,7 +625,7 @@ gimp_display_shell_draw_tri (GimpDrawable    *texture,
 
   if (y[0] != y[1])
     {
-      gimp_display_shell_trace_tri_edge (r_edge, x[0], y[0], x[1], y[1]);
+      gimp_canvas_transform_preview_trace_tri_edge (r_edge, x[0], y[0], x[1], y[1]);
 
       right = r_edge;
       dur   = (u[1] - u[0]) / (y[1] - y[0]);
@@ -497,13 +637,13 @@ gimp_display_shell_draw_tri (GimpDrawable    *texture,
         for (ry = y[0]; ry < y[1]; ry++)
           {
             if (ry >= clip_y1 && ry < clip_y2)
-              gimp_display_shell_draw_tri_row_mask (texture, cr,
-                                                    area, area_offx, area_offy,
-                                                    mask, mask_offx, mask_offy,
-                                                    *left, u_l, v_l,
-                                                    *right, u_r, v_r,
-                                                    ry,
-                                                    opacity);
+              gimp_canvas_transform_preview_draw_tri_row_mask (texture, cr,
+                                                               area, area_offx, area_offy,
+                                                               mask, mask_offx, mask_offy,
+                                                               *left, u_l, v_l,
+                                                               *right, u_r, v_r,
+                                                               ry,
+                                                               opacity);
             left ++;      right ++;
             u_l += dul;   v_l += dvl;
             u_r += dur;   v_r += dvr;
@@ -512,12 +652,12 @@ gimp_display_shell_draw_tri (GimpDrawable    *texture,
         for (ry = y[0]; ry < y[1]; ry++)
           {
             if (ry >= clip_y1 && ry < clip_y2)
-              gimp_display_shell_draw_tri_row (texture, cr,
-                                               area, area_offx, area_offy,
-                                               *left, u_l, v_l,
-                                               *right, u_r, v_r,
-                                               ry,
-                                               opacity);
+              gimp_canvas_transform_preview_draw_tri_row (texture, cr,
+                                                          area, area_offx, area_offy,
+                                                          *left, u_l, v_l,
+                                                          *right, u_r, v_r,
+                                                          ry,
+                                                          opacity);
             left ++;      right ++;
             u_l += dul;   v_l += dvl;
             u_r += dur;   v_r += dvr;
@@ -526,7 +666,7 @@ gimp_display_shell_draw_tri (GimpDrawable    *texture,
 
   if (y[1] != y[2])
     {
-      gimp_display_shell_trace_tri_edge (r_edge, x[1], y[1], x[2], y[2]);
+      gimp_canvas_transform_preview_trace_tri_edge (r_edge, x[1], y[1], x[2], y[2]);
 
       right = r_edge;
       dur   = (u[2] - u[1]) / (y[2] - y[1]);
@@ -538,13 +678,13 @@ gimp_display_shell_draw_tri (GimpDrawable    *texture,
         for (ry = y[1]; ry < y[2]; ry++)
           {
             if (ry >= clip_y1 && ry < clip_y2)
-              gimp_display_shell_draw_tri_row_mask (texture, cr,
-                                                    area, area_offx, area_offy,
-                                                    mask, mask_offx, mask_offy,
-                                                    *left,  u_l, v_l,
-                                                    *right, u_r, v_r,
-                                                    ry,
-                                                    opacity);
+              gimp_canvas_transform_preview_draw_tri_row_mask (texture, cr,
+                                                               area, area_offx, area_offy,
+                                                               mask, mask_offx, mask_offy,
+                                                               *left,  u_l, v_l,
+                                                               *right, u_r, v_r,
+                                                               ry,
+                                                               opacity);
             left ++;      right ++;
             u_l += dul;   v_l += dvl;
             u_r += dur;   v_r += dvr;
@@ -553,12 +693,12 @@ gimp_display_shell_draw_tri (GimpDrawable    *texture,
         for (ry = y[1]; ry < y[2]; ry++)
           {
             if (ry >= clip_y1 && ry < clip_y2)
-              gimp_display_shell_draw_tri_row (texture, cr,
-                                               area, area_offx, area_offy,
-                                               *left,  u_l, v_l,
-                                               *right, u_r, v_r,
-                                               ry,
-                                               opacity);
+              gimp_canvas_transform_preview_draw_tri_row (texture, cr,
+                                                          area, area_offx, area_offy,
+                                                          *left,  u_l, v_l,
+                                                          *right, u_r, v_r,
+                                                          ry,
+                                                          opacity);
             left ++;      right ++;
             u_l += dul;   v_l += dvl;
             u_r += dur;   v_r += dvr;
@@ -570,29 +710,30 @@ gimp_display_shell_draw_tri (GimpDrawable    *texture,
 }
 
 /**
- * gimp_display_shell_draw_tri_row:
+ * gimp_canvas_transform_preview_draw_tri_row:
  * @texture: the thing being transformed
  * @cr:      the #cairo_t to draw to
  * @area:    has prefetched pixel data of dest
  *
- * Called from gimp_display_shell_draw_tri(), this draws a single row of a
- * triangle onto dest when there is not a mask. The run (x1,y) to (x2,y) in
- * dest corresponds to the run (u1,v1) to (u2,v2) in texture.
+ * Called from gimp_canvas_transform_preview_draw_tri(), this draws a
+ * single row of a triangle onto dest when there is not a mask. The
+ * run (x1,y) to (x2,y) in dest corresponds to the run (u1,v1) to
+ * (u2,v2) in texture.
  **/
 static void
-gimp_display_shell_draw_tri_row (GimpDrawable    *texture,
-                                 cairo_t         *cr,
-                                 cairo_surface_t *area,
-                                 gint             area_offx,
-                                 gint             area_offy,
-                                 gint             x1,
-                                 gfloat           u1,
-                                 gfloat           v1,
-                                 gint             x2,
-                                 gfloat           u2,
-                                 gfloat           v2,
-                                 gint             y,
-                                 guchar           opacity)
+gimp_canvas_transform_preview_draw_tri_row (GimpDrawable    *texture,
+                                            cairo_t         *cr,
+                                            cairo_surface_t *area,
+                                            gint             area_offx,
+                                            gint             area_offy,
+                                            gint             x1,
+                                            gfloat           u1,
+                                            gfloat           v1,
+                                            gint             x2,
+                                            gfloat           u2,
+                                            gfloat           v2,
+                                            gint             y,
+                                            guchar           opacity)
 {
   TileManager  *tiles;     /* used to get the source texture colors   */
   guchar       *pptr;      /* points into the pixels of a row of area */
@@ -801,28 +942,28 @@ gimp_display_shell_draw_tri_row (GimpDrawable    *texture,
 }
 
 /**
- * gimp_display_shell_draw_tri_row_mask:
+ * gimp_canvas_transform_preview_draw_tri_row_mask:
  *
- * Called from gimp_display_shell_draw_tri(), this draws a single row of a
- * triangle onto dest, when there is a mask.
+ * Called from gimp_canvas_transform_preview_draw_tri(), this draws a
+ * single row of a triangle onto dest, when there is a mask.
  **/
 static void
-gimp_display_shell_draw_tri_row_mask (GimpDrawable    *texture,
-                                      cairo_t         *cr,
-                                      cairo_surface_t *area,
-                                      gint             area_offx,
-                                      gint             area_offy,
-                                      GimpChannel     *mask,
-                                      gint             mask_offx,
-                                      gint             mask_offy,
-                                      gint             x1,
-                                      gfloat           u1,
-                                      gfloat           v1,
-                                      gint             x2,
-                                      gfloat           u2,
-                                      gfloat           v2,
-                                      gint             y,
-                                      guchar           opacity)
+gimp_canvas_transform_preview_draw_tri_row_mask (GimpDrawable    *texture,
+                                                 cairo_t         *cr,
+                                                 cairo_surface_t *area,
+                                                 gint             area_offx,
+                                                 gint             area_offy,
+                                                 GimpChannel     *mask,
+                                                 gint             mask_offx,
+                                                 gint             mask_offy,
+                                                 gint             x1,
+                                                 gfloat           u1,
+                                                 gfloat           v1,
+                                                 gint             x2,
+                                                 gfloat           u2,
+                                                 gfloat           v2,
+                                                 gint             y,
+                                                 guchar           opacity)
 {
 
   TileManager  *tiles, *masktiles; /* used to get the source texture colors */
@@ -1071,19 +1212,19 @@ gimp_display_shell_draw_tri_row_mask (GimpDrawable    *texture,
 }
 
 /**
- * gimp_display_shell_trace_tri_edge:
+ * gimp_canvas_transform_preview_trace_tri_edge:
  * @dest: x coordinates are placed in this array
  *
- * Find the x coordinates for a line that runs from (x1,y1) to (x2,y2),
- * corresponding to the y coordinates y1 to y2-1. So
- * dest must be large enough to hold y2-y1 values.
+ * Find the x coordinates for a line that runs from (x1,y1) to
+ * (x2,y2), corresponding to the y coordinates y1 to y2-1. So dest
+ * must be large enough to hold y2-y1 values.
  **/
 static void
-gimp_display_shell_trace_tri_edge (gint *dest,
-                                   gint  x1,
-                                   gint  y1,
-                                   gint  x2,
-                                   gint  y2)
+gimp_canvas_transform_preview_trace_tri_edge (gint *dest,
+                                              gint  x1,
+                                              gint  y1,
+                                              gint  x2,
+                                              gint  y2)
 {
   const gint  dy = y2 - y1;
   gint        dx;
diff --git a/app/display/gimpcanvastransformpreview.h b/app/display/gimpcanvastransformpreview.h
new file mode 100644
index 0000000..56be9db
--- /dev/null
+++ b/app/display/gimpcanvastransformpreview.h
@@ -0,0 +1,59 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpcanvastransformpreview.h
+ * Copyright (C) 2011 Michael Natterer <mitch gimp org>
+ *
+ * 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_CANVAS_TRANSFORM_PREVIEW_H__
+#define __GIMP_CANVAS_TRANSFORM_PREVIEW_H__
+
+
+#include "tools/tools-types.h" /* eek */
+
+#include "gimpcanvasitem.h"
+
+
+#define GIMP_TYPE_CANVAS_TRANSFORM_PREVIEW            (gimp_canvas_transform_preview_get_type ())
+#define GIMP_CANVAS_TRANSFORM_PREVIEW(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_CANVAS_TRANSFORM_PREVIEW, GimpCanvasTransformPreview))
+#define GIMP_CANVAS_TRANSFORM_PREVIEW_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_CANVAS_TRANSFORM_PREVIEW, GimpCanvasTransformPreviewClass))
+#define GIMP_IS_CANVAS_TRANSFORM_PREVIEW(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_CANVAS_TRANSFORM_PREVIEW))
+#define GIMP_IS_CANVAS_TRANSFORM_PREVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_CANVAS_TRANSFORM_PREVIEW))
+#define GIMP_CANVAS_TRANSFORM_PREVIEW_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_CANVAS_TRANSFORM_PREVIEW, GimpCanvasTransformPreviewClass))
+
+
+typedef struct _GimpCanvasTransformPreview      GimpCanvasTransformPreview;
+typedef struct _GimpCanvasTransformPreviewClass GimpCanvasTransformPreviewClass;
+
+struct _GimpCanvasTransformPreview
+{
+  GimpCanvasItem  parent_instance;
+};
+
+struct _GimpCanvasTransformPreviewClass
+{
+  GimpCanvasItemClass  parent_class;
+};
+
+
+GType            gimp_canvas_transform_preview_get_type (void) G_GNUC_CONST;
+
+GimpCanvasItem * gimp_canvas_transform_preview_new      (GimpDisplayShell  *shell,
+                                                         GimpTransformTool *transform_tool,
+                                                         gdouble            opacity);
+
+
+#endif /* __GIMP_CANVAS_TRANSFORM_PREVIEW_H__ */
diff --git a/app/display/gimpdisplayshell-appearance.c b/app/display/gimpdisplayshell-appearance.c
index 9393e05..d433795 100644
--- a/app/display/gimpdisplayshell-appearance.c
+++ b/app/display/gimpdisplayshell-appearance.c
@@ -284,23 +284,6 @@ gimp_display_shell_get_show_layer (GimpDisplayShell *shell)
 }
 
 void
-gimp_display_shell_set_show_transform (GimpDisplayShell *shell,
-                                       gboolean          show)
-{
-  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
-
-  shell->show_transform_preview = show;
-}
-
-gboolean
-gimp_display_shell_get_show_transform (GimpDisplayShell *shell)
-{
-  g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), FALSE);
-
-  return shell->show_transform_preview;
-}
-
-void
 gimp_display_shell_set_show_guides (GimpDisplayShell *shell,
                                     gboolean          show)
 {
diff --git a/app/display/gimpdisplayshell-appearance.h b/app/display/gimpdisplayshell-appearance.h
index 77cc494..f6cca4c 100644
--- a/app/display/gimpdisplayshell-appearance.h
+++ b/app/display/gimpdisplayshell-appearance.h
@@ -45,10 +45,6 @@ void       gimp_display_shell_set_show_layer         (GimpDisplayShell       *sh
                                                       gboolean                show);
 gboolean   gimp_display_shell_get_show_layer         (GimpDisplayShell       *shell);
 
-void       gimp_display_shell_set_show_transform     (GimpDisplayShell       *shell,
-                                                      gboolean                show);
-gboolean   gimp_display_shell_get_show_transform     (GimpDisplayShell       *shell);
-
 void       gimp_display_shell_set_show_grid          (GimpDisplayShell       *shell,
                                                       gboolean                show);
 gboolean   gimp_display_shell_get_show_grid          (GimpDisplayShell       *shell);
diff --git a/app/display/gimpdisplayshell-callbacks.c b/app/display/gimpdisplayshell-callbacks.c
index c44da44..8415d5d 100644
--- a/app/display/gimpdisplayshell-callbacks.c
+++ b/app/display/gimpdisplayshell-callbacks.c
@@ -38,7 +38,6 @@
 #include "gimpdisplayshell-appearance.h"
 #include "gimpdisplayshell-callbacks.h"
 #include "gimpdisplayshell-draw.h"
-#include "gimpdisplayshell-preview.h"
 #include "gimpdisplayshell-scroll.h"
 #include "gimpdisplayshell-selection.h"
 #include "gimpdisplayshell-title.h"
@@ -531,11 +530,6 @@ gimp_display_shell_canvas_expose_image (GimpDisplayShell *shell,
   /*  finally, draw all the remaining image window stuff on top
    */
 
-  /* draw the transform tool preview */
-  cairo_save (cr);
-  gimp_display_shell_preview_transform (shell, cr);
-  cairo_restore (cr);
-
   /* draw canvas items */
   gimp_canvas_item_draw (shell->canvas_item, cr);
 
diff --git a/app/display/gimpdisplayshell.h b/app/display/gimpdisplayshell.h
index 1f89087..20f9833 100644
--- a/app/display/gimpdisplayshell.h
+++ b/app/display/gimpdisplayshell.h
@@ -179,7 +179,6 @@ struct _GimpDisplayShell
   GimpTreeHandler   *vectors_visible_handler;
 
   gboolean           zoom_on_resize;
-  gboolean           show_transform_preview;
 
   gboolean           size_allocate_from_configure_event;
 
diff --git a/app/tools/gimprotatetool.c b/app/tools/gimprotatetool.c
index f6d3e37..a306f1b 100644
--- a/app/tools/gimprotatetool.c
+++ b/app/tools/gimprotatetool.c
@@ -381,8 +381,6 @@ rotate_angle_changed (GtkAdjustment     *adj,
 
       gimp_transform_tool_recalc (tr_tool, GIMP_TOOL (tr_tool)->display);
 
-      gimp_transform_tool_expose_preview (tr_tool);
-
       gimp_draw_tool_resume (GIMP_DRAW_TOOL (tr_tool));
     }
 
@@ -408,8 +406,6 @@ rotate_center_changed (GtkWidget         *widget,
 
       gimp_transform_tool_recalc (tr_tool, GIMP_TOOL (tr_tool)->display);
 
-      gimp_transform_tool_expose_preview (tr_tool);
-
       gimp_draw_tool_resume (GIMP_DRAW_TOOL (tr_tool));
     }
 }
diff --git a/app/tools/gimpscaletool.c b/app/tools/gimpscaletool.c
index 31b4574..199acf0 100644
--- a/app/tools/gimpscaletool.c
+++ b/app/tools/gimpscaletool.c
@@ -351,8 +351,6 @@ gimp_scale_tool_size_notify (GtkWidget         *box,
 
           gimp_transform_tool_recalc (tr_tool, GIMP_TOOL (tr_tool)->display);
 
-          gimp_transform_tool_expose_preview (tr_tool);
-
           gimp_draw_tool_resume (GIMP_DRAW_TOOL (tr_tool));
         }
     }
diff --git a/app/tools/gimpsheartool.c b/app/tools/gimpsheartool.c
index 4da3077..d329762 100644
--- a/app/tools/gimpsheartool.c
+++ b/app/tools/gimpsheartool.c
@@ -261,8 +261,6 @@ shear_x_mag_changed (GtkAdjustment     *adj,
 
       gimp_transform_tool_recalc (tr_tool, GIMP_TOOL (tr_tool)->display);
 
-      gimp_transform_tool_expose_preview (tr_tool);
-
       gimp_draw_tool_resume (GIMP_DRAW_TOOL (tr_tool));
     }
 }
@@ -284,8 +282,6 @@ shear_y_mag_changed (GtkAdjustment     *adj,
 
       gimp_transform_tool_recalc (tr_tool, GIMP_TOOL (tr_tool)->display);
 
-      gimp_transform_tool_expose_preview (tr_tool);
-
       gimp_draw_tool_resume (GIMP_DRAW_TOOL (tr_tool));
     }
 }
diff --git a/app/tools/gimptransformtool.c b/app/tools/gimptransformtool.c
index 6ddb99a..70d47b0 100644
--- a/app/tools/gimptransformtool.c
+++ b/app/tools/gimptransformtool.c
@@ -52,10 +52,9 @@
 #include "widgets/gimpdialogfactory.h"
 
 #include "display/gimpcanvasgroup.h"
+#include "display/gimpcanvastransformpreview.h"
 #include "display/gimpdisplay.h"
 #include "display/gimpdisplayshell.h"
-#include "display/gimpdisplayshell-appearance.h"
-#include "display/gimpdisplayshell-expose.h"
 #include "display/gimpdisplayshell-transform.h"
 #include "display/gimptooldialog.h"
 
@@ -144,8 +143,6 @@ static void      gimp_transform_tool_grid_recalc            (GimpTransformTool
 
 static void      gimp_transform_tool_handles_recalc         (GimpTransformTool     *tr_tool,
                                                              GimpDisplay           *display);
-static void      gimp_transform_tool_force_expose_preview   (GimpTransformTool     *tr_tool);
-
 static void      gimp_transform_tool_response               (GtkWidget             *widget,
                                                              gint                   response_id,
                                                              GimpTransformTool     *tr_tool);
@@ -322,8 +319,6 @@ gimp_transform_tool_initialize (GimpTool     *tool,
       /*  start drawing the bounding box and handles...  */
       gimp_draw_tool_start (GIMP_DRAW_TOOL (tool), display);
 
-      gimp_transform_tool_expose_preview (tr_tool);
-
       tr_tool->function = TRANSFORM_CREATING;
 
       /*  Save the current transformation info  */
@@ -422,9 +417,6 @@ gimp_transform_tool_button_release (GimpTool              *tool,
       /*  recalculate the tool's transformation matrix  */
       gimp_transform_tool_recalc (tr_tool, display);
 
-      /* get rid of preview artifacts left outside the drawable's area */
-      gimp_transform_tool_expose_preview (tr_tool);
-
       gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
     }
 
@@ -458,8 +450,6 @@ gimp_transform_tool_motion (GimpTool         *tool,
       tr_tool_class->motion (tr_tool, display);
 
       gimp_transform_tool_recalc (tr_tool, display);
-
-      gimp_transform_tool_expose_preview (tr_tool);
     }
 
   tr_tool->lastx = tr_tool->curx;
@@ -763,65 +753,6 @@ gimp_transform_tool_options_notify (GimpTool         *tool,
             }
         }
 
-      if (! strcmp (pspec->name, "type")         ||
-          ! strcmp (pspec->name, "direction")    ||
-          ! strcmp (pspec->name, "preview-type") ||
-          ! strcmp (pspec->name, "grid-type")    ||
-          ! strcmp (pspec->name, "grid-size")    ||
-          ! strcmp (pspec->name, "preview-opacity"))
-        {
-          GimpDisplayShell *shell = NULL;
-
-          if (gimp_draw_tool_is_active (GIMP_DRAW_TOOL (tr_tool)))
-            shell = gimp_display_get_shell (GIMP_DRAW_TOOL (tr_tool)->display);
-
-          switch (tr_options->preview_type)
-            {
-            default:
-            case GIMP_TRANSFORM_PREVIEW_TYPE_OUTLINE:
-              if (shell)
-                {
-                  gimp_display_shell_set_show_transform (shell, FALSE);
-                  gimp_transform_tool_force_expose_preview (tr_tool);
-                }
-              break;
-
-            case GIMP_TRANSFORM_PREVIEW_TYPE_GRID:
-              if (shell)
-                {
-                  gimp_display_shell_set_show_transform (shell, FALSE);
-                  gimp_transform_tool_force_expose_preview (tr_tool);
-                }
-              break;
-
-            case GIMP_TRANSFORM_PREVIEW_TYPE_IMAGE:
-              if (shell)
-                {
-                  if (tr_options->type      == GIMP_TRANSFORM_TYPE_LAYER &&
-                      tr_options->direction == GIMP_TRANSFORM_FORWARD)
-                    gimp_display_shell_set_show_transform (shell, TRUE);
-                  else
-                    gimp_display_shell_set_show_transform (shell, FALSE);
-
-                  gimp_transform_tool_force_expose_preview (tr_tool);
-                }
-              break;
-
-            case GIMP_TRANSFORM_PREVIEW_TYPE_IMAGE_GRID:
-              if (shell)
-                {
-                  if (tr_options->type      == GIMP_TRANSFORM_TYPE_LAYER &&
-                      tr_options->direction == GIMP_TRANSFORM_FORWARD)
-                    gimp_display_shell_set_show_transform (shell, TRUE);
-                  else
-                    gimp_display_shell_set_show_transform (shell, FALSE);
-
-                  gimp_transform_tool_force_expose_preview (tr_tool);
-                }
-              break;
-            }
-        }
-
       if (tr_tool->function != TRANSFORM_CREATING)
         {
           gimp_transform_tool_grid_recalc (tr_tool);
@@ -840,10 +771,25 @@ gimp_transform_tool_options_notify (GimpTool         *tool,
 static void
 gimp_transform_tool_draw (GimpDrawTool *draw_tool)
 {
-  GimpTool          *tool    = GIMP_TOOL (draw_tool);
-  GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (draw_tool);
-  GimpImage         *image   = gimp_display_get_image (tool->display);
-  gdouble            z1, z2, z3, z4;
+  GimpTool             *tool    = GIMP_TOOL (draw_tool);
+  GimpTransformTool    *tr_tool = GIMP_TRANSFORM_TOOL (draw_tool);
+  GimpTransformOptions *options = GIMP_TRANSFORM_TOOL_GET_OPTIONS (tool);
+  GimpImage            *image   = gimp_display_get_image (tool->display);
+  gdouble               z1, z2, z3, z4;
+
+  if ((options->preview_type == GIMP_TRANSFORM_PREVIEW_TYPE_IMAGE ||
+       options->preview_type == GIMP_TRANSFORM_PREVIEW_TYPE_IMAGE_GRID) &&
+      options->type         == GIMP_TRANSFORM_TYPE_LAYER &&
+      options->direction    == GIMP_TRANSFORM_FORWARD)
+    {
+      GimpCanvasItem *item;
+
+      item = gimp_canvas_transform_preview_new (gimp_display_get_shell (draw_tool->display),
+                                                tr_tool,
+                                                options->preview_opacity);
+      gimp_draw_tool_add_item (draw_tool, item);
+      g_object_unref (item);
+    }
 
   if (tr_tool->use_grid)
     {
@@ -1381,110 +1327,13 @@ gimp_transform_tool_transform_bounding_box (GimpTransformTool *tr_tool)
                                 &tr_tool->tcx, &tr_tool->tcy);
 }
 
-void
-gimp_transform_tool_expose_preview (GimpTransformTool *tr_tool)
-{
-  GimpTransformOptions *options = GIMP_TRANSFORM_TOOL_GET_OPTIONS (tr_tool);
-
-  if ((options->preview_type == GIMP_TRANSFORM_PREVIEW_TYPE_IMAGE ||
-       options->preview_type == GIMP_TRANSFORM_PREVIEW_TYPE_IMAGE_GRID) &&
-      options->type         == GIMP_TRANSFORM_TYPE_LAYER &&
-      options->direction    == GIMP_TRANSFORM_FORWARD)
-    {
-      gimp_transform_tool_force_expose_preview (tr_tool);
-    }
-}
-
-static void
-gimp_transform_tool_force_expose_preview (GimpTransformTool *tr_tool)
-{
-  static gint       last_x = 0;
-  static gint       last_y = 0;
-  static gint       last_w = 0;
-  static gint       last_h = 0;
-
-  GimpDisplayShell *shell;
-  gdouble           dx[4], dy[4];
-  gint              area_x, area_y, area_w, area_h;
-  gint              i;
-
-  g_return_if_fail (GIMP_IS_TRANSFORM_TOOL (tr_tool));
-
-  if (! tr_tool->use_grid)
-    return;
-
-  /*  we might be called as the result of cancelling the transform
-   *  tool dialog, return silently because the draw tool may have
-   *  already been stopped by gimp_transform_tool_halt()
-   */
-  if (! gimp_draw_tool_is_active (GIMP_DRAW_TOOL (tr_tool)))
-    return;
-
-  shell = gimp_display_get_shell (GIMP_DRAW_TOOL (tr_tool)->display);
-
-  gimp_display_shell_transform_xy_f (shell, tr_tool->tx1, tr_tool->ty1,
-                                     dx + 0, dy + 0);
-  gimp_display_shell_transform_xy_f (shell, tr_tool->tx2, tr_tool->ty2,
-                                     dx + 1, dy + 1);
-  gimp_display_shell_transform_xy_f (shell, tr_tool->tx3, tr_tool->ty3,
-                                     dx + 2, dy + 2);
-  gimp_display_shell_transform_xy_f (shell, tr_tool->tx4, tr_tool->ty4,
-                                     dx + 3, dy + 3);
-
-  /* find bounding box around preview */
-  area_x = area_w = (gint) dx[0];
-  area_y = area_h = (gint) dy[0];
-
-  for (i = 1; i < 4; i++)
-    {
-      if (dx[i] < area_x)
-        area_x = (gint) dx[i];
-      else if (dx[i] > area_w)
-        area_w = (gint) dx[i];
-
-      if (dy[i] < area_y)
-        area_y = (gint) dy[i];
-      else if (dy[i] > area_h)
-        area_h = (gint) dy[i];
-    }
-
-  area_w -= area_x;
-  area_h -= area_y;
-
-  gimp_display_shell_expose_area (shell,
-                                  MIN (area_x, last_x),
-                                  MIN (area_y, last_y),
-                                  MAX (area_w, last_w) + ABS (last_x - area_x),
-                                  MAX (area_h, last_h) + ABS (last_y - area_y));
-
-  /* area of last preview must be re-exposed to avoid leaving artifacts */
-  last_x = area_x;
-  last_y = area_y;
-  last_w = area_w;
-  last_h = area_h;
-}
-
 static void
 gimp_transform_tool_halt (GimpTransformTool *tr_tool)
 {
   GimpTool *tool = GIMP_TOOL (tr_tool);
 
   if (gimp_draw_tool_is_active (GIMP_DRAW_TOOL (tr_tool)))
-    {
-      GimpDisplayShell *shell;
-
-      shell = gimp_display_get_shell (GIMP_DRAW_TOOL (tr_tool)->display);
-
-      if (gimp_display_shell_get_show_transform (shell))
-        {
-          gimp_display_shell_set_show_transform (shell, FALSE);
-
-          /* get rid of preview artifacts left outside the drawable's area */
-          gimp_transform_tool_expose_preview (tr_tool);
-        }
-
-      gimp_draw_tool_stop (GIMP_DRAW_TOOL (tr_tool));
-    }
+    gimp_draw_tool_stop (GIMP_DRAW_TOOL (tr_tool));
 
   /*  inactivate the tool  */
   tr_tool->function = TRANSFORM_CREATING;
@@ -1704,16 +1553,6 @@ gimp_transform_tool_prepare (GimpTransformTool *tr_tool,
 {
   GimpTransformOptions *options = GIMP_TRANSFORM_TOOL_GET_OPTIONS (tr_tool);
   GimpImage            *image   = gimp_display_get_image (display);
-  gboolean              show_transform;
-
-  show_transform =
-    ((options->preview_type == GIMP_TRANSFORM_PREVIEW_TYPE_IMAGE ||
-      options->preview_type == GIMP_TRANSFORM_PREVIEW_TYPE_IMAGE_GRID) &&
-     options->type         == GIMP_TRANSFORM_TYPE_LAYER &&
-     options->direction    == GIMP_TRANSFORM_FORWARD);
-
-  gimp_display_shell_set_show_transform (gimp_display_get_shell (display),
-                                         show_transform);
 
   if (tr_tool->dialog)
     {
@@ -1772,9 +1611,6 @@ gimp_transform_tool_response (GtkWidget         *widget,
         /*  recalculate the tool's transformation matrix  */
         gimp_transform_tool_recalc (tr_tool, tool->display);
 
-        /* get rid of preview artifacts left outside the drawable's area */
-        gimp_transform_tool_expose_preview (tr_tool);
-
         gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
       }
       break;
diff --git a/app/tools/gimptransformtool.h b/app/tools/gimptransformtool.h
index 30c034e..b1e2518 100644
--- a/app/tools/gimptransformtool.h
+++ b/app/tools/gimptransformtool.h
@@ -132,11 +132,10 @@ struct _GimpTransformToolClass
 };
 
 
-GType   gimp_transform_tool_get_type       (void) G_GNUC_CONST;
+GType   gimp_transform_tool_get_type (void) G_GNUC_CONST;
 
-void    gimp_transform_tool_recalc         (GimpTransformTool *tr_tool,
-                                            GimpDisplay       *display);
-void    gimp_transform_tool_expose_preview (GimpTransformTool *tr_tool);
+void    gimp_transform_tool_recalc   (GimpTransformTool *tr_tool,
+                                      GimpDisplay       *display);
 
 
 #endif  /*  __GIMP_TRANSFORM_TOOL_H__  */



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