[gimp] app: use gimp_transform_polygon() in GimpCanvasTransformGuides



commit 4626190ac76fbbdfc829e671f2c27ff32e96e1ed
Author: Ell <ell_se yahoo com>
Date:   Sun Jan 28 13:39:00 2018 -0500

    app: use gimp_transform_polygon() in GimpCanvasTransformGuides
    
    Add a "clip" property to GimpCavnasTransformGuides.  When set, use
    gimp_transform_polygon() for transforming the guides and the
    bounding box, so that they're properly clipped.
    
    Add a corresponding "clip-guides" property to
    GimpToolTransformGrid, and set it to TRUE in GimpToolHandleGrid, so
    that the handle-transform tool's guides are clipped properly.

 app/display/gimpcanvastransformguides.c |  246 ++++++++++++++++++++-----------
 app/display/gimpcanvastransformguides.h |    6 +-
 app/display/gimptoolhandlegrid.c        |   11 +-
 app/display/gimptooltransformgrid.c     |   20 +++-
 app/display/gimptoolwidget.c            |    5 +-
 app/display/gimptoolwidget.h            |    3 +-
 6 files changed, 192 insertions(+), 99 deletions(-)
---
diff --git a/app/display/gimpcanvastransformguides.c b/app/display/gimpcanvastransformguides.c
index 586616f..379382a 100644
--- a/app/display/gimpcanvastransformguides.c
+++ b/app/display/gimpcanvastransformguides.c
@@ -47,7 +47,8 @@ enum
   PROP_X2,
   PROP_Y2,
   PROP_TYPE,
-  PROP_N_GUIDES
+  PROP_N_GUIDES,
+  PROP_CLIP
 };
 
 
@@ -60,6 +61,7 @@ struct _GimpCanvasTransformGuidesPrivate
   gdouble        x2, y2;
   GimpGuidesType type;
   gint           n_guides;
+  gboolean       clip;
 };
 
 #define GET_PRIVATE(transform) \
@@ -150,6 +152,11 @@ gimp_canvas_transform_guides_class_init (GimpCanvasTransformGuidesClass *klass)
                                                      1, 128, 4,
                                                      GIMP_PARAM_READWRITE));
 
+  g_object_class_install_property (object_class, PROP_CLIP,
+                                   g_param_spec_boolean ("clip", NULL, NULL,
+                                                         FALSE,
+                                                         GIMP_PARAM_READWRITE));
+
   g_type_class_add_private (klass, sizeof (GimpCanvasTransformGuidesPrivate));
 }
 
