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)