diff --git a/app/core/Makefile.am b/app/core/Makefile.am
index bc0ef130f0..374b3a7c3a 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 9076c316c0..d1c077be2f 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/gimparea.c b/app/core/gimparea.c
deleted file mode 100644
index 6b6db9279c..0000000000
--- a/app/core/gimparea.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/* GIMP - The GNU Image Manipulation Program
- * Copyright (C) 1995 Spencer Kimball and Peter Mattis
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#include "config.h"
-
-#include
-
-#include "core-types.h"
-
-#include "gimparea.h"
-
-
-#define OVERHEAD 25 /* in units of pixel area */
-
-
-GimpArea *
-gimp_area_new (gint x1,
- gint y1,
- gint x2,
- gint y2)
-{
- GimpArea *area = g_slice_new (GimpArea);
-
- area->x1 = x1;
- area->y1 = y1;
- area->x2 = x2;
- area->y2 = y2;
-
- return area;
-}
-
-void
-gimp_area_free (GimpArea *area)
-{
- g_slice_free (GimpArea, area);
-}
-
-
-/*
- * As far as I can tell, this function takes a GimpArea and unifies it with
- * an existing list of GimpAreas, trying to avoid overdraw. [adam]
- */
-GSList *
-gimp_area_list_process (GSList *list,
- GimpArea *area)
-{
- GSList *retval;
- GSList *l;
-
- retval = g_slist_prepend (NULL, area);
-
- for (l = list; l; l = g_slist_next (l))
- {
- GimpArea *this = l->data;
- gint area1;
- gint area2;
- gint area3;
-
- area1 = (area->x2 - area->x1) * (area->y2 - area->y1) + OVERHEAD;
- area2 = (this->x2 - this->x1) * (this->y2 - this->y1) + OVERHEAD;
- area3 = ((MAX (this->x2, area->x2) - MIN (this->x1, area->x1)) *
- (MAX (this->y2, area->y2) - MIN (this->y1, area->y1)) + OVERHEAD);
-
- if (area1 + area2 < area3)
- {
- retval = g_slist_prepend (retval, this);
- }
- else
- {
- area->x1 = MIN (area->x1, this->x1);
- area->y1 = MIN (area->y1, this->y1);
- area->x2 = MAX (area->x2, this->x2);
- area->y2 = MAX (area->y2, this->y2);
-
- g_slice_free (GimpArea, this);
- }
- }
-
- if (list)
- g_slist_free (list);
-
- return retval;
-}
-
-void
-gimp_area_list_free (GSList *areas)
-{
- GSList *list;
-
- for (list = areas; list; list = list->next)
- gimp_area_free (list->data);
-
- g_slist_free (areas);
-}
diff --git a/app/core/gimparea.h b/app/core/gimparea.h
deleted file mode 100644
index 833784ba76..0000000000
--- a/app/core/gimparea.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* GIMP - The GNU Image Manipulation Program
- * Copyright (C) 1995 Spencer Kimball and Peter Mattis
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#ifndef __GIMP_AREA_H__
-#define __GIMP_AREA_H__
-
-
-struct _GimpArea
-{
- gint x1, y1, x2, y2; /* area bounds */
-};
-
-
-GimpArea * gimp_area_new (gint x1,
- gint y1,
- gint x2,
- gint y2);
-void gimp_area_free (GimpArea *area);
-
-GSList * gimp_area_list_process (GSList *list,
- GimpArea *area);
-void gimp_area_list_free (GSList *list);
-
-
-#endif /* __GIMP_AREA_H__ */
diff --git a/app/core/gimpprojection.c b/app/core/gimpprojection.c
index 4a31d066b4..5225d56176 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;
- proj->priv->chunk_render.update_areas =
- gimp_area_list_process (proj->priv->chunk_render.update_areas, area);
+ 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));
+
+ 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 06b8abe869..f7d22b8566 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;
- 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));
+ image_width = gimp_image_get_width (private->image);
+ image_height = gimp_image_get_height (private->image);
- private->update_areas = gimp_area_list_process (private->update_areas,
- area);
+ 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;
+
+ 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)