@@ -203,6 +210,10 @@ gimp_canvas_transform_guides_set_property (GObject      *object,
       private->n_guides = g_value_get_int (value);
       break;
 
+    case PROP_CLIP:
+      private->clip = g_value_get_boolean (value);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
       break;
@@ -247,6 +258,10 @@ gimp_canvas_transform_guides_get_property (GObject    *object,
       g_value_set_int (value, private->n_guides);
       break;
 
+    case PROP_CLIP:
+      g_value_set_boolean (value, private->clip);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
       break;
@@ -255,34 +270,42 @@ gimp_canvas_transform_guides_get_property (GObject    *object,
 
 static gboolean
 gimp_canvas_transform_guides_transform (GimpCanvasItem *item,
-                                        gdouble        *tx1,
-                                        gdouble        *ty1,
-                                        gdouble        *tx2,
-                                        gdouble        *ty2,
-                                        gdouble        *tx3,
-                                        gdouble        *ty3,
-                                        gdouble        *tx4,
-                                        gdouble        *ty4)
+                                        GimpVector2    *t_vertices,
+                                        gint           *n_t_vertices)
 {
   GimpCanvasTransformGuidesPrivate *private = GET_PRIVATE (item);
+  GimpVector2                       vertices[4];
+
+  vertices[0] = (GimpVector2) { private->x1, private->y1 };
+  vertices[1] = (GimpVector2) { private->x2, private->y1 };
+  vertices[2] = (GimpVector2) { private->x2, private->y2 };
+  vertices[3] = (GimpVector2) { private->x1, private->y2 };
+
+  if (private->clip)
+    {
+      gimp_transform_polygon (&private->transform, vertices, 4, TRUE,
+                              t_vertices, n_t_vertices);
+
+      return TRUE;
+    }
+  else
+    {
+      gint i;
+
+      for (i = 0; i < 4; i++)
+        {
+          gimp_matrix3_transform_point (&private->transform,
+                                        vertices[i].x,    vertices[i].y,
+                                        &t_vertices[i].x, &t_vertices[i].y);
+        }
+
+      *n_t_vertices = 4;
 
-  gimp_matrix3_transform_point (&private->transform,
-                                private->x1, private->y1,
-                                tx1, ty1);
-  gimp_matrix3_transform_point (&private->transform,
-                                private->x2, private->y1,
-                                tx2, ty2);
-  gimp_matrix3_transform_point (&private->transform,
-                                private->x1, private->y2,
-                                tx3, ty3);
-  gimp_matrix3_transform_point (&private->transform,
-                                private->x2, private->y2,
-                                tx4, ty4);
-
-  return gimp_transform_polygon_is_convex (*tx1, *ty1,
-                                           *tx2, *ty2,
-                                           *tx3, *ty3,
-                                           *tx4, *ty4);
+      return gimp_transform_polygon_is_convex (t_vertices[0].x, t_vertices[0].y,
+                                               t_vertices[1].x, t_vertices[1].y,
+                                               t_vertices[3].x, t_vertices[3].y,
+                                               t_vertices[2].x, t_vertices[2].y);
+    }
 }
 
 static void
@@ -294,19 +317,54 @@ draw_line (cairo_t        *cr,
            gdouble         x2,
            gdouble         y2)
 {
-  gimp_matrix3_transform_point (transform, x1, y1, &x1, &y1);
-  gimp_matrix3_transform_point (transform, x2, y2, &x2, &y2);
+  GimpCanvasTransformGuidesPrivate *private = GET_PRIVATE (item);
+  GimpVector2                       vertices[2];
+  GimpVector2                       t_vertices[2];
+  gint                              n_t_vertices;
 
-  gimp_canvas_item_transform_xy_f (item, x1, y1, &x1, &y1);
-  gimp_canvas_item_transform_xy_f (item, x2, y2, &x2, &y2);
+  vertices[0] = (GimpVector2) { x1, y1 };
+  vertices[1] = (GimpVector2) { x2, y2 };
 
-  x1 = floor (x1) + 0.5;
-  y1 = floor (y1) + 0.5;
-  x2 = floor (x2) + 0.5;
-  y2 = floor (y2) + 0.5;
+  if (private->clip)
+    {
+      gimp_transform_polygon (transform, vertices, 2, FALSE,
+                              t_vertices, &n_t_vertices);
+    }
+  else
+    {
+      gint i;
 
-  cairo_move_to (cr, x1, y1);
-  cairo_line_to (cr, x2, y2);
+      for (i = 0; i < 2; i++)
+        {
+          gimp_matrix3_transform_point (transform,
+                                        vertices[i].x,    vertices[i].y,
+                                        &t_vertices[i].x, &t_vertices[i].y);
+        }
+
+      n_t_vertices = 2;
+    }
+
+  if (n_t_vertices == 2)
+    {
+      gint i;
+
+      for (i = 0; i < 2; i++)
+        {
+          GimpVector2 v;
+
+          gimp_canvas_item_transform_xy_f (item,
+                                           t_vertices[i].x, t_vertices[i].y,
+                                           &v.x,            &v.y);
+
+          v.x = floor (v.x) + 0.5;
+          v.y = floor (v.y) + 0.5;
+
+          if (i == 0)
+            cairo_move_to (cr, v.x, v.y);
+          else
+            cairo_line_to (cr, v.x, v.y);
+        }
+    }
 }
 
 static void
@@ -336,40 +394,36 @@ gimp_canvas_transform_guides_draw (GimpCanvasItem *item,
                                    cairo_t        *cr)
 {
   GimpCanvasTransformGuidesPrivate *private = GET_PRIVATE (item);
-  gdouble                           x1, y1;
-  gdouble                           x2, y2;
-  gdouble                           x3, y3;
-  gdouble                           x4, y4;
+  GimpVector2                       t_vertices[5];
+  gint                              n_t_vertices;
   gboolean                          convex;
   gint                              i;
 
   convex = gimp_canvas_transform_guides_transform (item,
-                                                   &x1, &y1,
-                                                   &x2, &y2,
-                                                   &x3, &y3,
-                                                   &x4, &y4);
-
-  gimp_canvas_item_transform_xy_f (item, x1, y1, &x1, &y1);
-  gimp_canvas_item_transform_xy_f (item, x2, y2, &x2, &y2);
-  gimp_canvas_item_transform_xy_f (item, x3, y3, &x3, &y3);
-  gimp_canvas_item_transform_xy_f (item, x4, y4, &x4, &y4);
-
-  x1 = floor (x1) + 0.5;
-  y1 = floor (y1) + 0.5;
-  x2 = floor (x2) + 0.5;
-  y2 = floor (y2) + 0.5;
-  x3 = floor (x3) + 0.5;
-  y3 = floor (y3) + 0.5;
-  x4 = floor (x4) + 0.5;
-  y4 = floor (y4) + 0.5;
-
-  cairo_move_to (cr, x1, y1);
-  cairo_line_to (cr, x2, y2);
-  cairo_line_to (cr, x4, y4);
-  cairo_line_to (cr, x3, y3);
-  cairo_line_to (cr, x1, y1);
-
-  if (! convex)
+                                                   t_vertices, &n_t_vertices);
+
+  if (n_t_vertices < 2)
+    return;
+
+  for (i = 0; i < n_t_vertices; i++)
+    {
+      GimpVector2 v;
+
+      gimp_canvas_item_transform_xy_f (item, t_vertices[i].x, t_vertices[i].y,
+                                       &v.x, &v.y);
+
+      v.x = floor (v.x) + 0.5;
+      v.y = floor (v.y) + 0.5;
+
+      if (i == 0)
+        cairo_move_to (cr, v.x, v.y);
+      else
+        cairo_line_to (cr, v.x, v.y);
+    }
+
+  cairo_close_path (cr);
+
+  if (! convex || n_t_vertices < 3)
     {
       _gimp_canvas_item_stroke (item, cr);
       return;
@@ -535,30 +589,44 @@ gimp_canvas_transform_guides_draw (GimpCanvasItem *item,
 static cairo_region_t *
 gimp_canvas_transform_guides_get_extents (GimpCanvasItem *item)
 {
-  gdouble               x1, y1;
-  gdouble               x2, y2;
-  gdouble               x3, y3;
-  gdouble               x4, y4;
+  GimpVector2           t_vertices[5];
+  gint                  n_t_vertices;
+  GimpVector2           top_left;
+  GimpVector2           bottom_right;
   cairo_rectangle_int_t extents;
+  gint                  i;
+
+  gimp_canvas_transform_guides_transform (item, t_vertices, &n_t_vertices);
+
+  if (n_t_vertices < 2)
+    return  cairo_region_create ();
+
+  for (i = 0; i < n_t_vertices; i++)
+    {
+      GimpVector2 v;
 
-  gimp_canvas_transform_guides_transform (item,
-                                          &x1, &y1,
-                                          &x2, &y2,
-                                          &x3, &y3,
-                                          &x4, &y4);
+      gimp_canvas_item_transform_xy_f (item,
+                                       t_vertices[i].x, t_vertices[i].y,
+                                       &v.x,            &v.y);
 
-  gimp_canvas_item_transform_xy_f (item, x1, y1, &x1, &y1);
-  gimp_canvas_item_transform_xy_f (item, x2, y2, &x2, &y2);
-  gimp_canvas_item_transform_xy_f (item, x3, y3, &x3, &y3);
-  gimp_canvas_item_transform_xy_f (item, x4, y4, &x4, &y4);
+      if (i == 0)
+        {
+          top_left = bottom_right = v;
+        }
+      else
+        {
+          top_left.x     = MIN (top_left.x,     v.x);
+          top_left.y     = MIN (top_left.y,     v.y);
 
-  extents.x      = (gint) floor (MIN4 (x1, x2, x3, x4) - 1.5);
-  extents.y      = (gint) floor (MIN4 (y1, y2, y3, y4) - 1.5);
-  extents.width  = (gint) ceil  (MAX4 (x1, x2, x3, x4) + 1.5);
-  extents.height = (gint) ceil  (MAX4 (y1, y2, y3, y4) + 1.5);
+          bottom_right.x = MAX (bottom_right.x, v.x);
+          bottom_right.y = MAX (bottom_right.y, v.y);
+        }
+    }
 
-  extents.width  -= extents.x;
-  extents.height -= extents.y;
+  extents.x      = (gint) floor (top_left.x     - 1.5);
+  extents.y      = (gint) floor (top_left.y     - 1.5);
+  extents.width  = (gint) ceil  (bottom_right.x + 1.5) - extents.x;
+  extents.height = (gint) ceil  (bottom_right.y + 1.5) - extents.y;
 
   return cairo_region_create_rectangle (&extents);
 }
@@ -571,7 +639,8 @@ gimp_canvas_transform_guides_new (GimpDisplayShell  *shell,
                                   gdouble            x2,
                                   gdouble            y2,
                                   GimpGuidesType     type,
-                                  gint               n_guides)
+                                  gint               n_guides,
+                                  gboolean           clip)
 {
   g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), NULL);
 
@@ -584,6 +653,7 @@ gimp_canvas_transform_guides_new (GimpDisplayShell  *shell,
                        "y2",        y2,
                        "type",      type,
                        "n-guides",  n_guides,
+                       "clip",      clip,
                        NULL);
 }
 
@@ -595,7 +665,8 @@ gimp_canvas_transform_guides_set (GimpCanvasItem    *guides,
                                   gdouble            x2,
                                   gdouble            y2,
                                   GimpGuidesType     type,
-                                  gint               n_guides)
+                                  gint               n_guides,
+                                  gboolean           clip)
 {
   g_return_if_fail (GIMP_IS_CANVAS_TRANSFORM_GUIDES (guides));
 
@@ -609,6 +680,7 @@ gimp_canvas_transform_guides_set (GimpCanvasItem    *guides,
                 "y2",        y2,
                 "type",      type,
                 "n-guides",  n_guides,
+                "clip",      clip,
                 NULL);
 
   gimp_canvas_item_end_change (guides);
diff --git a/app/display/gimpcanvastransformguides.h b/app/display/gimpcanvastransformguides.h
index 6067c35..792de8a 100644
--- a/app/display/gimpcanvastransformguides.h
+++ b/app/display/gimpcanvastransformguides.h
@@ -56,7 +56,8 @@ GimpCanvasItem * gimp_canvas_transform_guides_new      (GimpDisplayShell  *shell
                                                         gdouble            x2,
                                                         gdouble            y2,
                                                         GimpGuidesType     type,
-                                                        gint               n_guides);
+                                                        gint               n_guides,
+                                                        gboolean           clip);
 
 void             gimp_canvas_transform_guides_set      (GimpCanvasItem    *guides,
                                                         const GimpMatrix3 *transform,
@@ -65,7 +66,8 @@ void             gimp_canvas_transform_guides_set      (GimpCanvasItem    *guide
                                                         gdouble            x2,
                                                         gdouble            y2,
                                                         GimpGuidesType     type,
-                                                        gint               n_guides);
+                                                        gint               n_guides,
+                                                        gboolean           clip);
 
 
 #endif /* __GIMP_CANVAS_TRANSFORM_GUIDES_H__ */
