[gimp] app: make GimpNavigationView rotation aware



commit cd767505fc2f923a07c8482b6681dd11ee77d662
Author: Ell <ell_se yahoo com>
Date:   Sat Jul 16 21:37:02 2016 +0000

    app: make GimpNavigationView rotation aware
    
    Rotate the viewport marker to correctly reflect the visible part
    of the image.

 app/display/gimpnavigationeditor.c |   25 ++++++-
 app/widgets/gimpnavigationview.c   |  149 ++++++++++++++++++++++--------------
 app/widgets/gimpnavigationview.h   |    5 +-
 3 files changed, 118 insertions(+), 61 deletions(-)
---
diff --git a/app/display/gimpnavigationeditor.c b/app/display/gimpnavigationeditor.c
index 02390d2..300a5f4 100644
--- a/app/display/gimpnavigationeditor.c
+++ b/app/display/gimpnavigationeditor.c
@@ -92,6 +92,8 @@ static void        gimp_navigation_editor_shell_scaled      (GimpDisplayShell
                                                              GimpNavigationEditor *editor);
 static void        gimp_navigation_editor_shell_scrolled    (GimpDisplayShell     *shell,
                                                              GimpNavigationEditor *editor);
+static void        gimp_navigation_editor_shell_rotated     (GimpDisplayShell     *shell,
+                                                             GimpNavigationEditor *editor);
 static void        gimp_navigation_editor_shell_reconnect   (GimpDisplayShell     *shell,
                                                              GimpNavigationEditor *editor);
 static void        gimp_navigation_editor_update_marker     (GimpNavigationEditor *editor);
@@ -464,6 +466,9 @@ gimp_navigation_editor_set_shell (GimpNavigationEditor *editor,
                                             gimp_navigation_editor_shell_scrolled,
                                             editor);
       g_signal_handlers_disconnect_by_func (editor->shell,
+                                            gimp_navigation_editor_shell_rotated,
+                                            editor);
+      g_signal_handlers_disconnect_by_func (editor->shell,
                                             gimp_navigation_editor_shell_reconnect,
                                             editor);
     }
@@ -487,6 +492,9 @@ gimp_navigation_editor_set_shell (GimpNavigationEditor *editor,
       g_signal_connect (editor->shell, "scrolled",
                         G_CALLBACK (gimp_navigation_editor_shell_scrolled),
                         editor);
+      g_signal_connect (editor->shell, "rotated",
+                        G_CALLBACK (gimp_navigation_editor_shell_rotated),
+                        editor);
       g_signal_connect (editor->shell, "reconnect",
                         G_CALLBACK (gimp_navigation_editor_shell_reconnect),
                         editor);
@@ -680,6 +688,17 @@ gimp_navigation_editor_shell_scrolled (GimpDisplayShell     *shell,
 }
 
 static void
+gimp_navigation_editor_shell_rotated (GimpDisplayShell     *shell,
+                                      GimpNavigationEditor *editor)
+{
+  gimp_navigation_editor_update_marker (editor);
+
+  if (gimp_editor_get_ui_manager (GIMP_EDITOR (editor)))
+    gimp_ui_manager_update (gimp_editor_get_ui_manager (GIMP_EDITOR (editor)),
+                            gimp_editor_get_popup_data (GIMP_EDITOR (editor)));
+}
+
+static void
 gimp_navigation_editor_shell_reconnect (GimpDisplayShell     *shell,
                                         GimpNavigationEditor *editor)
 {
@@ -714,6 +733,10 @@ gimp_navigation_editor_update_marker (GimpNavigationEditor *editor)
                                            shell->disp_height / 2,
                                            &x, &y);
 
-      gimp_navigation_view_set_marker (view, x, y, w, h);
+      gimp_navigation_view_set_marker (view,
+                                       x, y, w, h,
+                                       shell->flip_horizontally,
+                                       shell->flip_vertically,
+                                       shell->rotate_angle);
     }
 }
