app: derive GimpMeasureTool from GimpTransformTool

Derive GimpMeasureTool from GimpTransformTool (and
GimpMeasureOptions from GimpTransformOptions), so that we can reuse
GimpTransformTool's logic for the "straighten" function.  This
simplifies the code, aligns the measure tool with the rest of the
transform tools in terms of transform-related options (it can now
transform selections and paths, in addition to layers, and the
resampling method and clipping behavior are adjustable,) and fixes
straightening of layer groups.

Rename the function from "auto straighten" to just "straighten".

Don't resize the canvas after straightening.  Since we only
transform the active layer, and not the entire image, resizing the
canvas doesn't make much sense.

When in 3-point mode, rotate the second point toward the third
point, rather than toward the x-axis.
This commit is contained in:
Ell
2018-06-09 16:35:46 -04:00
parent 1dbe765905
commit b0cf2e435a
4 changed files with 142 additions and 117 deletions

View File

@ -52,7 +52,7 @@ static void gimp_measure_options_get_property (GObject *object,
G_DEFINE_TYPE (GimpMeasureOptions, gimp_measure_options,
GIMP_TYPE_TOOL_OPTIONS)
GIMP_TYPE_TRANSFORM_OPTIONS)
static void
@ -121,20 +121,34 @@ gimp_measure_options_gui (GimpToolOptions *tool_options)
GObject *config = G_OBJECT (tool_options);
GtkWidget *vbox = gimp_tool_options_gui (tool_options);
GtkWidget *button;
GtkWidget *frame;
GtkWidget *vbox2;
/* the use_info_window toggle button */
button = gimp_prop_check_button_new (config, "use-info-window", NULL);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_widget_show (button);
button = gtk_button_new_with_label (_("Auto straighten"));
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
/* the straighten frame */
frame = gimp_frame_new (_("Straighten"));
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
/* the transform options */
vbox2 = gimp_transform_options_gui (tool_options, FALSE, TRUE, TRUE);
gtk_container_add (GTK_CONTAINER (frame), vbox2);
gtk_widget_show (vbox2);
/* the straighten button */
button = gtk_button_new_with_label (_("Straighten"));
gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
gtk_widget_set_sensitive (button, FALSE);
gimp_help_set_help_data (button,
_("Rotate the active layer using the measurement line as horizon"),
_("Rotate the active layer, selection or path "
"by the measured angle"),
NULL);
gtk_widget_show (button);
GIMP_MEASURE_OPTIONS (tool_options)->auto_straighten = button;
GIMP_MEASURE_OPTIONS (tool_options)->straighten = button;
return vbox;
}

View File

@ -19,7 +19,7 @@
#define __GIMP_MEASURE_OPTIONS_H__
#include "core/gimptooloptions.h"
#include "gimptransformoptions.h"
#define GIMP_TYPE_MEASURE_OPTIONS (gimp_measure_options_get_type ())
@ -30,15 +30,20 @@
#define GIMP_MEASURE_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_MEASURE_OPTIONS, GimpMeasureOptionsClass))
typedef struct _GimpMeasureOptions GimpMeasureOptions;
typedef struct _GimpToolOptionsClass GimpMeasureOptionsClass;
typedef struct _GimpMeasureOptions GimpMeasureOptions;
typedef struct _GimpMeasureOptionsClass GimpMeasureOptionsClass;
struct _GimpMeasureOptions
{
GimpToolOptions parent_instance;
GimpTransformOptions parent_instance;
gboolean use_info_window;
GtkWidget *auto_straighten;
gboolean use_info_window;
GtkWidget *straighten;
};
struct _GimpMeasureOptionsClass
{
GimpTransformOptionsClass parent_class;
};

View File