diff --git a/app/display/gimptoolhandlegrid.c b/app/display/gimptoolhandlegrid.c
index dc1bfc9..acb83a9 100644
--- a/app/display/gimptoolhandlegrid.c
+++ b/app/display/gimptoolhandlegrid.c
@@ -1109,10 +1109,11 @@ gimp_tool_handle_grid_new (GimpDisplayShell *shell,
   g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), NULL);
 
   return g_object_new (GIMP_TYPE_TOOL_HANDLE_GRID,
-                       "shell",     shell,
-                       "x1",        x1,
-                       "y1",        y1,
-                       "x2",        x2,
-                       "y2",        y2,
+                       "shell",       shell,
+                       "x1",          x1,
+                       "y1",          y1,
+                       "x2",          x2,
+                       "y2",          y2,
+                       "clip-guides", TRUE,
                        NULL);
 }
diff --git a/app/display/gimptooltransformgrid.c b/app/display/gimptooltransformgrid.c
index 15f250e..01236a9 100644
--- a/app/display/gimptooltransformgrid.c
+++ b/app/display/gimptooltransformgrid.c
@@ -59,6 +59,7 @@ enum
   PROP_PIVOT_Y,
   PROP_GUIDE_TYPE,
   PROP_N_GUIDES,
+  PROP_CLIP_GUIDES,
   PROP_SHOW_GUIDES,
   PROP_INSIDE_FUNCTION,
   PROP_OUTSIDE_FUNCTION,