diff --git a/app/widgets/gimpnavigationview.c b/app/widgets/gimpnavigationview.c
index b449052..50969a3 100644
--- a/app/widgets/gimpnavigationview.c
+++ b/app/widgets/gimpnavigationview.c
@@ -23,6 +23,8 @@
 
 #include "config.h"
 
+#include <math.h>
+
 #include <gegl.h>
 #include <gtk/gtk.h>
 #include <gdk/gdkkeysyms.h>
@@ -60,6 +62,9 @@ struct _GimpNavigationView
   gdouble      center_y;
   gdouble      width;
   gdouble      height;
+  gboolean     flip_horizontally;
+  gboolean     flip_vertically;
+  gdouble      rotate_angle;
 
   /*  values in view coordinates  */
   gint         p_center_x;
@@ -73,30 +78,33 @@ struct _GimpNavigationView
 };
 
 
-static void     gimp_navigation_view_size_allocate  (GtkWidget      *widget,
-                                                     GtkAllocation  *allocation);
-static gboolean gimp_navigation_view_expose         (GtkWidget      *widget,
-                                                     GdkEventExpose *event);
-static gboolean gimp_navigation_view_button_press   (GtkWidget      *widget,
-                                                     GdkEventButton *bevent);
-static gboolean gimp_navigation_view_button_release (GtkWidget      *widget,
-                                                     GdkEventButton *bevent);
-static gboolean gimp_navigation_view_scroll         (GtkWidget      *widget,
-                                                     GdkEventScroll *sevent);
-static gboolean gimp_navigation_view_motion_notify  (GtkWidget      *widget,
-                                                     GdkEventMotion *mevent);
-static gboolean gimp_navigation_view_key_press      (GtkWidget      *widget,
-                                                     GdkEventKey    *kevent);
-
-static void     gimp_navigation_view_transform      (GimpNavigationView *nav_view);
-static void     gimp_navigation_view_draw_marker    (GimpNavigationView *nav_view,
-                                                     cairo_t            *cr);
-static void     gimp_navigation_view_move_to        (GimpNavigationView *nav_view,
-                                                     gint                tx,
-                                                     gint                ty);
-static void     gimp_navigation_view_get_ratio      (GimpNavigationView *nav_view,
-                                                     gdouble            *ratiox,
-                                                     gdouble            *ratioy);
+static void     gimp_navigation_view_size_allocate   (GtkWidget      *widget,
+                                                      GtkAllocation  *allocation);
+static gboolean gimp_navigation_view_expose          (GtkWidget      *widget,
+                                                      GdkEventExpose *event);
+static gboolean gimp_navigation_view_button_press    (GtkWidget      *widget,
+                                                      GdkEventButton *bevent);
+static gboolean gimp_navigation_view_button_release  (GtkWidget      *widget,
+                                                      GdkEventButton *bevent);
+static gboolean gimp_navigation_view_scroll          (GtkWidget      *widget,
+                                                      GdkEventScroll *sevent);
+static gboolean gimp_navigation_view_motion_notify   (GtkWidget      *widget,
+                                                      GdkEventMotion *mevent);
+static gboolean gimp_navigation_view_key_press       (GtkWidget      *widget,
+                                                      GdkEventKey    *kevent);
+
+static void     gimp_navigation_view_transform       (GimpNavigationView *nav_view);
+static void     gimp_navigation_view_draw_marker     (GimpNavigationView *nav_view,
+                                                      cairo_t            *cr);
+static void     gimp_navigation_view_move_to         (GimpNavigationView *nav_view,
+                                                      gint                tx,
+                                                      gint                ty);
+static void     gimp_navigation_view_get_ratio       (GimpNavigationView *nav_view,
+                                                      gdouble            *ratiox,
+                                                      gdouble            *ratioy);
+static gboolean gimp_navigation_view_point_in_marker (GimpNavigationView *nav_view,
+                                                      gint                x,
+                                                      gint                y);
 
 
 G_DEFINE_TYPE (GimpNavigationView, gimp_navigation_view, GIMP_TYPE_VIEW)
