[gtk+/wip/baedert/gtkimageview: 145/255] Simple rotation working
- From: Timm Bäder <baedert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/baedert/gtkimageview: 145/255] Simple rotation working
- Date: Thu, 12 May 2016 17:30:06 +0000 (UTC)
commit a0a173668c8cba1b51c7c482ecc5a358a02833c0
Author: Timm Bäder <mail baedert org>
Date: Sun Jan 17 14:10:12 2016 +0100
Simple rotation working
demos/gtk-demo/image_view.c | 2 +-
gtk/gtkimageview.c | 291 +++++++++++++++++++++----------------------
2 files changed, 142 insertions(+), 151 deletions(-)
---
diff --git a/demos/gtk-demo/image_view.c b/demos/gtk-demo/image_view.c
index 3bdcfe4..acbe76f 100644
--- a/demos/gtk-demo/image_view.c
+++ b/demos/gtk-demo/image_view.c
@@ -127,7 +127,7 @@ load_pixbuf_button_clicked_cb ()
GdkPixbuf *pixbuf;
/* I really hope you have this. */
- pixbuf = gdk_pixbuf_new_from_file ("/home/baedert/imageview.png",
+ pixbuf = gdk_pixbuf_new_from_file ("/home/baedert/imageview2.png",
NULL);
g_assert (pixbuf != NULL);
diff --git a/gtk/gtkimageview.c b/gtk/gtkimageview.c
index 8c6782c..489c9c1 100644
--- a/gtk/gtkimageview.c
+++ b/gtk/gtkimageview.c
@@ -25,6 +25,8 @@ double _new_y;
typedef struct
{
+ double hupper;
+ double vupper;
double hvalue;
double vvalue;
double angle;
@@ -32,6 +34,10 @@ typedef struct
} State;
+int p_x[360];
+int p_y[360];
+
+
struct _GtkImageViewPrivate
{
double scale;
@@ -147,6 +153,8 @@ gtk_image_view_get_current_state (GtkImageView *image_view,
state->vvalue = gtk_adjustment_get_value (priv->vadjustment);
state->scale = priv->scale;
state->angle = priv->angle;
+ state->hupper = gtk_adjustment_get_upper (priv->hadjustment);
+ state->vupper = gtk_adjustment_get_upper (priv->vadjustment);
}
static gchar *
@@ -192,18 +200,18 @@ bounding_box_for_angle (GtkImageView *image_view,
double upper_right_x, upper_right_y;
double upper_left_x, upper_left_y;
double scale;
- /*static double cached_width;*/
- /*static double cached_height;*/
- /*static double cached_scale;*/
+ static double cached_width;
+ static double cached_height;
+ static double cached_scale;
- /*if (priv->size_valid)*/
- /*{*/
- /**width = cached_width;*/
- /**height = cached_height;*/
- /*if (scale_out)*/
- /**scale_out = cached_scale;*/
- /*return;*/
- /*}*/
+ if (priv->size_valid)
+ {
+ *width = cached_width;
+ *height = cached_height;
+ if (scale_out)
+ *scale_out = cached_scale;
+ return;
+ }
if (!priv->image_surface)
@@ -222,7 +230,7 @@ bounding_box_for_angle (GtkImageView *image_view,
upper_left_degrees = DEG_TO_RAD (angle) + atan (image_height / -image_width);
- r = sqrtf ((image_width / 2) * (image_width / 2) + (image_height / 2) * (image_height / 2));
+ r = sqrt ((image_width / 2) * (image_width / 2) + (image_height / 2) * (image_height / 2));
upper_right_x = r * cos (upper_right_degrees);
upper_right_y = r * sin (upper_right_degrees);
@@ -253,7 +261,7 @@ bounding_box_for_angle (GtkImageView *image_view,
}
}
- /*cached_scale = scale;*/
+ cached_scale = scale;
if (scale_out)
*scale_out = scale;
@@ -265,10 +273,10 @@ bounding_box_for_angle (GtkImageView *image_view,
}
- *width = bb_width * scale;
- *height = bb_height * scale;
- /*priv->size_valid = TRUE;*/
+ *width = cached_width = bb_width * scale;
+ *height = cached_height = bb_height * scale;
+ priv->size_valid = TRUE;
}
@@ -278,90 +286,54 @@ bounding_box_for_angle (GtkImageView *image_view,
static void
gtk_image_view_fix_point_rotate (GtkImageView *image_view,
- double angle_before,
- int anchor_x,
- int anchor_y,
+ double anchor_x,
+ double anchor_y,
State *old_state)
{
GtkImageViewPrivate *priv = gtk_image_view_get_instance_private (image_view);
- /*double new_angle = priv->angle;*/
- int bb_width;
- int bb_height;
- double center_x;
- double center_y;
- /*double value_x;*/
- /*double value_y;*/
g_assert (priv->anchor_x != -1 &&
priv->anchor_y != -1);
- double center_x_before;
- double center_y_before;
-
g_message ("Old State: %s", state_str (old_state));
+ g_message ("New angle: %f", priv->angle);
+ g_message ("Anchor: %f/%f", priv->anchor_x, priv->anchor_y);
- bounding_box_for_angle (image_view,
- old_state->angle,
- &bb_width,
- &bb_height,
- NULL);
-
- center_x_before = bb_width / 2.0;
- center_y_before = bb_height / 2.0;
-
- center_x_before -= old_state->hvalue;
- center_y_before -= old_state->vvalue;
-
- center_x_before += anchor_x;
- center_y_before += anchor_y;
-
-
- bounding_box_for_angle (image_view,
- priv->angle,
- &bb_width,
- &bb_height,
- NULL);
-
- /*
- * XXX The anchor point changes when the angle changes...
- */
-
+ /* 1) Calculate the angle of our anchor point. */
+ /*double anchor_angle = atan (priv->anchor_y / priv->anchor_x);*/
+ double anchor_angle = atan2 (priv->anchor_y, priv->anchor_x);
- /* Once we get here, we assume the adjustments are already updated. */
- g_assert (gtk_adjustment_get_upper (priv->hadjustment) == bb_width);
- g_assert (gtk_adjustment_get_upper (priv->vadjustment) == bb_height);
+ double anchor_length = sqrt ((priv->anchor_x * priv->anchor_x) + (priv->anchor_y * priv->anchor_y));
+ g_message ("Anchor angle: %f", RAD_TO_DEG (anchor_angle));
+ g_message ("Anchor length: %f", anchor_length);
- /*
- * We know that the given anchor_x/anchor_y are relatieve to the
- * old_state.
- * So, the new task is to compute where the position of anchor_x/anchor_y
- * are now that we changed priv->angle!
- *
- * After this, we need to update the current anchor point!
- * But only because it's relative to the center...
- */
+ /* 2) Calculate the position of our anchor point with increased angle */
+ double angle_diff = priv->angle - old_state->angle;
+ anchor_angle += DEG_TO_RAD (angle_diff);
+ /*anchor_angle += DEG_TO_RAD (old_state->angle);*/
+ g_message ("anchor angle after: %f", RAD_TO_DEG (anchor_angle));
- /*g_message ("bounding box: %d/%d", bb_width, bb_height);*/
- center_x = bb_width / 2.0;
- center_y = bb_height / 2.0;
+ g_message ("Angle got increased by %f", angle_diff);
+ double new_anchor_x = cos (anchor_angle) * anchor_length;
+ double new_anchor_y = sin (anchor_angle) * anchor_length;
+ g_message ("New anchor: %f, %f", new_anchor_x, new_anchor_y);
- // XXX Now that anchor_x/anchor_y are relative to the bounding box center,
- // what are center_x/center_y relative to?
- center_x -= gtk_adjustment_get_value (priv->hadjustment);
- center_y -= gtk_adjustment_get_value (priv->vadjustment);
+ /* Once we get here, we assume the adjustments are already updated. */
+ /*g_assert (gtk_adjustment_get_upper (priv->hadjustment) == bb_width);*/
+ /*g_assert (gtk_adjustment_get_upper (priv->vadjustment) == bb_height);*/
- center_x += anchor_x;
- center_y += anchor_y;
+ double hupper_diff = gtk_adjustment_get_upper (priv->hadjustment) - old_state->hupper;
+ double vupper_diff = gtk_adjustment_get_upper (priv->vadjustment) - old_state->vupper;
+ g_message ("hupper_diff: %f", hupper_diff);
+ g_message ("vupper_diff: %f", vupper_diff);
- /*double c = center_x;*/
- /*g_message ("%f, %f, %f, %f", a, b, c, gtk_adjustment_get_value (priv->hadjustment));*/
/*
* Facts:
@@ -379,25 +351,30 @@ gtk_image_view_fix_point_rotate (GtkImageView *image_view,
*
*/
- g_message ("Anchor: %f/%f", priv->anchor_x, priv->anchor_y);
- g_message ("Center before: %f/%f", center_x_before, center_y_before);
- g_message ("Center: %f/%f (This can be off)", center_x, center_y);
+ gtk_adjustment_set_value (priv->hadjustment,
+ gtk_adjustment_get_value (priv->hadjustment) + hupper_diff / 2.0);
+ gtk_adjustment_set_value (priv->vadjustment,
+ gtk_adjustment_get_value (priv->vadjustment) + vupper_diff / 2.0);
+
+
+ /*double diff_x = new_anchor_x - priv->anchor_x;*/
+ double diff_x = priv->anchor_x - new_anchor_x;
+ double diff_y = priv->anchor_y - new_anchor_y;
+ /*double diff_y = new_anchor_y - priv->anchor_y;// + vupper_diff / 2.0;*/
- // TODO: Fix the calculations for non-center points,
- // since our anchor point is now 150/150
- double diff_x = center_x - center_x_before;
- double diff_y = center_y - center_y_before;
g_message ("Diff: %f/%f", diff_x, diff_y);
gtk_adjustment_set_value (priv->hadjustment,
- gtk_adjustment_get_value (priv->hadjustment) + diff_x);
+ gtk_adjustment_get_value (priv->hadjustment) - diff_x);
gtk_adjustment_set_value (priv->vadjustment,
- gtk_adjustment_get_value (priv->vadjustment) + diff_y);
+ gtk_adjustment_get_value (priv->vadjustment) - diff_y);
+
g_message ("-------------------------");
+ gtk_widget_queue_draw (GTK_WIDGET (image_view));
}
static void
@@ -446,14 +423,14 @@ gesture_rotate_end_cb (GtkGesture *gesture,
}
static void
-gesture_rotate_cancel_cb (GtkGesture *gesture,
+gesture_rotate_cancel_cb (GtkGesture *gesture,
GdkEventSequence *sequence,
gpointer user_data)
{
GtkImageViewPrivate *priv = gtk_image_view_get_instance_private (user_data);
gtk_image_view_set_angle (user_data, priv->gesture_start_angle);
priv->in_rotate = FALSE;
- priv->gesture_start_angle = FALSE;
+ priv->gesture_start_angle = FALSE; // XXX wow, lol
/*priv->anchor_x = -1;*/
/*priv->anchor_y = -1;*/
@@ -468,7 +445,7 @@ gesture_angle_changed_cb (GtkGestureRotate *gesture,
{
GtkImageViewPrivate *priv = gtk_image_view_get_instance_private (GTK_IMAGE_VIEW (widget));
double new_angle;
- double old_angle;
+ /*double old_angle;*/
if (!priv->rotate_gesture_enabled)
{
@@ -490,7 +467,7 @@ gesture_angle_changed_cb (GtkGestureRotate *gesture,
priv->size_valid = FALSE;
/* Don't notify */
- old_angle = priv->angle;
+ /*old_angle = priv->angle;*/
priv->angle = new_angle;
gtk_image_view_update_adjustments (GTK_IMAGE_VIEW (widget));
@@ -501,6 +478,8 @@ gesture_angle_changed_cb (GtkGestureRotate *gesture,
/*priv->anchor_x,*/
/*priv->anchor_y);*/
+ // XXX Even if fit_allocation is not set, we still don't need to query a resize
+ // if we are in a scrolledwindow, right?
if (priv->fit_allocation)
gtk_widget_queue_draw (widget);
else
@@ -529,14 +508,14 @@ gtk_image_view_compute_bounding_box (GtkImageView *image_view,
static int cached_height;
static double cached_scale;
- /*if (priv->size_valid)*/
- /*{*/
- /**width = cached_width;*/
- /**height = cached_height;*/
- /*if (scale_out)*/
- /**scale_out = cached_scale;*/
- /*return;*/
- /*}*/
+ if (priv->size_valid)
+ {
+ *width = cached_width;
+ *height = cached_height;
+ if (scale_out)
+ *scale_out = cached_scale;
+ return;
+ }
if (!priv->image_surface)
@@ -553,7 +532,7 @@ gtk_image_view_compute_bounding_box (GtkImageView *image_view,
upper_right_degrees = DEG_TO_RAD (priv->angle) + atan (image_height / image_width);
upper_left_degrees = DEG_TO_RAD (priv->angle) + atan (image_height / -image_width);
- r = sqrtf ((image_width / 2.0) * (image_width / 2.0) + (image_height / 2.0) * (image_height / 2.0));
+ r = sqrt ((image_width / 2.0) * (image_width / 2.0) + (image_height / 2.0) * (image_height / 2.0));
upper_right_x = r * cos (upper_right_degrees);
upper_right_y = r * sin (upper_right_degrees);
@@ -592,16 +571,11 @@ gtk_image_view_compute_bounding_box (GtkImageView *image_view,
priv->scale = scale;
g_object_notify_by_pspec (G_OBJECT (image_view),
widget_props[PROP_SCALE]);
-
- *width = cached_width = bb_width * scale;
- *height = cached_height = bb_height * scale;
- }
- else
- {
- *width = cached_width = bb_width * scale;
- *height = cached_height = bb_height * scale;
}
+ *width = cached_width = bb_width * scale;
+ *height = cached_height = bb_height * scale;
+
priv->size_valid = TRUE;
}
@@ -640,6 +614,7 @@ gtk_image_view_update_adjustments (GtkImageView *image_view)
if (priv->vadjustment)
gtk_adjustment_configure (priv->vadjustment, 0, 0, 1, 0, 0, 1);
+
return;
}
@@ -763,6 +738,9 @@ gesture_scale_changed_cb (GtkGestureZoom *gesture,
double new_scale;
double old_scale = priv->scale;
+
+ g_error (":/");
+
/*if (!priv->rotate_gesture_enabled)*/
/*{*/
/*gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);*/
@@ -817,6 +795,7 @@ gtk_image_view_init (GtkImageView *image_view)
{
GtkImageViewPrivate *priv = gtk_image_view_get_instance_private (image_view);
GtkWidget *widget = GTK_WIDGET (image_view);
+ int i;
gtk_widget_set_can_focus (widget, TRUE);
gtk_widget_set_has_window (widget, FALSE);
@@ -824,6 +803,9 @@ gtk_image_view_init (GtkImageView *image_view)
_new_x = -1;
_new_y = -1;
+ for (i = 0; i < 360; i ++)
+ p_x[i] = p_y[i] = 0;
+
priv->scale = 1.0;
priv->angle = 0.0;
priv->snap_angle = FALSE;
@@ -931,10 +913,10 @@ frameclock_cb (GtkWidget *widget,
if (t >= 1.0)
{
priv->angle = priv->transition_end_angle;
- return FALSE;
+ return G_SOURCE_REMOVE;
}
- return TRUE;
+ return G_SOURCE_CONTINUE;
}
@@ -982,13 +964,13 @@ gtk_image_view_draw (GtkWidget *widget, cairo_t *ct)
GtkImageView *image_view = GTK_IMAGE_VIEW (widget);
GtkImageViewPrivate *priv = gtk_image_view_get_instance_private (image_view);
GtkStyleContext *sc = gtk_widget_get_style_context (widget);
+ int widget_width = gtk_widget_get_allocated_width (widget);
+ int widget_height = gtk_widget_get_allocated_height (widget);
int draw_x;
int draw_y;
int draw_width;
int draw_height;
double scale = 0.0;
- int widget_width = gtk_widget_get_allocated_width (widget);
- int widget_height = gtk_widget_get_allocated_height (widget);
if (priv->vadjustment && priv->hadjustment)
@@ -1074,17 +1056,34 @@ gtk_image_view_draw (GtkWidget *widget, cairo_t *ct)
cairo_restore (ct);
- /* XXX Debugging, Remove later. */
+ /* XXX @debug */
if (priv->anchor_x != -1 && priv->anchor_y != -1)
{
double w = gtk_adjustment_get_upper (priv->hadjustment);
double h = gtk_adjustment_get_upper (priv->vadjustment);
- double x = (w / 2.0) + priv->anchor_x - gtk_adjustment_get_value (priv->hadjustment);
- double y = (h / 2.0) + priv->anchor_y - gtk_adjustment_get_value (priv->vadjustment);
+ double hv = gtk_adjustment_get_value (priv->hadjustment);
+ double vv = gtk_adjustment_get_value (priv->vadjustment);
+ double x = (w / 2.0) + priv->anchor_x - hv;
+ double y = (h / 2.0) + priv->anchor_y - vv;
+ int i;
+
+ /*cairo_move_to (ct, 0, 0);*/
+ /*cairo_set_source_rgba (ct, 0, 1, 0, 1);*/
+ /*cairo_rectangle (ct, x - 2, y - 2, 4, 4);*/
+ /*cairo_fill (ct);*/
+
+
+ for (i = 0; i < 360; i ++)
+ {
+ if (p_x[i] == 0) continue;
+ /*g_message ("Drawing %d: %d, %d", i, p_x[i], p_y[i]);*/
+
+ /*cairo_set_source_rgba (ct, 0, 1, 0, 1);*/
+ /*cairo_rectangle (ct, w/2.0 + p_x[i] - 2 - hv, h/2.0 + p_y[i] - 2 - vv, 4, 4);*/
+ /*cairo_fill (ct);*/
+ }
+
- cairo_set_source_rgba (ct, 0, 1, 0, 1);
- cairo_rectangle (ct, x - 2, y - 2, 4, 4);
- cairo_fill (ct);
}
if (_new_x != -1 && _new_y != -1)
@@ -1172,7 +1171,7 @@ gtk_image_view_set_vadjustment (GtkImageView *image_view,
priv->vadjustment = vadjustment;
}
- g_object_notify ((GObject *)image_view, "vadjustment");
+ g_object_notify (G_OBJECT (image_view), "vadjustment");
gtk_image_view_update_adjustments (image_view);
@@ -1278,11 +1277,9 @@ gtk_image_view_set_angle (GtkImageView *image_view,
double angle)
{
GtkImageViewPrivate *priv = gtk_image_view_get_instance_private (image_view);
- double angle_before;
g_return_if_fail (GTK_IS_IMAGE_VIEW (image_view));
- angle_before = priv->angle;
if (angle > 360.0)
angle -= (int)(angle / 360.0) * 360;
@@ -1312,7 +1309,6 @@ gtk_image_view_set_angle (GtkImageView *image_view,
// Calculate the difference between the current surface center
// and the current widget center + 5
- // we aleady called _update_adjustments, so the 2 uppers are fine to use.
double cx = gtk_adjustment_get_upper (priv->hadjustment) / 2.0 -
gtk_adjustment_get_value (priv->hadjustment);
double cy = gtk_adjustment_get_upper (priv->vadjustment) / 2.0 -
@@ -1328,7 +1324,6 @@ gtk_image_view_set_angle (GtkImageView *image_view,
// Now store the difference between cx/cy and ax/ay in anchor_x/anchor_y
priv->anchor_x = ax - cx;
priv->anchor_y = ay - cy;
-
}
@@ -1336,6 +1331,8 @@ gtk_image_view_set_angle (GtkImageView *image_view,
/*if (priv->snap_angle)*/
/*gtk_image_view_do_snapping (image_view, angle);*/
/*else*/
+
+
priv->angle = angle;
@@ -1343,47 +1340,26 @@ gtk_image_view_set_angle (GtkImageView *image_view,
- gtk_image_view_update_adjustments (image_view);
+ /*gtk_image_view_update_adjustments (image_view);*/
g_object_notify_by_pspec (G_OBJECT (image_view),
widget_props[PROP_ANGLE]);
- /* XXX DEBUG */
- /*if (priv->hadjustment && priv->vadjustment)*/
- /*{*/
- /*static gboolean first = TRUE;*/
-
- /*if (first)*/
- /*{*/
- /*priv->gesture_start_scale = angle_before;*/
- /*first = FALSE;*/
- /*}*/
-
- /*priv->anchor_x = 200 + (gtk_widget_get_allocated_width (GTK_WIDGET (image_view))) / 2 - 200;*/
- /*priv->anchor_y = 200 + (gtk_widget_get_allocated_height (GTK_WIDGET (image_view))) / 2 - 200;*/
-
// XXX Later, we can just set the anchor_point to 0/0 here and calculate the
// center-relative anchor point in the gesture_begin handlers
- /*priv->anchor_x = priv->anchor_y = 5;*/
-
gtk_image_view_fix_point_rotate (image_view,
- angle_before,
priv->anchor_x,
priv->anchor_y,
&old_state);
- /*}*/
-
-
-
- /*if (priv->fit_allocation)*/
- /*gtk_widget_queue_draw (GTK_WIDGET (image_view));*/
- /*else*/
+ if (priv->fit_allocation)
+ gtk_widget_queue_draw (GTK_WIDGET (image_view));
+ else
gtk_widget_queue_resize (GTK_WIDGET (image_view));
}
@@ -1554,7 +1530,7 @@ gtk_image_view_get_zoom_gesture_enabled (GtkImageView *image_view)
static void
gtk_image_view_realize (GtkWidget *widget)
{
- GtkImageViewPrivate *priv = gtk_image_view_get_instance_private ((GtkImageView *)widget);
+ GtkImageViewPrivate *priv = gtk_image_view_get_instance_private (GTK_IMAGE_VIEW (widget));
GtkAllocation allocation;
GdkWindowAttr attributes = { 0, };
GdkWindow *window;
@@ -2224,13 +2200,28 @@ gtk_image_view_set_pixbuf (GtkImageView *image_view,
}
gtk_image_view_update_surface (image_view, pixbuf, scale_factor);
+
+ gtk_image_view_update_adjustments (image_view);
+
+
+ /* XXX @debug */
+ double value = gtk_adjustment_get_upper (priv->hadjustment) / 2.0 -
+ gtk_adjustment_get_page_size (priv->hadjustment) / 2.0;
+
+ gtk_adjustment_set_value (priv->hadjustment, value);
+
+ value = gtk_adjustment_get_upper (priv->vadjustment) / 2.0 -
+ gtk_adjustment_get_page_size (priv->vadjustment) / 2.0;
+
+ gtk_adjustment_set_value (priv->vadjustment, value);
+
}
/**
* gtk_image_view_set_surface:
* @image_view: A #GtkImageView instance
* @surface: (nullable): A #cairo_surface_t of type #CAIRO_SURFACE_TYPE_IMAGE, or
- * #NULL to unset any internal image data. In case this is #NULL, the scale will
+ * %NULL to unset any internal image data. In case this is %NULL, the scale will
* be reset to 1.0.
*/
void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]