@@ -90,6 +91,7 @@ struct _GimpToolTransformGridPrivate
   gdouble                pivot_y;
   GimpGuidesType         guide_type;
   gint                   n_guides;
+  gboolean               clip_guides;
   gboolean               show_guides;
   GimpTransformFunction  inside_function;
   GimpTransformFunction  outside_function;
@@ -292,6 +294,12 @@ gimp_tool_transform_grid_class_init (GimpToolTransformGridClass *klass)
                                                      GIMP_PARAM_READWRITE |
                                                      G_PARAM_CONSTRUCT));
 
+  g_object_class_install_property (object_class, PROP_CLIP_GUIDES,
+                                   g_param_spec_boolean ("clip-guides", NULL, NULL,
+                                                         FALSE,
+                                                         GIMP_PARAM_READWRITE |
+                                                         G_PARAM_CONSTRUCT));
+
   g_object_class_install_property (object_class, PROP_SHOW_GUIDES,
                                    g_param_spec_boolean ("show-guides", NULL, NULL,
                                                          TRUE,
@@ -455,7 +463,8 @@ gimp_tool_transform_grid_constructed (GObject *object)
                                                            private->x2,
                                                            private->y2,
                                                            private->guide_type,
-                                                           private->n_guides);
+                                                           private->n_guides,
+                                                           private->clip_guides);
 
   for (i = 0; i < 4; i++)
     {
@@ -586,6 +595,9 @@ gimp_tool_transform_grid_set_property (GObject      *object,
     case PROP_N_GUIDES:
       private->n_guides = g_value_get_int (value);
       break;
+    case PROP_CLIP_GUIDES:
+      private->clip_guides = g_value_get_boolean (value);
+      break;
     case PROP_SHOW_GUIDES:
       private->show_guides = g_value_get_boolean (value);
       break;
@@ -702,6 +714,9 @@ gimp_tool_transform_grid_get_property (GObject    *object,
     case PROP_N_GUIDES:
       g_value_set_int (value, private->n_guides);
       break;
+    case PROP_CLIP_GUIDES:
+      g_value_set_boolean (value, private->clip_guides);
+      break;
     case PROP_SHOW_GUIDES:
       g_value_set_boolean (value, private->show_guides);
       break;
@@ -1033,7 +1048,8 @@ gimp_tool_transform_grid_changed (GimpToolWidget *widget)
                                     private->x2,
                                     private->y2,
                                     private->guide_type,
-                                    private->n_guides);
+                                    private->n_guides,
+                                    private->clip_guides);
   gimp_canvas_item_set_visible (private->guides, private->show_guides);
 
   get_handle_geometry (grid, o, angle);
diff --git a/app/display/gimptoolwidget.c b/app/display/gimptoolwidget.c
index 38ae34a..ce777b5 100644
--- a/app/display/gimptoolwidget.c
+++ b/app/display/gimptoolwidget.c
@@ -697,7 +697,8 @@ gimp_tool_widget_add_transform_guides (GimpToolWidget    *widget,
                                        gdouble            x2,
                                        gdouble            y2,
                                        GimpGuidesType     type,
-                                       gint               n_guides)
+                                       gint               n_guides,
+                                       gboolean           clip)
 {
   GimpCanvasItem *item;
 
@@ -705,7 +706,7 @@ gimp_tool_widget_add_transform_guides (GimpToolWidget    *widget,
 
   item = gimp_canvas_transform_guides_new (widget->private->shell,
                                            transform, x1, y1, x2, y2,
-                                           type, n_guides);
+                                           type, n_guides, clip);
 
   gimp_tool_widget_add_item (widget, item);
   g_object_unref (item);
diff --git a/app/display/gimptoolwidget.h b/app/display/gimptoolwidget.h
index 2728503..7f2cac1 100644
--- a/app/display/gimptoolwidget.h
+++ b/app/display/gimptoolwidget.h
@@ -225,7 +225,8 @@ GimpCanvasItem * gimp_tool_widget_add_transform_guides
                                                  gdouble               x2,
                                                  gdouble               y2,
                                                  GimpGuidesType        type,
-                                                 gint                  n_guides);
+                                                 gint                  n_guides,
+                                                 gboolean              clip);
 
 /*  for tools, to be called from the respective GimpTool method
  *  implementations


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