@@ -161,10 +169,13 @@ gimp_navigation_view_init (GimpNavigationView *view)
                          GDK_POINTER_MOTION_MASK |
                          GDK_KEY_PRESS_MASK);
 
-  view->center_x        = 0.0;
-  view->center_y        = 0.0;
-  view->width           = 0.0;
-  view->height          = 0.0;
+  view->center_x          = 0.0;
+  view->center_y          = 0.0;
+  view->width             = 0.0;
+  view->height            = 0.0;
+  view->flip_horizontally = FALSE;
+  view->flip_vertically   = FALSE;
+  view->rotate_angle      = 0.0;
 
   view->p_center_x      = 0;
   view->p_center_y      = 0;
@@ -242,22 +253,14 @@ gimp_navigation_view_button_press (GtkWidget      *widget,
 {
   GimpNavigationView *nav_view = GIMP_NAVIGATION_VIEW (widget);
   gint                tx, ty;
-  gint                p_width_2;
-  gint                p_height_2;
   GdkDisplay         *display;
 
   tx = bevent->x;
   ty = bevent->y;
 
-  p_width_2  = nav_view->p_width  / 2;
-  p_height_2 = nav_view->p_height / 2;
-
   if (bevent->type == GDK_BUTTON_PRESS && bevent->button == 1)
     {
-      if (! (tx >= (nav_view->p_center_x - p_width_2)  &&
-             tx <  (nav_view->p_center_x + p_width_2)  &&
-             ty >= (nav_view->p_center_y - p_height_2) &&
-             ty <  (nav_view->p_center_y + p_height_2)))
+      if (! gimp_navigation_view_point_in_marker (nav_view, tx, ty))
         {
           GdkCursor *cursor;
 
@@ -351,11 +354,6 @@ gimp_navigation_view_motion_notify (GtkWidget      *widget,
     {
       GdkDisplay *display = gtk_widget_get_display (widget);
       GdkCursor  *cursor;
-      gint        p_width_2;
-      gint        p_height_2;
-
-      p_width_2  = nav_view->p_width  / 2;
-      p_height_2 = nav_view->p_height / 2;
 
       if (nav_view->p_center_x == view->renderer->width  / 2 &&
           nav_view->p_center_y == view->renderer->height / 2 &&
@@ -365,10 +363,8 @@ gimp_navigation_view_motion_notify (GtkWidget      *widget,
           gdk_window_set_cursor (view->event_window, NULL);
           return FALSE;
         }
-      else if (mevent->x >= nav_view->p_center_x - p_width_2  &&
-               mevent->y >= nav_view->p_center_y - p_height_2 &&
-               mevent->x <  nav_view->p_center_x + p_width_2  &&
-               mevent->y <  nav_view->p_center_y + p_height_2)
+      else if (gimp_navigation_view_point_in_marker (nav_view,
+                                                     mevent->x, mevent->y))
         {
           cursor = gdk_cursor_new_for_display (display, GDK_FLEUR);
         }
@@ -441,7 +437,10 @@ gimp_navigation_view_set_marker (GimpNavigationView *nav_view,
                                  gdouble             center_x,
                                  gdouble             center_y,
                                  gdouble             width,
-                                 gdouble             height)
+                                 gdouble             height,
+                                 gboolean            flip_horizontally,
+                                 gboolean            flip_vertically,
+                                 gdouble             rotate_angle)
 {
   GimpView *view;
 
@@ -451,10 +450,13 @@ gimp_navigation_view_set_marker (GimpNavigationView *nav_view,
 
   g_return_if_fail (view->renderer->viewable);
 
-  nav_view->center_x = center_x;
-  nav_view->center_y = center_y;
-  nav_view->width    = MAX (1.0, width);
-  nav_view->height   = MAX (1.0, height);
+  nav_view->center_x          = center_x;
+  nav_view->center_y          = center_y;
+  nav_view->width             = MAX (1.0, width);
+  nav_view->height            = MAX (1.0, height);
+  nav_view->flip_horizontally = flip_horizontally ? TRUE : FALSE;
+  nav_view->flip_vertically   = flip_vertically   ? TRUE : FALSE;
+  nav_view->rotate_angle      = rotate_angle;
 
   gimp_navigation_view_transform (nav_view);
 
@@ -517,31 +519,34 @@ gimp_navigation_view_draw_marker (GimpNavigationView *nav_view,
       GtkAllocation  allocation;
       gint           p_width_2;
       gint           p_height_2;
+      gdouble        angle;
 
       p_width_2  = nav_view->p_width  / 2;
       p_height_2 = nav_view->p_height / 2;
 
+      angle = G_PI * nav_view->rotate_angle / 180.0;
+      if (nav_view->flip_horizontally != nav_view->flip_vertically)
+        angle = -angle;
+
       gtk_widget_get_allocation (widget, &allocation);
 
       cairo_translate (cr, allocation.x, allocation.y);
       cairo_rectangle (cr,
                        0, 0,
                        allocation.width, allocation.height);
+      cairo_translate (cr, nav_view->p_center_x, nav_view->p_center_y);
+      cairo_rotate (cr, -angle);
       cairo_rectangle (cr,
-                       nav_view->p_center_x - p_width_2,
-                       nav_view->p_center_y - p_height_2,
-                       nav_view->p_width,
-                       nav_view->p_height);
+                       -p_width_2, -p_height_2,
+                       nav_view->p_width, nav_view->p_height);
 
       cairo_set_source_rgba (cr, 0, 0, 0, 0.5);
       cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
       cairo_fill (cr);
 
       cairo_rectangle (cr,
-                       nav_view->p_center_x - p_width_2,
-                       nav_view->p_center_y - p_height_2,
-                       nav_view->p_width,
-                       nav_view->p_height);
+                       -p_width_2, -p_height_2,
+                       nav_view->p_width, nav_view->p_height);
 
       cairo_set_source_rgb (cr, 1, 1, 1);
       cairo_set_line_width (cr, BORDER_WIDTH);
@@ -585,3 +590,29 @@ gimp_navigation_view_get_ratio (GimpNavigationView *nav_view,
   *ratioy = (gdouble) view->renderer->height /
             (gdouble) gimp_image_get_height (image);
 }
+
+static gboolean
+gimp_navigation_view_point_in_marker (GimpNavigationView *nav_view,
+                                      gint                x,
+                                      gint                y)
+{
+  gint    p_width_2, p_height_2;
+  gdouble angle;
+  gdouble tx, ty;
+
+  p_width_2  = nav_view->p_width  / 2;
+  p_height_2 = nav_view->p_height / 2;
+
+  angle = G_PI * nav_view->rotate_angle / 180.0;
+  if (nav_view->flip_horizontally != nav_view->flip_vertically)
+    angle = -angle;
+
+  x -= nav_view->p_center_x;
+  y -= nav_view->p_center_y;
+
+  tx = cos (angle) * x - sin (angle) * y;
+  ty = sin (angle) * x + cos (angle) * y;
+
+  return tx >= -p_width_2  && tx < p_width_2 &&
+         ty >= -p_height_2 && ty < p_height_2;
+}
diff --git a/app/widgets/gimpnavigationview.h b/app/widgets/gimpnavigationview.h
index a5498aa..b2c6cb5 100644
--- a/app/widgets/gimpnavigationview.h
+++ b/app/widgets/gimpnavigationview.h
@@ -59,7 +59,10 @@ void    gimp_navigation_view_set_marker   (GimpNavigationView *view,
                                            gdouble             center_x,
                                            gdouble             center_y,
                                            gdouble             width,
-                                           gdouble             height);
+                                           gdouble             height,
+                                           gboolean            flip_horizontally,
+                                           gboolean            flip_vertically,
+                                           gdouble             rotate_angle);
 void    gimp_navigation_view_set_motion_offset
                                           (GimpNavigationView *view,
                                            gint                motion_offset_x,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]