Commit 457f6bf9 authored by Michael Natterer's avatar Michael Natterer 😴

app: add GimpToolTransformGrid, GimpToolRotateGrid and GimpToolShearGrid

which do all transform tools' (except handle transform) canvas GUI and
their interaction.
parent 46843c84
......@@ -168,6 +168,12 @@ libappdisplay_a_sources = \
gimptoolcompass.h \
gimptoolline.c \
gimptoolline.h \
gimptoolrotategrid.c \
gimptoolrotategrid.h \
gimptoolsheargrid.c \
gimptoolsheargrid.h \
gimptooltransformgrid.c \
gimptooltransformgrid.h \
gimptoolwidget.c \
gimptoolwidget.h
......
......@@ -259,6 +259,41 @@ gimp_path_style_get_type (void)
return type;
}
GType
gimp_transform_function_get_type (void)
{
static const GEnumValue values[] =
{
{ GIMP_TRANSFORM_FUNCTION_MOVE, "GIMP_TRANSFORM_FUNCTION_MOVE", "move" },
{ GIMP_TRANSFORM_FUNCTION_SCALE, "GIMP_TRANSFORM_FUNCTION_SCALE", "scale" },
{ GIMP_TRANSFORM_FUNCTION_ROTATE, "GIMP_TRANSFORM_FUNCTION_ROTATE", "rotate" },
{ GIMP_TRANSFORM_FUNCTION_SHEAR, "GIMP_TRANSFORM_FUNCTION_SHEAR", "shear" },
{ GIMP_TRANSFORM_FUNCTION_PERSPECTIVE, "GIMP_TRANSFORM_FUNCTION_PERSPECTIVE", "perspective" },
{ 0, NULL, NULL }
};
static const GimpEnumDesc descs[] =
{
{ GIMP_TRANSFORM_FUNCTION_MOVE, "GIMP_TRANSFORM_FUNCTION_MOVE", NULL },
{ GIMP_TRANSFORM_FUNCTION_SCALE, "GIMP_TRANSFORM_FUNCTION_SCALE", NULL },
{ GIMP_TRANSFORM_FUNCTION_ROTATE, "GIMP_TRANSFORM_FUNCTION_ROTATE", NULL },
{ GIMP_TRANSFORM_FUNCTION_SHEAR, "GIMP_TRANSFORM_FUNCTION_SHEAR", NULL },
{ GIMP_TRANSFORM_FUNCTION_PERSPECTIVE, "GIMP_TRANSFORM_FUNCTION_PERSPECTIVE", NULL },
{ 0, NULL, NULL }
};
static GType type = 0;
if (G_UNLIKELY (! type))
{
type = g_enum_register_static ("GimpTransformFunction", values);
gimp_type_set_translation_context (type, "transform-function");
gimp_enum_set_value_descriptions (type, descs);
}
return type;
}
GType
gimp_zoom_focus_get_type (void)
{
......
......@@ -120,6 +120,20 @@ typedef enum
} GimpPathStyle;
#define GIMP_TYPE_TRANSFORM_FUNCTION (gimp_transform_function_get_type ())
GType gimp_transform_function_get_type (void) G_GNUC_CONST;
typedef enum
{
GIMP_TRANSFORM_FUNCTION_MOVE,
GIMP_TRANSFORM_FUNCTION_SCALE,
GIMP_TRANSFORM_FUNCTION_ROTATE,
GIMP_TRANSFORM_FUNCTION_SHEAR,
GIMP_TRANSFORM_FUNCTION_PERSPECTIVE
} GimpTransformFunction;
#define GIMP_TYPE_ZOOM_FOCUS (gimp_zoom_focus_get_type ())
GType gimp_zoom_focus_get_type (void) G_GNUC_CONST;
......
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimptoolrotategrid.c
* Copyright (C) 2017 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/>.
*/
#include "config.h"
#include <gegl.h>
#include <gtk/gtk.h>
#include "libgimpbase/gimpbase.h"
#include "libgimpmath/gimpmath.h"
#include "display-types.h"
#include "core/gimp-transform-utils.h"
#include "core/gimp-utils.h"
#include "gimpdisplayshell.h"
#include "gimptoolrotategrid.h"
#include "gimp-intl.h"
enum
{
PROP_0,
PROP_ANGLE
};
struct _GimpToolRotateGridPrivate
{
gdouble angle;
gboolean rotate_grab;
gdouble real_angle;
gdouble last_x;
gdouble last_y;
};
/* local function prototypes */
static void gimp_tool_rotate_grid_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_tool_rotate_grid_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static gint gimp_tool_rotate_grid_button_press (GimpToolWidget *widget,
const GimpCoords *coords,
guint32 time,
GdkModifierType state,
GimpButtonPressType press_type);
static void gimp_tool_rotate_grid_motion (GimpToolWidget *widget,
const GimpCoords *coords,
guint32 time,
GdkModifierType state);
G_DEFINE_TYPE (GimpToolRotateGrid, gimp_tool_rotate_grid,
GIMP_TYPE_TOOL_TRANSFORM_GRID)
#define parent_class gimp_tool_rotate_grid_parent_class
static void
gimp_tool_rotate_grid_class_init (GimpToolRotateGridClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GimpToolWidgetClass *widget_class = GIMP_TOOL_WIDGET_CLASS (klass);
object_class->set_property = gimp_tool_rotate_grid_set_property;
object_class->get_property = gimp_tool_rotate_grid_get_property;
widget_class->button_press = gimp_tool_rotate_grid_button_press;
widget_class->motion = gimp_tool_rotate_grid_motion;
g_object_class_install_property (object_class, PROP_ANGLE,
g_param_spec_double ("angle",
NULL, NULL,
-GIMP_MAX_IMAGE_SIZE,
GIMP_MAX_IMAGE_SIZE,
0.0,
GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
g_type_class_add_private (klass, sizeof (GimpToolRotateGridPrivate));
}
static void
gimp_tool_rotate_grid_init (GimpToolRotateGrid *grid)
{
grid->private = G_TYPE_INSTANCE_GET_PRIVATE (grid,
GIMP_TYPE_TOOL_ROTATE_GRID,
GimpToolRotateGridPrivate);
}
static void
gimp_tool_rotate_grid_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GimpToolRotateGrid *grid = GIMP_TOOL_ROTATE_GRID (object);
GimpToolRotateGridPrivate *private = grid->private;
switch (property_id)
{
case PROP_ANGLE:
private->angle = g_value_get_double (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_tool_rotate_grid_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GimpToolRotateGrid *grid = GIMP_TOOL_ROTATE_GRID (object);
GimpToolRotateGridPrivate *private = grid->private;
switch (property_id)
{
case PROP_ANGLE:
g_value_set_double (value, private->angle);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static gint
gimp_tool_rotate_grid_button_press (GimpToolWidget *widget,
const GimpCoords *coords,
guint32 time,
GdkModifierType state,
GimpButtonPressType press_type)
{
GimpToolRotateGrid *grid = GIMP_TOOL_ROTATE_GRID (widget);
GimpToolRotateGridPrivate *private = grid->private;
GimpTransformHandle handle;
handle = GIMP_TOOL_WIDGET_CLASS (parent_class)->button_press (widget,
coords, time,
state,
press_type);
if (handle == GIMP_TRANSFORM_HANDLE_ROTATION)
{
private->rotate_grab = TRUE;
private->real_angle = private->angle;
private->last_x = coords->x;
private->last_y = coords->y;
}
else
{
private->rotate_grab = FALSE;
}
return handle;
}
void
gimp_tool_rotate_grid_motion (GimpToolWidget *widget,
const GimpCoords *coords,
guint32 time,
GdkModifierType state)
{
GimpToolRotateGrid *grid = GIMP_TOOL_ROTATE_GRID (widget);
GimpToolRotateGridPrivate *private = grid->private;
gdouble angle1, angle2, angle;
gdouble pivot_x, pivot_y;
gdouble x1, y1, x2, y2;
gboolean constrain;
GimpMatrix3 transform;
if (! private->rotate_grab)
{
gdouble old_pivot_x;
gdouble old_pivot_y;
g_object_get (widget,
"pivot-x", &old_pivot_x,
"pivot-y", &old_pivot_y,
NULL);
g_object_freeze_notify (G_OBJECT (widget));
GIMP_TOOL_WIDGET_CLASS (parent_class)->motion (widget,
coords, time, state);
g_object_get (widget,
"pivot-x", &pivot_x,
"pivot-y", &pivot_y,
NULL);
if (old_pivot_x != pivot_x ||
old_pivot_y != pivot_y)
{
gimp_matrix3_identity (&transform);
gimp_transform_matrix_rotate_center (&transform,
pivot_x, pivot_y,
private->angle);
g_object_set (widget,
"transform", &transform,
NULL);
}
g_object_thaw_notify (G_OBJECT (widget));
return;
}
g_object_get (widget,
"pivot-x", &pivot_x,
"pivot-y", &pivot_y,
"constrain-rotate", &constrain,
NULL);
x1 = coords->x - pivot_x;
x2 = private->last_x - pivot_x;
y1 = pivot_y - coords->y;
y2 = pivot_y - private->last_y;
/* find the first angle */
angle1 = atan2 (y1, x1);
/* find the angle */
angle2 = atan2 (y2, x2);
angle = angle2 - angle1;
if (angle > G_PI || angle < -G_PI)
angle = angle2 - ((angle1 < 0) ? 2.0 * G_PI + angle1 : angle1 - 2.0 * G_PI);
/* increment the transform tool's angle */
private->real_angle += angle;
/* limit the angle to between -180 and 180 degrees */
if (private->real_angle < - G_PI)
{
private->real_angle += 2.0 * G_PI;
}
else if (private->real_angle > G_PI)
{
private->real_angle -= 2.0 * G_PI;
}
/* constrain the angle to 15-degree multiples if ctrl is held down */
#define FIFTEEN_DEG (G_PI / 12.0)
if (constrain)
{
angle = FIFTEEN_DEG * (gint) ((private->real_angle +
FIFTEEN_DEG / 2.0) / FIFTEEN_DEG);
}
else
{
angle = private->real_angle;
}
gimp_matrix3_identity (&transform);
gimp_transform_matrix_rotate_center (&transform, pivot_x, pivot_y, angle);
g_object_set (widget,
"transform", &transform,
"angle", angle,
NULL);
private->last_x = coords->x;
private->last_y = coords->y;
}
/* public functions */
GimpToolWidget *
gimp_tool_rotate_grid_new (GimpDisplayShell *shell,
gdouble x1,
gdouble y1,
gdouble x2,
gdouble y2,
gdouble pivot_x,
gdouble pivot_y,
gdouble angle)
{
GimpMatrix3 transform;
g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), NULL);
gimp_matrix3_identity (&transform);
gimp_transform_matrix_rotate_center (&transform, pivot_x, pivot_y, angle);
return g_object_new (GIMP_TYPE_TOOL_ROTATE_GRID,
"shell", shell,
"transform", &transform,
"x1", x1,
"y1", y1,
"x2", x2,
"y2", y2,
"pivot-x", pivot_x,
"pivot-y", pivot_y,
"angle", angle,
NULL);
}
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimptoolrotategrid.h
* Copyright (C) 2017 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_TOOL_ROTATE_GRID_H__
#define __GIMP_TOOL_ROTATE_GRID_H__
#include "gimptooltransformgrid.h"
#define GIMP_TYPE_TOOL_ROTATE_GRID (gimp_tool_rotate_grid_get_type ())
#define GIMP_TOOL_ROTATE_GRID(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_TOOL_ROTATE_GRID, GimpToolRotateGrid))
#define GIMP_TOOL_ROTATE_GRID_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_TOOL_ROTATE_GRID, GimpToolRotateGridClass))
#define GIMP_IS_TOOL_ROTATE_GRID(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_TOOL_ROTATE_GRID))
#define GIMP_IS_TOOL_ROTATE_GRID_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_TOOL_ROTATE_GRID))
#define GIMP_TOOL_ROTATE_GRID_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_TOOL_ROTATE_GRID, GimpToolRotateGridClass))
typedef struct _GimpToolRotateGrid GimpToolRotateGrid;
typedef struct _GimpToolRotateGridPrivate GimpToolRotateGridPrivate;
typedef struct _GimpToolRotateGridClass GimpToolRotateGridClass;
struct _GimpToolRotateGrid
{
GimpToolTransformGrid parent_instance;
GimpToolRotateGridPrivate *private;
};
struct _GimpToolRotateGridClass
{
GimpToolTransformGridClass parent_class;
};
GType gimp_tool_rotate_grid_get_type (void) G_GNUC_CONST;
GimpToolWidget * gimp_tool_rotate_grid_new (GimpDisplayShell *shell,
gdouble x1,
gdouble y1,
gdouble x2,
gdouble y2,
gdouble pivot_x,
gdouble pivot_y,
gdouble angle);
#endif /* __GIMP_TOOL_ROTATE_GRID_H__ */
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimptoolsheargrid.c
* Copyright (C) 2017 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/>.
*/
#include "config.h"
#include <gegl.h>
#include <gtk/gtk.h>
#include "libgimpbase/gimpbase.h"
#include "libgimpmath/gimpmath.h"
#include "display-types.h"
#include "core/gimp-transform-utils.h"
#include "core/gimp-utils.h"
#include "gimpdisplayshell.h"
#include "gimptoolsheargrid.h"
#include "gimp-intl.h"
enum
{
PROP_0,
PROP_ORIENTATION,
PROP_SHEAR_X,
PROP_SHEAR_Y
};
struct _GimpToolShearGridPrivate
{
GimpOrientationType orientation;
gdouble shear_x;
gdouble shear_y;
gdouble last_x;
gdouble last_y;
};
/* local function prototypes */
static void gimp_tool_shear_grid_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_tool_shear_grid_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static gint gimp_tool_shear_grid_button_press (GimpToolWidget *widget,
const GimpCoords *coords,
guint32 time,
GdkModifierType state,
GimpButtonPressType press_type);
static void gimp_tool_shear_grid_motion (GimpToolWidget *widget,
const GimpCoords *coords,
guint32 time,
GdkModifierType state);
G_DEFINE_TYPE (GimpToolShearGrid, gimp_tool_shear_grid,
GIMP_TYPE_TOOL_TRANSFORM_GRID)
#define parent_class gimp_tool_shear_grid_parent_class
static void
gimp_tool_shear_grid_class_init (GimpToolShearGridClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GimpToolWidgetClass *widget_class = GIMP_TOOL_WIDGET_CLASS (klass);
object_class->set_property = gimp_tool_shear_grid_set_property;
object_class->get_property = gimp_tool_shear_grid_get_property;
widget_class->button_press = gimp_tool_shear_grid_button_press;
widget_class->motion = gimp_tool_shear_grid_motion;
g_object_class_install_property (object_class, PROP_ORIENTATION,
g_param_spec_enum ("orientation",
NULL, NULL,
GIMP_TYPE_ORIENTATION_TYPE,
GIMP_ORIENTATION_UNKNOWN,
GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
g_object_class_install_property (object_class, PROP_SHEAR_X,
g_param_spec_double ("shear-x",
NULL, NULL,
-GIMP_MAX_IMAGE_SIZE,
GIMP_MAX_IMAGE_SIZE,
0.0,
GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
g_object_class_install_property (object_class, PROP_SHEAR_Y,
g_param_spec_double ("shear-y",
NULL, NULL,
-GIMP_MAX_IMAGE_SIZE,
GIMP_MAX_IMAGE_SIZE,
0.0,
GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
g_type_class_add_private (klass, sizeof (GimpToolShearGridPrivate));
}
static void
gimp_tool_shear_grid_init (GimpToolShearGrid *grid)
{
grid->private = G_TYPE_INSTANCE_GET_PRIVATE (grid,
GIMP_TYPE_TOOL_SHEAR_GRID,
GimpToolShearGridPrivate);
g_object_set (grid,
"inside-function", GIMP_TRANSFORM_FUNCTION_SHEAR,
"outside-function", GIMP_TRANSFORM_FUNCTION_SHEAR,
"use-corner-handles", FALSE,
"use-perspective-handles", FALSE,
"use-side-handles", FALSE,
"use-shear-handles", FALSE,
"use-center-handle", FALSE,
"use-pivot-handle", FALSE,
NULL);
}
static void
gimp_tool_shear_grid_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GimpToolShearGrid *grid = GIMP_TOOL_SHEAR_GRID (object);
GimpToolShearGridPrivate *private = grid->private;
switch (property_id)
{
case PROP_ORIENTATION:
private->orientation = g_value_get_enum (value);
break;
case PROP_SHEAR_X:
private->shear_x = g_value_get_double (value);
break;
case PROP_SHEAR_Y:
private->shear_y = g_value_get_double (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_tool_shear_grid_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GimpToolShearGrid *grid = GIMP_TOOL_SHEAR_GRID (object);
GimpToolShearGridPrivate *private = grid->private;
switch (property_id)
{
case PROP_ORIENTATION:
g_value_set_enum (value, private->orientation);
break;
case PROP_SHEAR_X:
g_value_set_double (value, private->shear_x);
break;
case PROP_SHEAR_Y:
g_value_set_double (value, private->shear_y);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static gint
gimp_tool_shear_grid_button_press (GimpToolWidget *widget,
const GimpCoords *coords,
guint32 time,
GdkModifierType state,
GimpButtonPressType press_type)
{
GimpToolShearGrid *grid = GIMP_TOOL_SHEAR_GRID (widget);
GimpToolShearGridPrivate *private = grid->private;
private->last_x = coords->x;
private->last_y = coords->y;
return 1;
}
void
gimp_tool_shear_grid_motion (GimpToolWidget *widget,
const GimpCoords *coords,
guint32 time,
GdkModifierType state)
{
GimpToolShearGrid *grid = GIMP_TOOL_SHEAR_GRID (widget);
GimpToolShearGridPrivate *private = grid->private;
gdouble diffx = coords->x - private->last_x;
gdouble diffy = coords->y - private->last_y;
gdouble amount = 0.0;
GimpMatrix3 transform;
GimpMatrix3 *t;
gdouble x1, y1;
gdouble x2, y2;
gdouble tx1, ty1;
gdouble tx2, ty2;
gdouble tx3, ty3;
gdouble tx4, ty4;
gdouble current_x;
gdouble current_y;
g_object_get (widget,
"transform", &t,
"x1", &x1,
"y1", &y1,
"x2", &x2,
"y2", &y2,
NULL);
gimp_matrix3_transform_point (t, x1, y1, &tx1, &ty1);
gimp_matrix3_transform_point (t, x2, y1, &tx2, &ty2);
gimp_matrix3_transform_point (t, x1, y2, &tx3, &ty3);
gimp_matrix3_transform_point (t, x2, y2, &tx4, &ty4);
g_free (t);
current_x = coords->x;
current_y = coords->y;
diffx = current_x - private->last_x;
diffy = current_y - private->last_y;
/* If we haven't yet decided on which way to control shearing