Commit 8a09fd1f authored by Michael Natterer's avatar Michael Natterer 😴

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.
parent 1e11a279
......@@ -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);
}
......
......@@ -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);
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment