[gimp] Honor the projectable's offset in the projection



commit dd8a7740abf97ece183e424ee295e94f4061b50b
Author: Michael Natterer <mitch gimp org>
Date:   Mon Aug 24 15:59:14 2009 +0200

    Honor the projectable's offset in the projection
    
    Add/Subtract the projectable's offset whenever we go from coordinates
    from our public interface (which are always image coordinates) and
    coordinates in out internal tile pyramid (wihch always starts at 0,0).
    
    The Gegl projection still needs an offset node that is missing.
    
    Also, connect to the projectable's "update" signal using
    g_signal_connect_closure_by_id() instead of simply g_signal_connect(),
    so we really connect to the signal of the GimpProjectable interface
    and not to the "update" signal of GimpDrawable (which is a conflict
    that will happen on group layers).

 app/core/gimpprojection-construct.c |   27 ++++++++++++++++++++++-
 app/core/gimpprojection.c           |   41 +++++++++++++++++++++++++++++-----
 2 files changed, 61 insertions(+), 7 deletions(-)
---
diff --git a/app/core/gimpprojection-construct.c b/app/core/gimpprojection-construct.c
index e475550..ad86b27 100644
--- a/app/core/gimpprojection-construct.c
+++ b/app/core/gimpprojection-construct.c
@@ -75,6 +75,7 @@ gimp_projection_construct (GimpProjection *proj,
       gint          width, height;
       gint          off_x, off_y;
 
+      gimp_projectable_get_offset (proj->projectable, &proj_off_x, &proj_off_y);
       gimp_projectable_get_size (proj->projectable, &width, &height);
 
       gimp_item_get_offset (item, &off_x, &off_y);
@@ -86,7 +87,9 @@ gimp_projection_construct (GimpProjection *proj,
           ! gimp_drawable_is_indexed (layer)                    &&
           gimp_layer_get_opacity (layer) == GIMP_OPACITY_OPAQUE &&
           off_x == 0                                            &&
-          off_y == 0)
+          off_y == 0                                            &&
+          proj_offset_x == 0                                    &&
+          proj_offset_y == 0)
         {
           PixelRegion srcPR, destPR;
 
@@ -176,6 +179,8 @@ gimp_projection_construct_legacy (GimpProjection *proj,
 {
   GList *list;
   GList *reverse_list = NULL;
+  gint   proj_off_x;
+  gint   proj_off_y;
 
   for (list = gimp_projectable_get_channels (proj->projectable);
        list;
@@ -206,6 +211,8 @@ gimp_projection_construct_legacy (GimpProjection *proj,
         }
     }
 
+  gimp_projectable_get_offset (proj->projectable, &proj_off_x, &proj_off_y);
+
   for (list = reverse_list; list; list = g_list_next (list))
     {
       GimpItem    *item = list->data;
@@ -217,6 +224,13 @@ gimp_projection_construct_legacy (GimpProjection *proj,
 
       gimp_item_get_offset (item, &off_x, &off_y);
 
+      /*  subtract the projectable's offsets because the list of
+       *  update areas is in tile-pyramid coordinates, but our
+       *  external API is always in terms of image coordinates.
+       */
+      off_x -= proj_off_x;
+      off_y -= proj_off_y;
+
       x1 = CLAMP (off_x,                               x, x + w);
       y1 = CLAMP (off_y,                               y, y + h);
       x2 = CLAMP (off_x + gimp_item_get_width  (item), x, x + w);
@@ -259,8 +273,12 @@ gimp_projection_initialize (GimpProjection *proj,
                             gint            h)
 {
   GList    *list;
+  gint      proj_off_x;
+  gint      proj_off_y;
   gboolean  coverage = FALSE;
 
+  gimp_projectable_get_offset (proj->projectable, &proj_off_x, &proj_off_y);
+
   for (list = gimp_projectable_get_layers (proj->projectable);
        list;
        list = g_list_next (list))
@@ -272,6 +290,13 @@ gimp_projection_initialize (GimpProjection *proj,
 
       gimp_item_get_offset (item, &off_x, &off_y);
 
+      /*  subtract the projectable's offsets because the list of
+       *  update areas is in tile-pyramid coordinates, but our
+       *  external API is always in terms of image coordinates.
+       */
+      off_x -= proj_off_x;
+      off_y -= proj_off_y;
+
       if (gimp_item_get_visible (item)                          &&
           ! gimp_drawable_has_alpha (drawable)                  &&
           ! gimp_layer_get_mask (layer)                         &&
diff --git a/app/core/gimpprojection.c b/app/core/gimpprojection.c
index d4cfa63..9a928ab 100644
--- a/app/core/gimpprojection.c
+++ b/app/core/gimpprojection.c
@@ -345,6 +345,7 @@ GimpProjection *
 gimp_projection_new (GimpProjectable *projectable)
 {
   GimpProjection *proj;
+  GClosure       *closure;
 
   g_return_val_if_fail (GIMP_IS_PROJECTABLE (projectable), NULL);
 
@@ -352,9 +353,18 @@ gimp_projection_new (GimpProjectable *projectable)
 
   proj->projectable = projectable;
 
-  g_signal_connect_object (projectable, "update",
-                           G_CALLBACK (gimp_projection_projectable_update),
-                           proj, 0);
+  closure = g_cclosure_new_object (G_CALLBACK (gimp_projection_projectable_update),
+                                   G_OBJECT (proj));
+
+  /*  connect the "update" signal by ID so we definitely get the signal
+   *  of GimpPickable and not the one of GimpDrawable in case of group
+   *  layers
+   */
+  g_signal_connect_closure_by_id (projectable,
+                                  g_signal_lookup ("update",
+                                                   GIMP_TYPE_PROJECTABLE), 0,
+                                  closure, FALSE);
+
   g_signal_connect_object (projectable, "flush",
                            G_CALLBACK (gimp_projection_projectable_flush),
                            proj, 0);
@@ -501,9 +511,18 @@ gimp_projection_add_update_area (GimpProjection *proj,
                                  gint            h)
 {
   GimpArea *area;
+  gint      off_x, off_y;
   gint      width, height;
 
-  gimp_projectable_get_size (proj->projectable, &width, &height);
+  gimp_projectable_get_offset (proj->projectable, &off_x, &off_y);
+  gimp_projectable_get_size   (proj->projectable, &width, &height);
+
+  /*  subtract the projectable's offsets because the list of update
+   *  areas is in tile-pyramid coordinates, but our external API is
+   *  always in terms of image coordinates.
+   */
+  x -= off_x;
+  y -= off_y;
 
   area = gimp_area_new (CLAMP (x,     0, width),
                         CLAMP (y,     0, height),
@@ -715,10 +734,12 @@ gimp_projection_paint_area (GimpProjection *proj,
                             gint            w,
                             gint            h)
 {
+  gint off_x, off_y;
   gint width, height;
   gint x1, y1, x2, y2;
 
-  gimp_projectable_get_size (proj->projectable, &width, &height);
+  gimp_projectable_get_offset (proj->projectable, &off_x, &off_y);
+  gimp_projectable_get_size   (proj->projectable, &width, &height);
 
   /*  Bounds check  */
   x1 = CLAMP (x,     0, width);
@@ -728,8 +749,16 @@ gimp_projection_paint_area (GimpProjection *proj,
 
   gimp_projection_invalidate (proj, x1, y1, x2 - x1, y2 - y1);
 
+  /*  add the projectable's offsets because the list of update areas
+   *  is in tile-pyramid coordinates, but our external API is always
+   *  in terms of image coordinates.
+   */
   g_signal_emit (proj, projection_signals[UPDATE], 0,
-                 now, x1, y1, x2 - x1, y2 - y1);
+                 now,
+                 x1 + off_x,
+                 y1 + off_y,
+                 x2 - x1,
+                 y2 - y1);
 }
 
 static void



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