[gthumb] rotate image: added ability to rotate dragging the image
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gthumb] rotate image: added ability to rotate dragging the image
- Date: Wed, 18 May 2011 18:42:03 +0000 (UTC)
commit 2f0cf2e606c9c34137fc5578d12bc521bcb9f483
Author: Paolo Bacchilega <paobac src gnome org>
Date: Wed May 18 20:41:01 2011 +0200
rotate image: added ability to rotate dragging the image
extensions/file_tools/cairo-rotate.c | 22 ++--
extensions/file_tools/cairo-rotate.h | 4 +-
extensions/file_tools/gth-file-tool-rotate.c | 34 +++++-
extensions/file_tools/gth-image-rotator.c | 162 ++++++++++++++++++++++++--
extensions/file_tools/gth-image-rotator.h | 6 +-
5 files changed, 202 insertions(+), 26 deletions(-)
---
diff --git a/extensions/file_tools/cairo-rotate.c b/extensions/file_tools/cairo-rotate.c
index bb78f5b..350c6c1 100644
--- a/extensions/file_tools/cairo-rotate.c
+++ b/extensions/file_tools/cairo-rotate.c
@@ -147,29 +147,29 @@ _cairo_image_surface_rotate_get_cropping_region (cairo_surface_t *image,
double
-_cairo_image_surface_rotate_get_align_angle (gboolean vertical,
- GdkPoint p1,
- GdkPoint p2)
+_cairo_image_surface_rotate_get_align_angle (gboolean vertical,
+ GdkPoint *p1,
+ GdkPoint *p2)
{
double angle;
if (! vertical) {
- if (p1.y == p2.y)
+ if (p1->y == p2->y)
return 0.0;
- if (p2.x > p1.x)
- angle = -atan2 (p2.y - p1.y, p2.x - p1.x);
+ if (p2->x > p1->x)
+ angle = -atan2 (p2->y - p1->y, p2->x - p1->x);
else
- angle = -atan2 (p1.y - p2.y, p1.x - p2.x);
+ angle = -atan2 (p1->y - p2->y, p1->x - p2->x);
}
else {
- if (p1.x == p2.x)
+ if (p1->x == p2->x)
return 0.0;
- if (p2.y > p1.y)
- angle = atan2 (p2.x - p1.x, p2.y - p1.y);
+ if (p2->y > p1->y)
+ angle = atan2 (p2->x - p1->x, p2->y - p1->y);
else
- angle = atan2 (p1.x - p2.x, p1.y - p2.y);
+ angle = atan2 (p1->x - p2->x, p1->y - p2->y);
}
angle = angle * 180.0 / G_PI;
diff --git a/extensions/file_tools/cairo-rotate.h b/extensions/file_tools/cairo-rotate.h
index 189ee49..a22fda5 100644
--- a/extensions/file_tools/cairo-rotate.h
+++ b/extensions/file_tools/cairo-rotate.h
@@ -38,8 +38,8 @@ void _cairo_image_surface_rotate_get_cropping_region (cairo_su
double p2,
GdkRectangle *region);
double _cairo_image_surface_rotate_get_align_angle (gboolean vertical,
- GdkPoint p1,
- GdkPoint p2);
+ GdkPoint *p1,
+ GdkPoint *p2);
cairo_surface_t * _cairo_image_surface_rotate (cairo_surface_t *image,
double angle,
gboolean high_quality,
diff --git a/extensions/file_tools/gth-file-tool-rotate.c b/extensions/file_tools/gth-file-tool-rotate.c
index ddda9dc..93f9d62 100644
--- a/extensions/file_tools/gth-file-tool-rotate.c
+++ b/extensions/file_tools/gth-file-tool-rotate.c
@@ -173,7 +173,7 @@ alignment_changed_cb (GthImageLineTool *line_tool,
gth_image_viewer_set_tool (GTH_IMAGE_VIEWER (viewer), self->priv->rotator);
gth_image_line_tool_get_points (line_tool, &p1, &p2);
- angle = _cairo_image_surface_rotate_get_align_angle (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("alignment_parallel_radiobutton"))), p1, p2);
+ angle = _cairo_image_surface_rotate_get_align_angle (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("alignment_parallel_radiobutton"))), &p1, &p2);
gtk_adjustment_set_value (self->priv->rotation_angle_adj, angle);
}
@@ -224,6 +224,9 @@ static void
reset_button_clicked_cb (GtkButton *button,
GthFileToolRotate *self)
{
+ gth_image_rotator_set_center (GTH_IMAGE_ROTATOR (self->priv->rotator),
+ cairo_image_surface_get_width (self->priv->image) / 2,
+ cairo_image_surface_get_height (self->priv->image) / 2);
gtk_adjustment_set_value (self->priv->rotation_angle_adj, 0.0);
}
@@ -346,6 +349,27 @@ resize_combobox_changed_cb (GtkComboBox *combo_box,
}
+static void
+rotator_angle_changed_cb (GthImageRotator *rotator,
+ double angle,
+ GthFileToolRotate *self)
+{
+ gtk_adjustment_set_value (self->priv->rotation_angle_adj, angle);
+}
+
+
+static void
+rotator_center_changed_cb (GthImageRotator *rotator,
+ int x,
+ int y,
+ GthFileToolRotate *self)
+{
+ gth_image_rotator_set_center (rotator, x, y);
+ update_crop_parameters (self);
+ update_crop_region (self);
+}
+
+
static GtkWidget *
gth_file_tool_rotate_get_options (GthFileTool *base)
{
@@ -495,6 +519,14 @@ gth_file_tool_rotate_get_options (GthFileTool *base)
"changed",
G_CALLBACK (resize_combobox_changed_cb),
self);
+ g_signal_connect (self->priv->rotator,
+ "angle-changed",
+ G_CALLBACK (rotator_angle_changed_cb),
+ self);
+ g_signal_connect (self->priv->rotator,
+ "center-changed",
+ G_CALLBACK (rotator_center_changed_cb),
+ self);
update_crop_parameters (self);
update_crop_region (self);
diff --git a/extensions/file_tools/gth-image-rotator.c b/extensions/file_tools/gth-image-rotator.c
index a3a151e..7a39d27 100644
--- a/extensions/file_tools/gth-image-rotator.c
+++ b/extensions/file_tools/gth-image-rotator.c
@@ -29,11 +29,15 @@
#define MIN4(a,b,c,d) MIN(MIN((a),(b)),MIN((c),(d)))
#define MAX4(a,b,c,d) MAX(MAX((a),(b)),MAX((c),(d)))
+#define G_2_PI (G_PI * 2)
+#define RAD_TO_DEG(x) ((x) * 180 / G_PI)
+#define DEG_TO_RAD(x) ((x) * G_PI / 180)
enum {
CHANGED,
CENTER_CHANGED,
+ ANGLE_CHANGED,
LAST_SIGNAL
};
@@ -65,6 +69,10 @@ struct _GthImageRotatorPrivate {
GdkPoint preview_center;
GdkRectangle clip_area;
cairo_matrix_t matrix;
+ gboolean dragging;
+ double angle_before_dragging;
+ GdkPoint drag_p1;
+ GdkPoint drag_p2;
GthFit original_fit_mode;
gboolean original_zoom_enabled;
};
@@ -75,12 +83,17 @@ gth_image_rotator_set_viewer (GthImageViewerTool *base,
GthImageViewer *viewer)
{
GthImageRotator *self = GTH_IMAGE_ROTATOR (base);
+ GdkCursor *cursor;
self->priv->viewer = viewer;
self->priv->original_fit_mode = gth_image_viewer_get_fit_mode (GTH_IMAGE_VIEWER (viewer));
self->priv->original_zoom_enabled = gth_image_viewer_get_zoom_enabled (GTH_IMAGE_VIEWER (viewer));
gth_image_viewer_set_fit_mode (GTH_IMAGE_VIEWER (viewer), GTH_FIT_SIZE_IF_LARGER);
gth_image_viewer_set_zoom_enabled (GTH_IMAGE_VIEWER (viewer), FALSE);
+
+ cursor = gdk_cursor_new (GDK_LEFT_PTR);
+ gth_image_viewer_set_cursor (self->priv->viewer, cursor);
+ gdk_cursor_unref (cursor);
}
@@ -352,6 +365,22 @@ paint_grid (GthImageRotator *self,
static void
+paint_point (GthImageRotator *self,
+ GdkEventExpose *event,
+ cairo_t *cr,
+ GdkPoint *p)
+{
+ double radius = 10.0;
+
+ cairo_move_to (cr, p->x - radius, p->y - radius);
+ cairo_line_to (cr, p->x + radius, p->y + radius);
+ cairo_move_to (cr, p->x - radius, p->y + radius);
+ cairo_line_to (cr, p->x + radius, p->y - radius);
+ cairo_stroke (cr);
+}
+
+
+static void
gth_image_rotator_expose (GthImageViewerTool *base,
GdkEventExpose *event,
cairo_t *cr)
@@ -401,6 +430,22 @@ gth_image_rotator_expose (GthImageViewerTool *base,
paint_grid (self, event, cr);
}
+ if (self->priv->dragging) {
+ GdkPoint center;
+
+ cairo_set_antialias (cr, CAIRO_ANTIALIAS_DEFAULT);
+ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+
+ center.x = self->priv->center.x * self->priv->preview_zoom + self->priv->preview_image_area.x;
+ center.y = self->priv->center.y * self->priv->preview_zoom + self->priv->preview_image_area.y;
+ paint_point (self, event, cr, ¢er);
+
+ /* used for debugging purposes
+ paint_point (self, event, cr, &self->priv->drag_p1);
+ paint_point (self, event, cr, &self->priv->drag_p2);
+ */
+ }
+
cairo_restore (cr);
}
@@ -409,7 +454,20 @@ static gboolean
gth_image_rotator_button_release (GthImageViewerTool *base,
GdkEventButton *event)
{
- /* FIXME */
+ GthImageRotator *self = GTH_IMAGE_ROTATOR (base);
+ GdkCursor *cursor;
+
+ self->priv->dragging = FALSE;
+ self->priv->drag_p1.x = 0;
+ self->priv->drag_p1.y = 0;
+ self->priv->drag_p2.x = 0;
+ self->priv->drag_p2.y = 0;
+
+ cursor = gdk_cursor_new (GDK_LEFT_PTR);
+ gth_image_viewer_set_cursor (self->priv->viewer, cursor);
+ gdk_cursor_unref (cursor);
+
+ gtk_widget_queue_draw (GTK_WIDGET (self->priv->viewer));
return FALSE;
}
@@ -426,18 +484,89 @@ gth_image_rotator_button_press (GthImageViewerTool *base,
x = (event->x - self->priv->preview_image_area.x) / self->priv->preview_zoom;
y = (event->y - self->priv->preview_image_area.y) / self->priv->preview_zoom;
- gth_image_rotator_set_center (self, (int) x, (int) y);
+ g_signal_emit (self, signals[CENTER_CHANGED], 0, (int) x, (int) y);
+ }
+
+ if (event->type == GDK_BUTTON_PRESS) {
+ self->priv->dragging = FALSE;
+ self->priv->drag_p1.x = event->x;
+ self->priv->drag_p1.y = event->y;
}
return FALSE;
}
+static double
+get_angle (GdkPoint *p1,
+ GdkPoint *p2)
+{
+ double a = 0.0;
+ int x, y;
+
+ x = p2->x - p1->x;
+ y = p2->y - p1->y;
+ if (x >= 0) {
+ if (y >= 0)
+ a = atan2 (y, x);
+ else
+ a = G_2_PI - atan2 (- y, x);
+ }
+ else {
+ if (y >= 0)
+ a = G_PI - atan2 (y, - x);
+ else
+ a = G_PI + atan2 (- y, - x);
+ }
+
+ return a;
+}
+
+
static gboolean
gth_image_rotator_motion_notify (GthImageViewerTool *base,
GdkEventMotion *event)
{
- /* FIXME */
+ GthImageRotator *self = GTH_IMAGE_ROTATOR (base);
+
+ if (! self->priv->dragging
+ && gtk_drag_check_threshold (GTK_WIDGET (self->priv->viewer),
+ self->priv->drag_p1.x,
+ self->priv->drag_p1.y,
+ self->priv->drag_p2.x,
+ self->priv->drag_p2.y))
+ {
+ GdkCursor *cursor;
+
+ self->priv->angle_before_dragging = self->priv->angle;
+ self->priv->dragging = TRUE;
+
+ cursor = gdk_cursor_new_from_name (gtk_widget_get_display (GTK_WIDGET (self->priv->viewer)), "grabbing");
+ gth_image_viewer_set_cursor (self->priv->viewer, cursor);
+ if (cursor != NULL)
+ gdk_cursor_unref (cursor);
+ }
+
+ if (self->priv->dragging) {
+ GdkPoint center;
+ double angle1;
+ double angle2;
+ double angle;
+
+ self->priv->drag_p2.x = event->x;
+ self->priv->drag_p2.y = event->y;
+
+ center.x = self->priv->center.x * self->priv->preview_zoom + self->priv->preview_image_area.x;
+ center.y = self->priv->center.y * self->priv->preview_zoom + self->priv->preview_image_area.y;
+
+ angle1 = get_angle (¢er, &self->priv->drag_p1);
+ angle2 = get_angle (¢er, &self->priv->drag_p2);
+ if (angle2 < angle1 - G_PI)
+ angle2 = G_2_PI + angle2;
+ angle = self->priv->angle_before_dragging + (angle2 - angle1);
+
+ g_signal_emit (self, signals[ANGLE_CHANGED], 0, CLAMP (RAD_TO_DEG (angle), -90.0, 90));
+ }
return FALSE;
}
@@ -473,6 +602,7 @@ gth_image_rotator_instance_init (GthImageRotator *self)
self->priv->crop_region.y = 0;
self->priv->crop_region.width = 0;
self->priv->crop_region.height = 0;
+ self->priv->dragging = FALSE;
}
@@ -517,9 +647,20 @@ gth_image_rotator_class_init (GthImageRotatorClass *class)
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GthImageRotatorClass, center_changed),
NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
+ gth_marshal_VOID__INT_INT,
+ G_TYPE_NONE,
+ 2,
+ G_TYPE_INT,
+ G_TYPE_INT);
+ signals[ANGLE_CHANGED] = g_signal_new ("angle-changed",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GthImageRotatorClass, angle_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__DOUBLE,
G_TYPE_NONE,
- 0);
+ 1,
+ G_TYPE_DOUBLE);
}
@@ -596,10 +737,8 @@ gth_image_rotator_set_grid_type (GthImageRotator *self,
return;
self->priv->grid_type = grid_type;
- gtk_widget_queue_draw (GTK_WIDGET (self->priv->viewer));
- /*g_signal_emit (G_OBJECT (self),
- signals[GRID_VISIBILITY_CHANGED],
- 0);*/
+ if (self->priv->viewer != NULL)
+ gtk_widget_queue_draw (GTK_WIDGET (self->priv->viewer));
}
@@ -622,7 +761,7 @@ gth_image_rotator_set_center (GthImageRotator *self,
if (self->priv->viewer != NULL)
gtk_widget_queue_draw (GTK_WIDGET (self->priv->viewer));
- g_signal_emit (self, signals[CENTER_CHANGED], 0);
+ g_signal_emit (self, signals[CHANGED], 0);
}
@@ -642,10 +781,11 @@ gth_image_rotator_set_angle (GthImageRotator *self,
{
double radiants;
- radiants = angle * M_PI / 180.0;
+ radiants = DEG_TO_RAD (angle);
if (radiants == self->priv->angle)
return;
self->priv->angle = radiants;
+
_gth_image_rotator_update_tranformation_matrix (self);
if (self->priv->viewer != NULL)
diff --git a/extensions/file_tools/gth-image-rotator.h b/extensions/file_tools/gth-image-rotator.h
index b811bc0..b1c1f45 100644
--- a/extensions/file_tools/gth-image-rotator.h
+++ b/extensions/file_tools/gth-image-rotator.h
@@ -58,7 +58,11 @@ struct _GthImageRotatorClass
/*< signals >*/
void (* changed) (GthImageRotator *rotator);
- void (* center_changed) (GthImageRotator *rotator);
+ void (* center_changed) (GthImageRotator *rotator,
+ int x,
+ int y);
+ void (* angle_changed) (GthImageRotator *rotator,
+ double angle);
};
GType gth_image_rotator_get_type (void);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]