[gimp] app: remove GimpArea and use cairo_region_t instead



commit 9b341d05bb9926ee6de7aae3d449e2f3031c7b60
Author: Michael Natterer <mitch gimp org>
Date:   Sat May 31 01:22:54 2014 +0200

    app: remove GimpArea and use cairo_region_t instead
    
    This may or may not remove some logic that avoids drawing tiny update
    regions, and may or may not improve things or make them worse. Will
    add code that actually tile-aligns update areas later.

 app/core/Makefile.am      |    2 -
 app/core/core-types.h     |    1 -
 app/core/gimparea.c       |  108 --------------------------
 app/core/gimparea.h       |   39 ----------
 app/core/gimpprojection.c |  184 ++++++++++++++++++++++++++-------------------
 app/display/gimpdisplay.c |   77 ++++++++++---------
 6 files changed, 149 insertions(+), 262 deletions(-)
---
diff --git a/app/core/Makefile.am b/app/core/Makefile.am
index bc0ef13..374b3a7 100644
--- a/app/core/Makefile.am
+++ b/app/core/Makefile.am
@@ -55,8 +55,6 @@ libappcore_a_sources = \
        gimp-user-install.h                     \
        gimp-utils.c                            \
        gimp-utils.h                            \
-       gimparea.c                              \
-       gimparea.h                              \
        gimpbezierdesc.h                        \
        gimpbezierdesc.c                        \
        gimpboundary.c                          \
diff --git a/app/core/core-types.h b/app/core/core-types.h
index 9076c31..d1c077b 100644
--- a/app/core/core-types.h
+++ b/app/core/core-types.h
@@ -197,7 +197,6 @@ typedef struct _GimpTagged          GimpTagged;      /* dummy typedef */
 
 /*  non-object types  */
 
-typedef struct _GimpArea            GimpArea;
 typedef struct _GimpBoundSeg        GimpBoundSeg;
 typedef struct _GimpCoords          GimpCoords;
 typedef struct _GimpGradientSegment GimpGradientSegment;
diff --git a/app/core/gimpprojection.c b/app/core/gimpprojection.c
index 4a31d06..5225d56 100644
--- a/app/core/gimpprojection.c
+++ b/app/core/gimpprojection.c
@@ -29,7 +29,6 @@
 
 #include "gimp.h"
 #include "gimp-utils.h"
-#include "gimparea.h"
 #include "gimpimage.h"
 #include "gimpmarshal.h"
 #include "gimppickable.h"
@@ -67,14 +66,14 @@ typedef struct _GimpProjectionChunkRender GimpProjectionChunkRender;
 
 struct _GimpProjectionChunkRender
 {
-  gboolean running;
-  gint     width;
-  gint     height;
-  gint     x;
-  gint     y;
-  gint     base_x;
-  gint     base_y;
-  GSList  *update_areas;   /*  flushed update areas */
+  gboolean        running;
+  gint            width;
+  gint            height;
+  gint            x;
+  gint            y;
+  gint            base_x;
+  gint            base_y;
+  cairo_region_t *update_region;   /*  flushed update region */
 };
 
 
@@ -87,7 +86,7 @@ struct _GimpProjectionPrivate
   GeglBuffer                *buffer;
   gpointer                   validate_handler;
 
-  GSList                    *update_areas;
+  cairo_region_t            *update_region;
   GimpProjectionChunkRender  chunk_render;
   guint                      chunk_render_idle_id;
 
@@ -227,11 +226,17 @@ gimp_projection_finalize (GObject *object)
   if (proj->priv->chunk_render.running)
     gimp_projection_chunk_render_stop (proj);
 
-  gimp_area_list_free (proj->priv->update_areas);
-  proj->priv->update_areas = NULL;
+  if (proj->priv->update_region)
+    {
+      cairo_region_destroy (proj->priv->update_region);
+      proj->priv->update_region = NULL;
+    }
 
-  gimp_area_list_free (proj->priv->chunk_render.update_areas);
-  proj->priv->chunk_render.update_areas = NULL;
+  if (proj->priv->chunk_render.update_region)
+    {
+      cairo_region_destroy (proj->priv->chunk_render.update_region);
+      proj->priv->chunk_render.update_region = NULL;
+    }
 
   gimp_projection_free_buffer (proj);
 