@ -30,17 +30,10 @@
#include "tools-types.h"
#include "config/gimpcoreconfig.h"
#include "core/gimp.h"
#include "core/gimpdrawable.h"
#include "core/gimpdrawable-transform.h"
#include "core/gimpimage.h"
#include "core/gimpimage-guides.h"
#include "core/gimpimage-resize.h"
#include "core/gimpimage-undo.h"
#include "core/gimpimage-undo-push.h"
#include "core/gimpitem-linked.h"
#include "core/gimpprogress.h"
#include "core/gimp-transform-utils.h"
@ -82,6 +75,9 @@ static void gimp_measure_tool_motion (GimpTool *tool,
GdkModifierType state,
GimpDisplay *display);
static void gimp_measure_tool_recalc_matrix (GimpTransformTool *tr_tool);
static gchar * gimp_measure_tool_get_undo_desc (GimpTransformTool *tr_tool);
static void gimp_measure_tool_compass_changed (GimpToolWidget *widget,
GimpMeasureTool *measure);
static void gimp_measure_tool_compass_response(GimpToolWidget *widget,
@ -112,10 +108,10 @@ static GimpToolGui * gimp_measure_tool_dialog_new (GimpMeasureTool *measur
static void gimp_measure_tool_dialog_update (GimpMeasureTool *measure,
GimpDisplay *display);
static void gimp_measure_tool_rotate_active_layer (GtkWidget *button,
static void gimp_measure_tool_straighten_clicked (GtkWidget *button,
GimpMeasureTool *measure);
G_DEFINE_TYPE (GimpMeasureTool, gimp_measure_tool, GIMP_TYPE_DRAW_TOOL)
G_DEFINE_TYPE (GimpMeasureTool, gimp_measure_tool, GIMP_TYPE_TRANSFORM_TOOL)
#define parent_class gimp_measure_tool_parent_class
@ -140,12 +136,18 @@ gimp_measure_tool_register (GimpToolRegisterCallback callback,
static void
gimp_measure_tool_class_init (GimpMeasureToolClass *klass)
{
GimpToolClass *tool_class = GIMP_TOOL_CLASS (klass);
GimpToolClass *tool_class = GIMP_TOOL_CLASS (klass);
GimpTransformToolClass *tr_class = GIMP_TRANSFORM_TOOL_CLASS (klass);
tool_class->control = gimp_measure_tool_control;
tool_class->button_press = gimp_measure_tool_button_press;
tool_class->button_release = gimp_measure_tool_button_release;
tool_class->motion = gimp_measure_tool_motion;
tr_class->recalc_matrix = gimp_measure_tool_recalc_matrix;
tr_class->get_undo_desc = gimp_measure_tool_get_undo_desc;
tr_class->progress_text = _("Straightening");
}
static void
@ -278,6 +280,64 @@ gimp_measure_tool_motion (GimpTool *tool,
}
}
static void
gimp_measure_tool_recalc_matrix (GimpTransformTool *tr_tool)
{
GimpMeasureTool *measure = GIMP_MEASURE_TOOL (tr_tool);
GimpVector2 p0;
GimpVector2 p1;
GimpVector2 p2;
gdouble angle;
if (measure->n_points < 2)
{
tr_tool->transform_valid = FALSE;
return;
}
p0.x = measure->x[0];
p0.y = measure->y[0];
p1.x = measure->x[1];
p1.y = measure->y[1];
if (measure->n_points == 2)
{
p2.x = p1.x;
p2.y = p0.y;
if (p2.x == p0.x)
p2.x--;
}
else
{
p2.x = measure->x[2];
p2.y = measure->y[2];
}
gimp_vector2_sub (&p1, &p1, &p0);
gimp_vector2_sub (&p2, &p2, &p0);
gimp_vector2_normalize (&p1);
gimp_vector2_normalize (&p2);
angle = atan2 (gimp_vector2_cross_product (&p1, &p2).x,
gimp_vector2_inner_product (&p1, &p2));
gimp_matrix3_identity (&tr_tool->transform);
gimp_transform_matrix_rotate_center (&tr_tool->transform,
p0.x, p0.y, angle);
tr_tool->transform_valid = TRUE;
}
static gchar *
gimp_measure_tool_get_undo_desc (GimpTransformTool *tr_tool)
{
return g_strdup (_("Straighten"));
}
static void
gimp_measure_tool_compass_changed (GimpToolWidget *widget,
GimpMeasureTool *measure)
@ -294,7 +354,7 @@ gimp_measure_tool_compass_changed (GimpToolWidget *widget,
"y3", &measure->y[2],
NULL);
gtk_widget_set_sensitive (options->auto_straighten, measure->n_points >= 2);
gtk_widget_set_sensitive (options->straighten, measure->n_points >= 2);
gimp_measure_tool_dialog_update (measure, GIMP_TOOL (measure)->display);
}
@ -400,8 +460,8 @@ gimp_measure_tool_start (GimpMeasureTool *measure,
g_signal_connect (measure->widget, "create-guides",
G_CALLBACK (gimp_measure_tool_compass_create_guides),
measure);
g_signal_connect (options->auto_straighten, "clicked",
G_CALLBACK (gimp_measure_tool_rotate_active_layer),
g_signal_connect (options->straighten, "clicked",
G_CALLBACK (gimp_measure_tool_straighten_clicked),
measure);
tool->display = display;
@ -415,7 +475,7 @@ gimp_measure_tool_halt (GimpMeasureTool *measure)
GimpMeasureOptions *options = GIMP_MEASURE_TOOL_GET_OPTIONS (measure);
GimpTool *tool = GIMP_TOOL (measure);
gtk_widget_set_sensitive (options->auto_straighten, FALSE);
gtk_widget_set_sensitive (options->straighten, FALSE);
if (tool->display)
gimp_tool_pop_status (tool, tool->display);
@ -423,8 +483,8 @@ gimp_measure_tool_halt (GimpMeasureTool *measure)
if (gimp_draw_tool_is_active (GIMP_DRAW_TOOL (measure)))
gimp_draw_tool_stop (GIMP_DRAW_TOOL (measure));
g_signal_handlers_disconnect_by_func (options->auto_straighten,
G_CALLBACK (gimp_measure_tool_rotate_active_layer),
g_signal_handlers_disconnect_by_func (options->straighten,
G_CALLBACK (gimp_measure_tool_straighten_clicked),
measure);
gimp_draw_tool_set_widget (GIMP_DRAW_TOOL (tool), NULL);
@ -806,84 +866,30 @@ gimp_measure_tool_dialog_new (GimpMeasureTool *measure)
}
static void
gimp_measure_tool_rotate_active_layer (GtkWidget *button,
GimpMeasureTool *measure)
gimp_measure_tool_straighten_clicked (GtkWidget *button,
GimpMeasureTool *measure)
{
GimpMeasureOptions *options = GIMP_MEASURE_TOOL_GET_OPTIONS (measure);
GimpDisplay *display = GIMP_TOOL (measure)->display;
GimpImage *image = gimp_display_get_image (display);
GimpContext *context = GIMP_CONTEXT (options);
GimpDrawable *item = gimp_image_get_active_drawable (image);
GimpProgress *progress;
gdouble ax = measure->x[1] - measure->x[0];
gdouble ay = measure->y[1] - measure->y[0];
gdouble angle;
GimpMatrix3 matrix;
gint offset_x;
gint offset_y;
gdouble x0, y0, x1, y1;
GimpTool *tool = GIMP_TOOL (measure);
GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (measure);
gdouble x0, y0;
gdouble x1, y1;
if (! item)
return;
angle = atan (ay / ax);
gimp_matrix3_identity (&matrix);
gimp_transform_matrix_rotate_center (&matrix, measure->x[0], measure->y[0], angle);
progress = gimp_progress_start (GIMP_PROGRESS (measure), FALSE,
"%s", _("Straightening"));
/* Start a transform undo group */
gimp_image_undo_group_start (image,
GIMP_UNDO_GROUP_TRANSFORM,
C_("undo-type", "Transform"));
if (gimp_item_get_linked (GIMP_ITEM (item)))
if (gimp_transform_tool_transform (tr_tool, tool->display))
{
gimp_item_linked_transform (GIMP_ITEM (item), context, &matrix,
GIMP_TRANSFORM_BACKWARD,
display->gimp->config->interpolation_type,
GIMP_TRANSFORM_RESIZE_ADJUST,
progress);
gimp_matrix3_transform_point (&tr_tool->transform,
measure->x[0],
measure->y[0],
&x0, &y0);
gimp_matrix3_transform_point (&tr_tool->transform,
measure->x[1],
measure->y[1],
&x1, &y1);
g_object_set (measure->widget,
"x1", SIGNED_ROUND (x0),
"y1", SIGNED_ROUND (y0),
"x2", SIGNED_ROUND (x1),
"y2", SIGNED_ROUND (y1),
NULL);
}
else
{
gimp_drawable_transform_affine (GIMP_DRAWABLE (item),
context,
&matrix,
GIMP_TRANSFORM_BACKWARD,
display->gimp->config->interpolation_type,
GIMP_TRANSFORM_RESIZE_ADJUST,
progress);
}
gimp_image_resize_to_layers (image, context, &offset_x, &offset_y,
NULL, NULL, progress);
/* Keep and transform the measurement points as well. */
gimp_matrix3_identity (&matrix);
gimp_transform_matrix_rotate_center (&matrix, measure->x[0], measure->y[0], - angle);
gimp_matrix3_translate (&matrix, offset_x, offset_y);
gimp_matrix3_transform_point (&matrix,
measure->x[0],
measure->y[0],
&x0, &y0);
gimp_matrix3_transform_point (&matrix,
measure->x[1],
measure->y[1],
&x1, &y1);
g_object_set (measure->widget,
"x1", (gint) x0,
"y1", (gint) y0,
"x2", (gint) x1,
"y2", (gint) y1,
NULL);
/* push the undo group end */
gimp_image_undo_group_end (image);
if (progress)
gimp_progress_end (progress);
gimp_image_flush (image);
}

View File

@ -19,7 +19,7 @@
#define __GIMP_MEASURE_TOOL_H__
#include "gimpdrawtool.h"
#include "gimptransformtool.h"
#define GIMP_TYPE_MEASURE_TOOL (gimp_measure_tool_get_type ())
@ -37,26 +37,26 @@ typedef struct _GimpMeasureToolClass GimpMeasureToolClass;
struct _GimpMeasureTool
{
GimpDrawTool parent_instance;
GimpTransformTool parent_instance;
GimpToolWidget *widget;
GimpToolWidget *grab_widget;
GimpToolWidget *widget;
GimpToolWidget *grab_widget;
gint n_points;
gint x[3];
gint y[3];
gint n_points;
gint x[3];
gint y[3];
GimpToolGui *gui;
GtkWidget *distance_label[2];
GtkWidget *angle_label[2];
GtkWidget *width_label[2];
GtkWidget *height_label[2];
GtkWidget *unit_label[4];
GimpToolGui *gui;
GtkWidget *distance_label[2];
GtkWidget *angle_label[2];
GtkWidget *width_label[2];
GtkWidget *height_label[2];
GtkWidget *unit_label[4];
};
struct _GimpMeasureToolClass
{
GimpDrawToolClass parent_class;
GimpTransformToolClass parent_class;
};