@@ -512,9 +517,9 @@ gimp_projection_add_update_area (GimpProjection *proj,
                                  gint            w,
                                  gint            h)
 {
-  GimpArea *area;
-  gint      off_x, off_y;
-  gint      width, height;
+  cairo_rectangle_int_t  rect;
+  gint                   off_x, off_y;
+  gint                   width, height;
 
   gimp_projectable_get_offset (proj->priv->projectable, &off_x, &off_y);
   gimp_projectable_get_size   (proj->priv->projectable, &width, &height);
@@ -526,13 +531,15 @@ gimp_projection_add_update_area (GimpProjection *proj,
   x -= off_x;
   y -= off_y;
 
-  area = gimp_area_new (CLAMP (x,     0, width),
-                        CLAMP (y,     0, height),
-                        CLAMP (x + w, 0, width),
-                        CLAMP (y + h, 0, height));
+  rect.x      = CLAMP (x,     0, width);
+  rect.y      = CLAMP (y,     0, height);
+  rect.width  = CLAMP (x + w, 0, width)  - rect.x;
+  rect.height = CLAMP (y + h, 0, height) - rect.y;
 
-  proj->priv->update_areas = gimp_area_list_process (proj->priv->update_areas,
-                                                     area);
+  if (proj->priv->update_region)
+    cairo_region_union_rectangle (proj->priv->update_region, &rect);
+  else
+    proj->priv->update_region = cairo_region_create_rectangle (&rect);
 }
 
 static void
@@ -540,25 +547,26 @@ gimp_projection_flush_whenever (GimpProjection *proj,
                                 gboolean        now)
 {
   /*  First the updates...  */
-  if (proj->priv->update_areas)
+  if (proj->priv->update_region)
     {
       if (now)  /* Synchronous */
         {
-          GSList *list;
+          gint n_rects = cairo_region_num_rectangles (proj->priv->update_region);
+          gint i;
 
-          for (list = proj->priv->update_areas; list; list = g_slist_next (list))
+          for (i = 0; i < n_rects; i++)
             {
-              GimpArea *area = list->data;
+              cairo_rectangle_int_t rect;
 
-              if ((area->x1 != area->x2) && (area->y1 != area->y2))
-                {
-                  gimp_projection_paint_area (proj,
-                                              FALSE, /* sic! */
-                                              area->x1,
-                                              area->y1,
-                                              (area->x2 - area->x1),
-                                              (area->y2 - area->y1));
-                }
+              cairo_region_get_rectangle (proj->priv->update_region,
+                                          i, &rect);
+
+              gimp_projection_paint_area (proj,
+                                          FALSE, /* sic! */
+                                          rect.x,
+                                          rect.y,
+                                          rect.width,
+                                          rect.height);
             }
         }
       else  /* Asynchronous */
@@ -566,9 +574,9 @@ gimp_projection_flush_whenever (GimpProjection *proj,
           gimp_projection_chunk_render_init (proj);
         }
 
-      /*  Free the update lists  */
-      gimp_area_list_free (proj->priv->update_areas);
-      proj->priv->update_areas = NULL;
+      /*  Free the update region  */
+      cairo_region_destroy (proj->priv->update_region);
+      proj->priv->update_region = NULL;
     }
   else if (! now && proj->priv->invalidate_preview)
     {
@@ -638,20 +646,22 @@ gimp_projection_chunk_render_callback (gpointer data)
 static void
 gimp_projection_chunk_render_init (GimpProjection *proj)
 {
-  GSList *list;
-
   /* We need to merge the ChunkRender's and the GimpProjection's
-   * update_areas list to keep track of which of the updates have been
-   * flushed and hence need to be drawn.
+   * update_regions list to keep track of which of the updates have
+   * been flushed and hence need to be drawn.
    */
-  for (list = proj->priv->update_areas; list; list = g_slist_next (list))
+  if (proj->priv->update_region)
     {
-      GimpArea *area = list->data;
-
-      proj->priv->chunk_render.update_areas =
-        gimp_area_list_process (proj->priv->chunk_render.update_areas,
-                                gimp_area_new (area->x1, area->y1,
-                                               area->x2, area->y2));
+      if (proj->priv->chunk_render.update_region)
+        {
+          cairo_region_union (proj->priv->chunk_render.update_region,
+                              proj->priv->update_region);
+        }
+      else
+        {
+          proj->priv->chunk_render.update_region =
+            cairo_region_copy (proj->priv->update_region);
+        }
     }
 
   /* If a chunk renderer was already running, merge the remainder of
@@ -660,24 +670,25 @@ gimp_projection_chunk_render_init (GimpProjection *proj)
    */
   if (proj->priv->chunk_render.running)
     {
-      GimpArea *area =
-        gimp_area_new (proj->priv->chunk_render.base_x,
-                       proj->priv->chunk_render.y,
-                       proj->priv->chunk_render.base_x + proj->priv->chunk_render.width,
-                       proj->priv->chunk_render.y + (proj->priv->chunk_render.height -
-                                                     (proj->priv->chunk_render.y -
-                                                      proj->priv->chunk_render.base_y)));
+      cairo_rectangle_int_t rect;
+
+      rect.x      = proj->priv->chunk_render.base_x;
+      rect.y      = proj->priv->chunk_render.y;
+      rect.width  = proj->priv->chunk_render.width;
+      rect.height = (proj->priv->chunk_render.height -
+                     (proj->priv->chunk_render.y -
+                      proj->priv->chunk_render.base_y));
 
-      proj->priv->chunk_render.update_areas =
-        gimp_area_list_process (proj->priv->chunk_render.update_areas, area);
+      cairo_region_union_rectangle (proj->priv->chunk_render.update_region,
+                                    &rect);
 
       gimp_projection_chunk_render_next_area (proj);
     }
   else
     {
-      if (proj->priv->chunk_render.update_areas == NULL)
+      if (proj->priv->chunk_render.update_region == NULL)
         {
-          g_warning ("%s: wanted to start chunk render with no update_areas",
+          g_warning ("%s: wanted to start chunk render with no update_region",
                      G_STRFUNC);
           return;
         }
@@ -702,14 +713,18 @@ gimp_projection_chunk_render_iteration (GimpProjection *proj)
   gint workw = GIMP_PROJECTION_CHUNK_WIDTH;
   gint workh = GIMP_PROJECTION_CHUNK_HEIGHT;
 
-  if (workx + workw > proj->priv->chunk_render.base_x + proj->priv->chunk_render.width)
+  if (workx + workw >
+      proj->priv->chunk_render.base_x + proj->priv->chunk_render.width)
     {
-      workw = proj->priv->chunk_render.base_x + proj->priv->chunk_render.width - workx;
+      workw = (proj->priv->chunk_render.base_x +
+               proj->priv->chunk_render.width - workx);
     }
 
-  if (worky + workh > proj->priv->chunk_render.base_y + proj->priv->chunk_render.height)
+  if (worky + workh >
+      proj->priv->chunk_render.base_y + proj->priv->chunk_render.height)
     {
-      workh = proj->priv->chunk_render.base_y + proj->priv->chunk_render.height - worky;
+      workh = (proj->priv->chunk_render.base_y +
+               proj->priv->chunk_render.height - worky);
     }
 
   gimp_projection_paint_area (proj, TRUE /* sic! */,
@@ -751,22 +766,34 @@ gimp_projection_chunk_render_iteration (GimpProjection *proj)
 static gboolean
 gimp_projection_chunk_render_next_area (GimpProjection *proj)
 {
-  GimpArea *area;
+  cairo_rectangle_int_t rect;
 
-  if (! proj->priv->chunk_render.update_areas)
+  if (! proj->priv->chunk_render.update_region)
     return FALSE;
 
-  area = proj->priv->chunk_render.update_areas->data;
+  if (cairo_region_is_empty (proj->priv->chunk_render.update_region))
+    {
+      cairo_region_destroy (proj->priv->chunk_render.update_region);
+      proj->priv->chunk_render.update_region = NULL;
 
-  proj->priv->chunk_render.update_areas =
-    g_slist_remove (proj->priv->chunk_render.update_areas, area);
+      return FALSE;
+    }
 
-  proj->priv->chunk_render.x      = proj->priv->chunk_render.base_x = area->x1;
-  proj->priv->chunk_render.y      = proj->priv->chunk_render.base_y = area->y1;
-  proj->priv->chunk_render.width  = area->x2 - area->x1;
-  proj->priv->chunk_render.height = area->y2 - area->y1;
+  cairo_region_get_rectangle (proj->priv->chunk_render.update_region,
+                              0, &rect);
+  cairo_region_subtract_rectangle (proj->priv->chunk_render.update_region,
+                                   &rect);
 
-  gimp_area_free (area);
+  if (cairo_region_is_empty (proj->priv->chunk_render.update_region))
+    {
+      cairo_region_destroy (proj->priv->chunk_render.update_region);
+      proj->priv->chunk_render.update_region = NULL;
+    }
+
+  proj->priv->chunk_render.x      = proj->priv->chunk_render.base_x = rect.x;
+  proj->priv->chunk_render.y      = proj->priv->chunk_render.base_y = rect.y;
+  proj->priv->chunk_render.width  = rect.width;
+  proj->priv->chunk_render.height = rect.height;
 
   return TRUE;
 }
@@ -854,8 +881,11 @@ gimp_projection_projectable_changed (GimpProjectable *projectable,
   if (proj->priv->chunk_render.running)
     gimp_projection_chunk_render_stop (proj);
 
-  gimp_area_list_free (proj->priv->update_areas);
-  proj->priv->update_areas = NULL;
+  if (proj->priv->update_region)
+    {
+      cairo_region_destroy (proj->priv->update_region);
+      proj->priv->update_region = NULL;
+    }
 
   gimp_projection_free_buffer (proj);
 
diff --git a/app/display/gimpdisplay.c b/app/display/gimpdisplay.c
index 06b8abe..f7d22b8 100644
--- a/app/display/gimpdisplay.c
+++ b/app/display/gimpdisplay.c
@@ -28,7 +28,6 @@
 #include "config/gimpguiconfig.h"
 
 #include "core/gimp.h"
-#include "core/gimparea.h"
 #include "core/gimpcontainer.h"
 #include "core/gimpcontext.h"
 #include "core/gimpimage.h"
@@ -68,16 +67,16 @@ typedef struct _GimpDisplayPrivate GimpDisplayPrivate;
 
 struct _GimpDisplayPrivate
 {
-  gint       ID;           /*  unique identifier for this display  */
+  gint            ID;           /*  unique identifier for this display  */
 
-  GimpImage *image;        /*  pointer to the associated image     */
-  gint       instance;     /*  the instance # of this display as
-                            *  taken from the image at creation    */
+  GimpImage      *image;        /*  pointer to the associated image     */
+  gint            instance;     /*  the instance # of this display as
+                                 *  taken from the image at creation    */
 
-  GtkWidget *shell;
-  GSList    *update_areas;
+  GtkWidget      *shell;
+  cairo_region_t *update_region;
 
-  guint64    last_flush_now;
+  guint64         last_flush_now;
 };
 
 #define GIMP_DISPLAY_GET_PRIVATE(display) \
@@ -505,10 +504,6 @@ gimp_display_delete (GimpDisplay *display)
   if (active_tool && active_tool->focus_display == display)
     tool_manager_focus_display_active (display->gimp, NULL);
 
-  /*  free the update area lists  */
-  gimp_area_list_free (private->update_areas);
-  private->update_areas = NULL;
-
   if (private->shell)
     {
       GimpDisplayShell *shell  = gimp_display_get_shell (display);
@@ -657,6 +652,12 @@ gimp_display_set_image (GimpDisplay *display,
 
       gimp_display_disconnect (display);
 
+      if (private->update_region)
+        {
+          cairo_region_destroy (private->update_region);
+          private->update_region = NULL;
+        }
+
       gimp_image_dec_display_count (private->image);
 
       /*  set private->image before unrefing because there may be code
@@ -789,17 +790,22 @@ gimp_display_update_area (GimpDisplay *display,
     }
   else
     {
-      GimpArea *area;
-      gint      image_width  = gimp_image_get_width  (private->image);
-      gint      image_height = gimp_image_get_height (private->image);
+      cairo_rectangle_int_t rect;
+      gint                  image_width;
+      gint                  image_height;
+
+      image_width  = gimp_image_get_width  (private->image);
+      image_height = gimp_image_get_height (private->image);
 
-      area = gimp_area_new (CLAMP (x,     0, image_width),
-                            CLAMP (y,     0, image_height),
-                            CLAMP (x + w, 0, image_width),
-                            CLAMP (y + h, 0, image_height));
+      rect.x      = CLAMP (x,     0, image_width);
+      rect.y      = CLAMP (y,     0, image_height);
+      rect.width  = CLAMP (x + w, 0, image_width)  - rect.x;
+      rect.height = CLAMP (y + h, 0, image_height) - rect.y;
 
-      private->update_areas = gimp_area_list_process (private->update_areas,
-                                                      area);
+      if (private->update_region)
+        cairo_region_union_rectangle (private->update_region, &rect);
+      else
+        private->update_region = cairo_region_create_rectangle (&rect);
     }
 }
 
@@ -828,26 +834,27 @@ gimp_display_flush_whenever (GimpDisplay *display,
 {
   GimpDisplayPrivate *private = GIMP_DISPLAY_GET_PRIVATE (display);
 
-  if (private->update_areas)
+  if (private->update_region)
     {
-      GSList *list;
+      gint n_rects = cairo_region_num_rectangles (private->update_region);
+      gint i;
 
-      for (list = private->update_areas; list; list = g_slist_next (list))
+      for (i = 0; i < n_rects; i++)
         {
-          GimpArea *area = list->data;
+          cairo_rectangle_int_t rect;
 
-          if ((area->x1 != area->x2) && (area->y1 != area->y2))
-            {
-              gimp_display_paint_area (display,
-                                       area->x1,
-                                       area->y1,
-                                       (area->x2 - area->x1),
-                                       (area->y2 - area->y1));
-            }
+          cairo_region_get_rectangle (private->update_region,
+                                      i, &rect);
+
+          gimp_display_paint_area (display,
+                                   rect.x,
+                                   rect.y,
+                                   rect.width,
+                                   rect.height);
         }
 
-      gimp_area_list_free (private->update_areas);
-      private->update_areas = NULL;
+      cairo_region_destroy (private->update_region);
+      private->update_region = NULL;
     }
 
   if (now)


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