From c5ec0d4f7087d2a9c8dcab767d2226869d77e5f5 Mon Sep 17 00:00:00 2001 From: Michael Natterer Date: Tue, 13 Jul 2004 16:36:29 +0000 Subject: [PATCH] *** empty log message *** --- ChangeLog | 61 +- app/core/Makefile.am | 8 +- app/core/core-types.h | 2 + app/core/gimparea.c | 12 +- app/core/gimparea.h | 22 +- app/core/gimpchannel.c | 4 +- app/core/gimpimage-contiguous-region.c | 30 +- app/core/gimpimage-convert.c | 1 - app/core/gimpimage-crop.c | 10 +- app/core/gimpimage-merge.c | 1 - app/core/gimpimage-pick-color.c | 8 +- app/core/gimpimage-projection.c | 790 --------------------- app/core/gimpimage-projection.h | 55 -- app/core/gimpimage-scale.c | 2 +- app/core/gimpimage.c | 58 +- app/core/gimpimage.h | 9 +- app/core/gimpmarshal.list | 1 + app/core/gimppalette-import.c | 10 +- app/core/gimpprojection-construct.c | 890 ++++++++--------------- app/core/gimpprojection-construct.h | 41 +- app/core/gimpprojection.c | 931 ++++++++++++------------- app/core/gimpprojection.h | 85 ++- app/dialogs/info-window.c | 6 +- app/display/Makefile.am | 2 - app/display/gimpdisplay-area.c | 105 --- app/display/gimpdisplay-area.h | 41 -- app/display/gimpdisplay-foreach.c | 19 - app/display/gimpdisplay-foreach.h | 1 - app/display/gimpdisplay-handlers.c | 71 +- app/display/gimpdisplay.c | 405 ++--------- app/display/gimpdisplay.h | 60 +- app/display/gimpdisplayshell-render.c | 14 +- app/display/gimpdisplayshell.c | 21 +- app/gui/info-window.c | 6 +- app/tools/gimpbrushtool.c | 3 + app/tools/gimpbucketfilltool.c | 2 +- app/tools/gimpbycolorselecttool.c | 10 +- app/tools/gimpclonetool.c | 2 +- app/tools/gimpcolortool.c | 2 +- app/tools/gimpeditselectiontool.c | 3 +- app/tools/gimpfliptool.c | 2 +- app/tools/gimpimagemaptool.c | 2 + app/tools/gimpiscissorstool.c | 6 +- app/tools/gimppainttool.c | 3 + app/tools/gimpselectiontool.c | 4 +- app/tools/gimpsourcetool.c | 2 +- app/tools/gimptransformtool.c | 6 +- app/widgets/gimpselectioneditor.c | 5 +- 48 files changed, 1134 insertions(+), 2700 deletions(-) delete mode 100644 app/core/gimpimage-projection.c delete mode 100644 app/core/gimpimage-projection.h delete mode 100644 app/display/gimpdisplay-area.c delete mode 100644 app/display/gimpdisplay-area.h diff --git a/ChangeLog b/ChangeLog index f2343f481f..605a7f4529 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,62 @@ +2004-07-13 Michael Natterer + + Added a GimpProjection object which maintains the idle projection + logic that was in GimpDisplay and takes care of constructing the + projection even without any display open. Makes color picking and + other reads from the projection work without display and fixes the + major bug that we were constructing the projection n times (!) + for n displays. + + * app/core/Makefile.am + * app/core/gimpimage-projection.[ch]: removed. + + * app/core/core-types.h + * app/core/gimpmarshal.list + * app/core/gimparea.[ch] + * app/core/gimpprojection.[ch] + * app/core/gimpprojection-construct.[ch]: new files assembled from + the pieces of gimpdisplay.c and gimpimage-projection.c. + + * app/core/gimpimage.[ch]: create a GimpProjection. + Removed explicit projection realloc calls because the projection + connects to the relevant GimpImage signals now. + Added gimp_image_coords_in_active_drawable(). + + * app/display/Makefile.am + * app/display/gimpdisplay-area.[ch]: removed. + + * app/display/gimpdisplay.[ch]: stripped away the idle render stuff + and just keep a list of update_areas which is painted on flush(). + Removed gimp_display_coords_in_active_drawable(). + + * app/display/gimpdisplay-foreach.[ch]: removed + gimp_display_finish_draw(). + + * app/core/gimpchannel.c + * app/core/gimpimage-contiguous-region.c + * app/core/gimpimage-convert.c + * app/core/gimpimage-crop.c + * app/core/gimpimage-merge.c + * app/core/gimpimage-pick-color.c + * app/core/gimpimage-scale.c + * app/core/gimppalette-import.c + * app/display/gimpdisplay-handlers.c + * app/display/gimpdisplayshell-render.c + * app/display/gimpdisplayshell.c + * app/gui/info-window.c + * app/tools/gimpbucketfilltool.c + * app/tools/gimpbycolorselecttool.c + * app/tools/gimpclonetool.c + * app/tools/gimpcolortool.c + * app/tools/gimpeditselectiontool.c + * app/tools/gimpfliptool.c + * app/tools/gimpimagemaptool.c + * app/tools/gimpiscissorstool.c + * app/tools/gimppainttool.c + * app/tools/gimpselectiontool.c + * app/tools/gimptransformtool.c + * app/widgets/gimpselectioneditor.c: changed accordingly. + 2004-07-13 Sven Neumann * libgimpwidgets/gimppixmap.[ch]: declared GimpPixmap as deprecated. @@ -27,7 +86,7 @@ * plug-ins/pagecurl/pagecurl.c: undef GIMP_DISABLE_DEPRECATED until GimpPixmap has been replaced here as well. - + 2004-07-13 Shlomi Fish * plug-ins/gimpressionist/presets.c: fixed bug #147483 (gimpressionist diff --git a/app/core/Makefile.am b/app/core/Makefile.am index 64db3623ba..142201c0dd 100644 --- a/app/core/Makefile.am +++ b/app/core/Makefile.am @@ -42,6 +42,8 @@ libappcore_a_sources = \ gimp-units.h \ gimp-utils.c \ gimp-utils.h \ + gimparea.c \ + gimparea.h \ gimpbrush.c \ gimpbrush.h \ gimpbrush-header.h \ @@ -131,8 +133,6 @@ libappcore_a_sources = \ gimpimage-pick-color.h \ gimpimage-preview.c \ gimpimage-preview.h \ - gimpimage-projection.c \ - gimpimage-projection.h \ gimpimage-qmask.c \ gimpimage-qmask.h \ gimpimage-resize.c \ @@ -182,6 +182,10 @@ libappcore_a_sources = \ gimpparasitelist.h \ gimppreviewcache.c \ gimppreviewcache.h \ + gimpprojection.c \ + gimpprojection.h \ + gimpprojection-construct.c \ + gimpprojection-construct.h \ gimpscanconvert.c \ gimpscanconvert.h \ gimpselection.c \ diff --git a/app/core/core-types.h b/app/core/core-types.h index d8215f7809..e10dbce90b 100644 --- a/app/core/core-types.h +++ b/app/core/core-types.h @@ -117,10 +117,12 @@ typedef struct _GimpImageMap GimpImageMap; typedef struct _GimpDocumentList GimpDocumentList; typedef struct _GimpEnvironTable GimpEnvironTable; typedef struct _GimpParasiteList GimpParasiteList; +typedef struct _GimpProjection GimpProjection; /* non-object types */ +typedef struct _GimpArea GimpArea; typedef struct _GimpCoords GimpCoords; typedef struct _GimpGradientSegment GimpGradientSegment; typedef struct _GimpGuide GimpGuide; diff --git a/app/core/gimparea.c b/app/core/gimparea.c index 29c411d36e..23a1f5396e 100644 --- a/app/core/gimparea.c +++ b/app/core/gimparea.c @@ -18,11 +18,11 @@ #include "config.h" -#include +#include -#include "display-types.h" +#include "core-types.h" -#include "gimpdisplay-area.h" +#include "gimparea.h" #define OVERHEAD 25 /* in units of pixel area */ @@ -51,8 +51,8 @@ gimp_area_new (gint x1, * an existing list of GimpAreas, trying to avoid overdraw. [adam] */ GSList * -gimp_display_area_list_process (GSList *list, - GimpArea *area) +gimp_area_list_process (GSList *list, + GimpArea *area) { GSList *new_list; GSList *l; @@ -93,7 +93,7 @@ gimp_display_area_list_process (GSList *list, } GSList * -gimp_display_area_list_free (GSList *list) +gimp_area_list_free (GSList *list) { if (list) { diff --git a/app/core/gimparea.h b/app/core/gimparea.h index 81067df212..ad478b91fd 100644 --- a/app/core/gimparea.h +++ b/app/core/gimparea.h @@ -16,26 +16,24 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#ifndef __GIMP_DISPLAY_AREA_H__ -#define __GIMP_DISPLAY_AREA_H__ +#ifndef __GIMP_AREA_H__ +#define __GIMP_AREA_H__ -typedef struct _GimpArea GimpArea; - struct _GimpArea { gint x1, y1, x2, y2; /* area bounds */ }; -GimpArea * gimp_area_new (gint x1, - gint y1, - gint x2, - gint y2); +GimpArea * gimp_area_new (gint x1, + gint y1, + gint x2, + gint y2); -GSList * gimp_display_area_list_process (GSList *list, - GimpArea *area); -GSList * gimp_display_area_list_free (GSList *list); +GSList * gimp_area_list_process (GSList *list, + GimpArea *area); +GSList * gimp_area_list_free (GSList *list); -#endif /* __GIMP_DISPLAY_AREA_H__ */ +#endif /* __GIMP_AREA_H__ */ diff --git a/app/core/gimpchannel.c b/app/core/gimpchannel.c index 0e6a9052e4..16c723c9d1 100644 --- a/app/core/gimpchannel.c +++ b/app/core/gimpchannel.c @@ -43,7 +43,6 @@ #include "gimp-utils.h" #include "gimpcontainer.h" #include "gimpimage.h" -#include "gimpimage-projection.h" #include "gimpimage-undo.h" #include "gimpimage-undo-push.h" #include "gimpchannel.h" @@ -51,6 +50,7 @@ #include "gimpdrawable-stroke.h" #include "gimpmarshal.h" #include "gimppaintinfo.h" +#include "gimpprojection.h" #include "gimpstrokeoptions.h" #include "gimp-intl.h" @@ -1497,7 +1497,7 @@ gimp_channel_new_from_component (GimpImage *gimage, g_return_val_if_fail (pixel != -1, NULL); - projection = gimp_image_projection (gimage); + projection = gimp_projection_get_tiles (gimage->projection); width = tile_manager_width (projection); height = tile_manager_height (projection); diff --git a/app/core/gimpimage-contiguous-region.c b/app/core/gimpimage-contiguous-region.c index f280e2b39e..c617ec586f 100644 --- a/app/core/gimpimage-contiguous-region.c +++ b/app/core/gimpimage-contiguous-region.c @@ -33,7 +33,7 @@ #include "gimpchannel.h" #include "gimpimage.h" #include "gimpimage-contiguous-region.h" -#include "gimpimage-projection.h" +#include "gimpprojection.h" /* local function prototypes */ @@ -104,13 +104,14 @@ gimp_image_contiguous_region_by_seed (GimpImage *gimage, if (sample_merged) { - pixel_region_init (&srcPR, gimp_image_projection (gimage), 0, 0, - gimage->width, gimage->height, FALSE); + GimpProjection *projection = gimage->projection; - src_type = gimp_image_projection_type (gimage); - has_alpha = - GIMP_IMAGE_TYPE_HAS_ALPHA (gimp_image_projection_type (gimage)); - bytes = gimp_image_projection_bytes (gimage); + pixel_region_init (&srcPR, gimp_projection_get_tiles (projection), + 0, 0, gimage->width, gimage->height, FALSE); + + src_type = gimp_projection_get_image_type (projection); + has_alpha = GIMP_IMAGE_TYPE_HAS_ALPHA (src_type); + bytes = gimp_projection_get_bytes (projection); } else { @@ -216,17 +217,16 @@ gimp_image_contiguous_region_by_color (GimpImage *gimage, /* Get the image information */ if (sample_merged) { - bytes = gimp_image_projection_bytes (gimage); - d_type = gimp_image_projection_type (gimage); + bytes = gimp_projection_get_bytes (gimage->projection); + d_type = gimp_projection_get_image_type (gimage->projection); has_alpha = GIMP_IMAGE_TYPE_HAS_ALPHA (d_type); indexed = GIMP_IMAGE_TYPE_IS_INDEXED (d_type); width = gimage->width; height = gimage->height; - pixel_region_init (&imagePR, gimp_image_projection (gimage), - 0, 0, - width, height, - FALSE); + pixel_region_init (&imagePR, + gimp_projection_get_tiles (gimage->projection), + 0, 0, width, height, FALSE); } else { @@ -238,9 +238,7 @@ gimp_image_contiguous_region_by_color (GimpImage *gimage, height = gimp_item_height (GIMP_ITEM (drawable)); pixel_region_init (&imagePR, gimp_drawable_data (drawable), - 0, 0, - width, height, - FALSE); + 0, 0, width, height, FALSE); } if (has_alpha) diff --git a/app/core/gimpimage-convert.c b/app/core/gimpimage-convert.c index 1ad5273f2c..d80f36e54a 100644 --- a/app/core/gimpimage-convert.c +++ b/app/core/gimpimage-convert.c @@ -139,7 +139,6 @@ #include "gimpdrawable.h" #include "gimpimage.h" #include "gimpimage-colormap.h" -#include "gimpimage-projection.h" #include "gimpimage-undo.h" #include "gimpimage-undo-push.h" #include "gimplist.h" diff --git a/app/core/gimpimage-crop.c b/app/core/gimpimage-crop.c index 7c00632cf6..25b5ffebb4 100644 --- a/app/core/gimpimage-crop.c +++ b/app/core/gimpimage-crop.c @@ -31,11 +31,11 @@ #include "gimpimage.h" #include "gimpimage-crop.h" #include "gimpimage-guides.h" -#include "gimpimage-projection.h" #include "gimpimage-undo.h" #include "gimpimage-undo-push.h" #include "gimplayer.h" #include "gimplist.h" +#include "gimpprojection.h" #include "gimp-intl.h" @@ -293,9 +293,9 @@ gimp_image_crop_auto_shrink (GimpImage *gimage, else { has_alpha = TRUE; - bytes = gimp_image_projection_bytes (gimage); - get_color_obj = G_OBJECT (gimage); - get_color_func = (GetColorFunc) gimp_image_projection_get_color_at; + bytes = gimp_projection_get_bytes (gimage->projection); + get_color_obj = G_OBJECT (gimage->projection); + get_color_func = (GetColorFunc) gimp_projection_get_color_at; } switch (gimp_image_crop_guess_bgcolor (get_color_obj, get_color_func, @@ -320,7 +320,7 @@ gimp_image_crop_auto_shrink (GimpImage *gimage, pixel_region_init (&PR, gimp_drawable_data (active_drawable), x1, y1, width, height, FALSE); else - pixel_region_init (&PR, gimp_image_projection (gimage), + pixel_region_init (&PR, gimp_projection_get_tiles (gimage->projection), x1, y1, width, height, FALSE); /* The following could be optimized further by processing diff --git a/app/core/gimpimage-merge.c b/app/core/gimpimage-merge.c index 18743e0a5b..11ca981d81 100644 --- a/app/core/gimpimage-merge.c +++ b/app/core/gimpimage-merge.c @@ -39,7 +39,6 @@ #include "gimpimage.h" #include "gimpimage-colorhash.h" #include "gimpimage-merge.h" -#include "gimpimage-projection.h" #include "gimpimage-undo.h" #include "gimplayer.h" #include "gimplayer-floating-sel.h" diff --git a/app/core/gimpimage-pick-color.c b/app/core/gimpimage-pick-color.c index dec2676526..37a229dcba 100644 --- a/app/core/gimpimage-pick-color.c +++ b/app/core/gimpimage-pick-color.c @@ -27,7 +27,7 @@ #include "core/gimpdrawable.h" #include "core/gimpimage.h" #include "core/gimpimage-pick-color.h" -#include "core/gimpimage-projection.h" +#include "core/gimpprojection.h" gboolean @@ -55,11 +55,11 @@ gimp_image_pick_color (GimpImage *gimage, if (sample_merged) { - my_sample_type = gimp_image_projection_type (gimage); + my_sample_type = gimp_projection_get_image_type (gimage->projection); is_indexed = FALSE; - color_func = (GimpImagePickColorFunc) gimp_image_projection_get_color_at; - color_obj = GIMP_OBJECT (gimage); + color_func = (GimpImagePickColorFunc) gimp_projection_get_color_at; + color_obj = GIMP_OBJECT (gimage->projection); } else { diff --git a/app/core/gimpimage-projection.c b/app/core/gimpimage-projection.c deleted file mode 100644 index c229177d10..0000000000 --- a/app/core/gimpimage-projection.c +++ /dev/null @@ -1,790 +0,0 @@ -/* The GIMP -- an 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include "libgimpcolor/gimpcolor.h" - -#include "core-types.h" - -#include "base/pixel-region.h" -#include "base/tile-manager.h" -#include "base/tile.h" - -#include "paint-funcs/paint-funcs.h" - -#include "gimp.h" -#include "gimpimage.h" -#include "gimpimage-projection.h" -#include "gimplayer.h" -#include "gimplayer-floating-sel.h" -#include "gimplayermask.h" -#include "gimplist.h" - - -/* local function prototypes */ - -static void gimp_image_projection_validate_tile (TileManager *tm, - Tile *tile); -static void gimp_image_construct_layers (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h); -static void gimp_image_construct_channels (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h); -static void gimp_image_initialize_projection (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h); -static void gimp_image_construct (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h); - -static void project_intensity (GimpImage *gimage, - GimpLayer *layer, - PixelRegion *src, - PixelRegion *dest, - PixelRegion *mask); -static void project_intensity_alpha (GimpImage *gimage, - GimpLayer *layer, - PixelRegion *src, - PixelRegion *dest, - PixelRegion *mask); -static void project_indexed (GimpImage *gimage, - GimpLayer *layer, - PixelRegion *src, - PixelRegion *dest); -static void project_indexed_alpha (GimpImage *gimage, - GimpLayer *layer, - PixelRegion *src, - PixelRegion *dest, - PixelRegion *mask); -static void project_channel (GimpImage *gimage, - GimpChannel *channel, - PixelRegion *src, - PixelRegion *src2); - - -/* public functions */ - -void -gimp_image_projection_allocate (GimpImage *gimage) -{ - GimpImageType proj_type = 0; - gint proj_bytes = 0; - - g_return_if_fail (GIMP_IS_IMAGE (gimage)); - - /* Find the number of bytes required for the projection. - * This includes the intensity channels and an alpha channel - * if one doesn't exist. - */ - switch (gimp_image_base_type (gimage)) - { - case GIMP_RGB: - case GIMP_INDEXED: - proj_bytes = 4; - proj_type = GIMP_RGBA_IMAGE; - break; - - case GIMP_GRAY: - proj_bytes = 2; - proj_type = GIMP_GRAYA_IMAGE; - break; - - default: - g_assert_not_reached (); - } - - if (gimage->projection) - { - if (proj_type != gimage->proj_type || - proj_bytes != gimage->proj_bytes || - gimage->width != tile_manager_width (gimage->projection) || - gimage->height != tile_manager_height (gimage->projection)) - { - gimp_image_projection_free (gimage); - } - } - - if (! gimage->projection) - { - gimage->proj_type = proj_type; - gimage->proj_bytes = proj_bytes; - - gimage->projection = tile_manager_new (gimage->width, gimage->height, - gimage->proj_bytes); - tile_manager_set_user_data (gimage->projection, gimage); - tile_manager_set_validate_proc (gimage->projection, - gimp_image_projection_validate_tile); - } -} - -void -gimp_image_projection_free (GimpImage *gimage) -{ - g_return_if_fail (GIMP_IS_IMAGE (gimage)); - - if (gimage->projection) - { - tile_manager_unref (gimage->projection); - gimage->projection = NULL; - } -} - -TileManager * -gimp_image_projection (GimpImage *gimage) -{ - g_return_val_if_fail (GIMP_IS_IMAGE (gimage), NULL); - - if (gimage->projection == NULL || - tile_manager_width (gimage->projection) != gimage->width || - tile_manager_height (gimage->projection) != gimage->height) - { - gimp_image_projection_allocate (gimage); - } - - return gimage->projection; -} - -GimpImageType -gimp_image_projection_type (const GimpImage *gimage) -{ - g_return_val_if_fail (GIMP_IS_IMAGE (gimage), -1); - - return gimage->proj_type; -} - -gint -gimp_image_projection_bytes (const GimpImage *gimage) -{ - g_return_val_if_fail (GIMP_IS_IMAGE (gimage), -1); - - return gimage->proj_bytes; -} - -gdouble -gimp_image_projection_opacity (const GimpImage *gimage) -{ - g_return_val_if_fail (GIMP_IS_IMAGE (gimage), GIMP_OPACITY_OPAQUE); - - return GIMP_OPACITY_OPAQUE; -} - -guchar * -gimp_image_projection_get_color_at (GimpImage *gimage, - gint x, - gint y) -{ - Tile *tile; - guchar *src; - guchar *dest; - - g_return_val_if_fail (GIMP_IS_IMAGE (gimage), NULL); - - if (x < 0 || y < 0 || x >= gimage->width || y >= gimage->height) - return NULL; - - dest = g_new (guchar, 5); - tile = tile_manager_get_tile (gimp_image_projection (gimage), x, y, - TRUE, FALSE); - src = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT); - gimp_image_get_color (gimage, gimp_image_projection_type (gimage), src, dest); - - dest[4] = 0; - tile_release (tile, FALSE); - - return dest; -} - -void -gimp_image_invalidate (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h, - gint x1, - gint y1, - gint x2, - gint y2) -{ - Tile *tile; - TileManager *tm; - gint i, j; - gint startx, starty; - gint endx, endy; - gint tilex, tiley; - - g_return_if_fail (GIMP_IS_IMAGE (gimage)); - - tm = gimp_image_projection (gimage); - - startx = x; - starty = y; - endx = x + w; - endy = y + h; - - /* invalidate all tiles which are located outside of the displayed area - * all tiles inside the displayed area are constructed. - */ - for (i = y; i < (y + h); i += (TILE_HEIGHT - (i % TILE_HEIGHT))) - for (j = x; j < (x + w); j += (TILE_WIDTH - (j % TILE_WIDTH))) - { - tile = tile_manager_get_tile (tm, j, i, FALSE, FALSE); - - /* check if the tile is outside the bounds */ - if ((MIN ((j + tile_ewidth (tile)), x2) - MAX (j, x1)) <= 0) - { - tile_invalidate_tile (&tile, tm, j, i); - - if (j < x1) - startx = MAX (startx, - (j - (j % TILE_WIDTH) + tile_ewidth (tile))); - else - endx = MIN (endx, j); - } - else if (MIN ((i + tile_eheight (tile)), y2) - MAX (i, y1) <= 0) - { - tile_invalidate_tile (&tile, tm, j, i); - - if (i < y1) - starty = MAX (starty, - (i - (i % TILE_HEIGHT) + tile_eheight (tile))); - else - endy = MIN (endy, i); - } - else - { - /* If the tile is not valid, make sure we get the entire tile - * in the construction extents - */ - if (! tile_is_valid (tile)) - { - tilex = j - (j % TILE_WIDTH); - tiley = i - (i % TILE_HEIGHT); - - startx = MIN (startx, tilex); - endx = MAX (endx, tilex + tile_ewidth (tile)); - starty = MIN (starty, tiley); - endy = MAX (endy, tiley + tile_eheight (tile)); - - tile_mark_valid (tile); /* hmmmmmmm..... */ - } - } - } - - if ((endx - startx) > 0 && (endy - starty) > 0) - gimp_image_construct (gimage, - startx, starty, - (endx - startx), (endy - starty)); -} - -void -gimp_image_invalidate_without_render (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h, - gint x1, - gint y1, - gint x2, - gint y2) -{ - Tile *tile; - TileManager *tm; - gint i, j; - - g_return_if_fail (GIMP_IS_IMAGE (gimage)); - - tm = gimp_image_projection (gimage); - - /* invalidate all tiles which are located outside of the displayed area - * all tiles inside the displayed area are constructed. - */ - for (i = y; i < (y + h); i += (TILE_HEIGHT - (i % TILE_HEIGHT))) - for (j = x; j < (x + w); j += (TILE_WIDTH - (j % TILE_WIDTH))) - { - tile = tile_manager_get_tile (tm, j, i, FALSE, FALSE); - - /* check if the tile is outside the bounds */ - if ((MIN ((j + tile_ewidth(tile)), x2) - MAX (j, x1)) <= 0) - { - tile_invalidate_tile (&tile, tm, j, i); - } - else if (MIN ((i + tile_eheight(tile)), y2) - MAX (i, y1) <= 0) - { - tile_invalidate_tile (&tile, tm, j, i); - } - } -} - - -/* private functions */ - -static void -gimp_image_projection_validate_tile (TileManager *tm, - Tile *tile) -{ - GimpImage *gimage; - gint x, y; - gint w, h; - - /* Get the gimage from the tilemanager */ - gimage = (GimpImage *) tile_manager_get_user_data (tm); - - gimp_set_busy_until_idle (gimage->gimp); - - /* Find the coordinates of this tile */ - tile_manager_get_tile_coordinates (tm, tile, &x, &y); - w = tile_ewidth (tile); - h = tile_eheight (tile); - - gimp_image_construct (gimage, x, y, w, h); -} - -static void -gimp_image_construct_layers (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h) -{ - GimpLayer *layer; - gint x1, y1, x2, y2; - PixelRegion src1PR, src2PR, maskPR; - PixelRegion * mask; - GList *list; - GList *reverse_list; - gint off_x; - gint off_y; - - /* composite the floating selection if it exists */ - if ((layer = gimp_image_floating_sel (gimage))) - floating_sel_composite (layer, x, y, w, h, FALSE); - - - reverse_list = NULL; - - for (list = GIMP_LIST (gimage->layers)->list; - list; - list = g_list_next (list)) - { - layer = (GimpLayer *) list->data; - - /* only add layers that are visible and not floating selections - * to the list - */ - if (! gimp_layer_is_floating_sel (layer) && - gimp_item_get_visible (GIMP_ITEM (layer))) - { - reverse_list = g_list_prepend (reverse_list, layer); - } - } - - for (list = reverse_list; list; list = g_list_next (list)) - { - layer = (GimpLayer *) list->data; - - gimp_item_offsets (GIMP_ITEM (layer), &off_x, &off_y); - - x1 = CLAMP (off_x, x, x + w); - y1 = CLAMP (off_y, y, y + h); - x2 = CLAMP (off_x + gimp_item_width (GIMP_ITEM (layer)), x, x + w); - y2 = CLAMP (off_y + gimp_item_height (GIMP_ITEM (layer)), y, y + h); - - /* configure the pixel regions */ - pixel_region_init (&src1PR, gimp_image_projection (gimage), - x1, y1, (x2 - x1), (y2 - y1), - TRUE); - - /* If we're showing the layer mask instead of the layer... */ - if (layer->mask && layer->mask->show_mask) - { - pixel_region_init (&src2PR, - gimp_drawable_data (GIMP_DRAWABLE (layer->mask)), - (x1 - off_x), (y1 - off_y), - (x2 - x1), (y2 - y1), FALSE); - - copy_gray_to_region (&src2PR, &src1PR); - } - /* Otherwise, normal */ - else - { - pixel_region_init (&src2PR, - gimp_drawable_data (GIMP_DRAWABLE (layer)), - (x1 - off_x), (y1 - off_y), - (x2 - x1), (y2 - y1), FALSE); - - if (layer->mask && layer->mask->apply_mask) - { - pixel_region_init (&maskPR, - gimp_drawable_data (GIMP_DRAWABLE (layer->mask)), - (x1 - off_x), (y1 - off_y), - (x2 - x1), (y2 - y1), FALSE); - mask = &maskPR; - } - else - mask = NULL; - - /* Based on the type of the layer, project the layer onto the - * projection image... - */ - switch (gimp_drawable_type (GIMP_DRAWABLE (layer))) - { - case GIMP_RGB_IMAGE: case GIMP_GRAY_IMAGE: - /* no mask possible */ - project_intensity (gimage, layer, &src2PR, &src1PR, mask); - break; - - case GIMP_RGBA_IMAGE: case GIMP_GRAYA_IMAGE: - project_intensity_alpha (gimage, layer, &src2PR, &src1PR, mask); - break; - - case GIMP_INDEXED_IMAGE: - /* no mask possible */ - project_indexed (gimage, layer, &src2PR, &src1PR); - break; - - case GIMP_INDEXEDA_IMAGE: - project_indexed_alpha (gimage, layer, &src2PR, &src1PR, mask); - break; - - default: - break; - } - } - - gimage->construct_flag = TRUE; /* something was projected */ - } - - g_list_free (reverse_list); -} - -static void -gimp_image_construct_channels (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h) -{ - GimpChannel *channel; - PixelRegion src1PR; - PixelRegion src2PR; - GList *list; - GList *reverse_list = NULL; - - /* reverse the channel list */ - for (list = GIMP_LIST (gimage->channels)->list; - list; - list = g_list_next (list)) - { - reverse_list = g_list_prepend (reverse_list, list->data); - } - - for (list = reverse_list; list; list = g_list_next (list)) - { - channel = (GimpChannel *) list->data; - - if (gimp_item_get_visible (GIMP_ITEM (channel))) - { - /* configure the pixel regions */ - pixel_region_init (&src1PR, - gimp_image_projection (gimage), - x, y, w, h, - TRUE); - pixel_region_init (&src2PR, - gimp_drawable_data (GIMP_DRAWABLE (channel)), - x, y, w, h, - FALSE); - - project_channel (gimage, channel, &src1PR, &src2PR); - - gimage->construct_flag = TRUE; - } - } - - g_list_free (reverse_list); -} - -static void -gimp_image_initialize_projection (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h) -{ - - GList *list; - gint coverage = 0; - PixelRegion PR; - guchar clear[4] = { 0, 0, 0, 0 }; - - /* this function determines whether a visible layer - * provides complete coverage over the image. If not, - * the projection is initialized to transparent - */ - - for (list = GIMP_LIST (gimage->layers)->list; - list; - list = g_list_next (list)) - { - GimpItem *item; - gint off_x, off_y; - - item = (GimpItem *) list->data; - - gimp_item_offsets (item, &off_x, &off_y); - - if (gimp_item_get_visible (GIMP_ITEM (item)) && - ! gimp_drawable_has_alpha (GIMP_DRAWABLE (item)) && - (off_x <= x) && - (off_y <= y) && - (off_x + gimp_item_width (item) >= x + w) && - (off_y + gimp_item_height (item) >= y + h)) - { - coverage = 1; - break; - } - } - - if (!coverage) - { - pixel_region_init (&PR, gimp_image_projection (gimage), - x, y, w, h, TRUE); - color_region (&PR, clear); - } -} - -static void -gimp_image_construct (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h) -{ - g_return_if_fail (GIMP_IS_IMAGE (gimage)); - -#if 0 - gint xoff; - gint yoff; - - /* set the construct flag, used to determine if anything - * has been written to the gimage raw image yet. - */ - gimage->construct_flag = FALSE; - - if (gimage->layers) - { - gimp_item_offsets (GIMP_ITEM (gimage->layers->data), &xoff, &yoff); - } - - if ((gimage->layers) && /* There's a layer. */ - (! g_slist_next (gimage->layers)) && /* It's the only layer. */ - (gimp_drawable_has_alpha (GIMP_DRAWABLE (gimage->layers->data))) && - /* It's !flat. */ - (gimp_item_get_visible (GIMP_ITEM (gimage->layers->data))) && - /* It's visible. */ - (gimp_item_width (GIMP_ITEM (gimage->layers->data)) == - gimage->width) && - (gimp_item_height (GIMP_ITEM (gimage->layers->data)) == - gimage->height) && /* Covers all. */ - (!gimp_drawable_is_indexed (GIMP_DRAWABLE (gimage->layers->data))) && - /* Not indexed. */ - (((GimpLayer *)(gimage->layers->data))->opacity == GIMP_OPACITY_OPAQUE) - /* Opaque */ - ) - { - gint xoff; - gint yoff; - - gimp_item_offsets (GIMP_ITEM (gimage->layers->data), &xoff, &yoff); - - if ((xoff==0) && (yoff==0)) /* Starts at 0,0 */ - { - PixelRegion srcPR, destPR; - gpointer pr; - - g_warning("Can use cow-projection hack. Yay!"); - - pixel_region_init (&srcPR, gimp_drawable_data - (GIMP_DRAWABLE (gimage->layers->data)), - x, y, w,h, FALSE); - pixel_region_init (&destPR, - gimp_image_projection (gimage), - x, y, w,h, TRUE); - - for (pr = pixel_regions_register (2, &srcPR, &destPR); - pr != NULL; - pr = pixel_regions_process (pr)) - { - tile_manager_map_over_tile (destPR.tiles, - destPR.curtile, srcPR.curtile); - } - - gimage->construct_flag = TRUE; - gimp_image_construct_channels (gimage, x, y, w, h); - - return; - } - } -#else - gimage->construct_flag = FALSE; -#endif - - /* First, determine if the projection image needs to be - * initialized--this is the case when there are no visible - * layers that cover the entire canvas--either because layers - * are offset or only a floating selection is visible - */ - gimp_image_initialize_projection (gimage, x, y, w, h); - - /* call functions which process the list of layers and - * the list of channels - */ - gimp_image_construct_layers (gimage, x, y, w, h); - gimp_image_construct_channels (gimage, x, y, w, h); -} - -static void -project_intensity (GimpImage *gimage, - GimpLayer *layer, - PixelRegion *src, - PixelRegion *dest, - PixelRegion *mask) -{ - if (! gimage->construct_flag) - initial_region (src, dest, mask, NULL, - layer->opacity * 255.999, - layer->mode, - gimage->visible, - INITIAL_INTENSITY); - else - combine_regions (dest, src, dest, mask, NULL, - layer->opacity * 255.999, - layer->mode, - gimage->visible, - COMBINE_INTEN_A_INTEN); -} - -static void -project_intensity_alpha (GimpImage *gimage, - GimpLayer *layer, - PixelRegion *src, - PixelRegion *dest, - PixelRegion *mask) -{ - if (! gimage->construct_flag) - initial_region (src, dest, mask, NULL, - layer->opacity * 255.999, - layer->mode, - gimage->visible, - INITIAL_INTENSITY_ALPHA); - else - combine_regions (dest, src, dest, mask, NULL, - layer->opacity * 255.999, - layer->mode, - gimage->visible, - COMBINE_INTEN_A_INTEN_A); -} - -static void -project_indexed (GimpImage *gimage, - GimpLayer *layer, - PixelRegion *src, - PixelRegion *dest) -{ - g_return_if_fail (gimage->cmap != NULL); - - if (! gimage->construct_flag) - initial_region (src, dest, NULL, gimage->cmap, - layer->opacity * 255.999, - layer->mode, - gimage->visible, - INITIAL_INDEXED); - else - g_warning ("%s: unable to project indexed image.", G_STRFUNC); -} - -static void -project_indexed_alpha (GimpImage *gimage, - GimpLayer *layer, - PixelRegion *src, - PixelRegion *dest, - PixelRegion *mask) -{ - g_return_if_fail (gimage->cmap != NULL); - - if (! gimage->construct_flag) - initial_region (src, dest, mask, gimage->cmap, - layer->opacity * 255.999, - layer->mode, - gimage->visible, - INITIAL_INDEXED_ALPHA); - else - combine_regions (dest, src, dest, mask, gimage->cmap, - layer->opacity * 255.999, - layer->mode, - gimage->visible, - COMBINE_INTEN_A_INDEXED_A); -} - -static void -project_channel (GimpImage *gimage, - GimpChannel *channel, - PixelRegion *src, - PixelRegion *src2) -{ - guchar col[3]; - guchar opacity; - gint type; - - gimp_rgba_get_uchar (&channel->color, - &col[0], &col[1], &col[2], &opacity); - - if (! gimage->construct_flag) - { - type = (channel->show_masked) ? - INITIAL_CHANNEL_MASK : INITIAL_CHANNEL_SELECTION; - - initial_region (src2, src, NULL, col, - opacity, - GIMP_NORMAL_MODE, - NULL, - type); - } - else - { - type = (channel->show_masked) ? - COMBINE_INTEN_A_CHANNEL_MASK : COMBINE_INTEN_A_CHANNEL_SELECTION; - - combine_regions (src, src2, src, NULL, col, - opacity, - GIMP_NORMAL_MODE, - NULL, - type); - } -} diff --git a/app/core/gimpimage-projection.h b/app/core/gimpimage-projection.h deleted file mode 100644 index 9ebf84946d..0000000000 --- a/app/core/gimpimage-projection.h +++ /dev/null @@ -1,55 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattisbvf - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __GIMP_IMAGE_PROJECTION_H__ -#define __GIMP_IMAGE_PROJECTION_H__ - - -void gimp_image_projection_allocate (GimpImage *gimage); -void gimp_image_projection_free (GimpImage *gimage); - -TileManager * gimp_image_projection (GimpImage *gimage); -GimpImageType gimp_image_projection_type (const GimpImage *gimage); -gint gimp_image_projection_bytes (const GimpImage *gimage); -gdouble gimp_image_projection_opacity (const GimpImage *gimage); - -guchar * gimp_image_projection_get_color_at (GimpImage *gimage, - gint x, - gint y); - -void gimp_image_invalidate (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h, - gint x1, - gint y1, - gint x2, - gint y2); -void gimp_image_invalidate_without_render (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h, - gint x1, - gint y1, - gint x2, - gint y2); - - -#endif /* __GIMP_IMAGE_PROJECTION_H__ */ diff --git a/app/core/gimpimage-scale.c b/app/core/gimpimage-scale.c index 02a235152d..c48a8b4435 100644 --- a/app/core/gimpimage-scale.c +++ b/app/core/gimpimage-scale.c @@ -228,7 +228,7 @@ gimp_image_scale_check (const GimpImage *gimage, gimp_object_get_memsize (GIMP_OBJECT (gimage->layers), NULL) + gimp_object_get_memsize (GIMP_OBJECT (gimage->channels), NULL) + gimp_object_get_memsize (GIMP_OBJECT (gimage->selection_mask), NULL) + - tile_manager_get_memsize (gimage->projection); + gimp_object_get_memsize (GIMP_OBJECT (gimage->projection), NULL); undo_size = gimp_object_get_memsize (GIMP_OBJECT (gimage->undo_stack), NULL); redo_size = gimp_object_get_memsize (GIMP_OBJECT (gimage->redo_stack), NULL); diff --git a/app/core/gimpimage.c b/app/core/gimpimage.c index 8e6ae58c81..3924bd75a0 100644 --- a/app/core/gimpimage.c +++ b/app/core/gimpimage.c @@ -45,7 +45,6 @@ #include "gimpimage-colormap.h" #include "gimpimage-guides.h" #include "gimpimage-preview.h" -#include "gimpimage-projection.h" #include "gimpimage-qmask.h" #include "gimpimage-undo.h" #include "gimpimage-undo-push.h" @@ -55,6 +54,7 @@ #include "gimplist.h" #include "gimpmarshal.h" #include "gimpparasitelist.h" +#include "gimpprojection.h" #include "gimpselection.h" #include "gimptemplate.h" #include "gimpundostack.h" @@ -116,7 +116,6 @@ static void gimp_image_invalidate_preview (GimpViewable *viewable); static void gimp_image_size_changed (GimpViewable *viewable); static gchar * gimp_image_get_description (GimpViewable *viewable, gchar **tooltip); -static void gimp_image_real_mode_changed (GimpImage *gimage); static void gimp_image_real_colormap_changed (GimpImage *gimage, gint color_index); static void gimp_image_real_flush (GimpImage *gimage); @@ -435,7 +434,7 @@ gimp_image_class_init (GimpImageClass *klass) viewable_class->get_new_preview = gimp_image_get_new_preview; viewable_class->get_description = gimp_image_get_description; - klass->mode_changed = gimp_image_real_mode_changed; + klass->mode_changed = NULL; klass->alpha_changed = NULL; klass->floating_selection_changed = NULL; klass->active_layer_changed = NULL; @@ -486,9 +485,7 @@ gimp_image_init (GimpImage *gimage) gimage->shadow = NULL; - gimage->construct_flag = FALSE; - gimage->proj_type = GIMP_RGBA_IMAGE; - gimage->projection = NULL; + gimage->projection = gimp_projection_new (gimage); gimage->guides = NULL; @@ -631,7 +628,10 @@ gimp_image_finalize (GObject *object) } if (gimage->projection) - gimp_image_projection_free (gimage); + { + g_object_unref (gimage->projection); + gimage->projection = NULL; + } if (gimage->shadow) gimp_image_free_shadow (gimage); @@ -739,7 +739,8 @@ gimp_image_get_memsize (GimpObject *object, memsize += tile_manager_get_memsize (gimage->shadow); if (gimage->projection) - memsize += tile_manager_get_memsize (gimage->projection); + memsize += gimp_object_get_memsize (GIMP_OBJECT (gimage->projection), + gui_size); memsize += gimp_g_list_get_memsize (gimage->guides, sizeof (GimpGuide)); @@ -819,8 +820,6 @@ gimp_image_size_changed (GimpViewable *viewable) } gimp_viewable_size_changed (GIMP_VIEWABLE (gimp_image_get_mask (gimage))); - - gimp_image_projection_allocate (gimage); } static gchar * @@ -846,13 +845,6 @@ gimp_image_get_description (GimpViewable *viewable, return retval; } -static void -gimp_image_real_mode_changed (GimpImage *gimage) -{ - gimp_image_projection_allocate (gimage); - gimp_image_update (gimage, 0, 0, gimage->width, gimage->height); -} - static void gimp_image_real_colormap_changed (GimpImage *gimage, gint color_index) @@ -3368,6 +3360,38 @@ gimp_image_pick_correlate_layer (const GimpImage *gimage, return NULL; } +gboolean +gimp_image_coords_in_active_drawable (GimpImage *gimage, + const GimpCoords *coords) +{ + GimpDrawable *drawable; + + g_return_val_if_fail (GIMP_IS_IMAGE (gimage), FALSE); + + drawable = gimp_image_active_drawable (gimage); + + if (drawable) + { + GimpItem *item = GIMP_ITEM (drawable); + gint x, y; + + gimp_item_offsets (item, &x, &y); + + x = ROUND (coords->x) - x; + y = ROUND (coords->y) - y; + + if (x < 0 || x > gimp_item_width (item)) + return FALSE; + + if (y < 0 || y > gimp_item_height (item)) + return FALSE; + + return TRUE; + } + + return FALSE; +} + void gimp_image_invalidate_layer_previews (GimpImage *gimage) { diff --git a/app/core/gimpimage.h b/app/core/gimpimage.h index fba60e734f..92ef57009b 100644 --- a/app/core/gimpimage.h +++ b/app/core/gimpimage.h @@ -124,12 +124,7 @@ struct _GimpImage TileManager *shadow; /* shadow buffer tiles */ - /* Projection attributes */ - gboolean construct_flag; /* flag for construction */ - GimpImageType proj_type; /* type of the projection image */ - gint proj_bytes; /* bpp in projection image */ - TileManager *projection; /* The projection--layers & */ - /* channels */ + GimpProjection *projection; /* projection layers & channels */ GList *guides; /* guides */ GimpGrid *grid; /* grid */ @@ -493,6 +488,8 @@ gboolean gimp_image_layer_boundary (const GimpImage *gimage, GimpLayer * gimp_image_pick_correlate_layer (const GimpImage *gimage, gint x, gint y); +gboolean gimp_image_coords_in_active_drawable (GimpImage *gimage, + const GimpCoords *coords); void gimp_image_invalidate_layer_previews (GimpImage *gimage); void gimp_image_invalidate_channel_previews (GimpImage *gimage); diff --git a/app/core/gimpmarshal.list b/app/core/gimpmarshal.list index 177a983ac2..78e6ce0cdb 100644 --- a/app/core/gimpmarshal.list +++ b/app/core/gimpmarshal.list @@ -27,6 +27,7 @@ BOOLEAN: ENUM, INT BOOLEAN: OBJECT, POINTER BOOLEAN: OBJECT, POINTER, STRING +VOID: BOOLEAN, INT, INT, INT, INT VOID: BOXED VOID: DOUBLE VOID: DOUBLE, DOUBLE diff --git a/app/core/gimppalette-import.c b/app/core/gimppalette-import.c index e82d549fc7..640304367d 100644 --- a/app/core/gimppalette-import.c +++ b/app/core/gimppalette-import.c @@ -44,8 +44,8 @@ #include "gimpcontainer.h" #include "gimpgradient.h" #include "gimpimage.h" -#include "gimpimage-projection.h" #include "gimppalette.h" +#include "gimpprojection.h" #include "gimp-intl.h" @@ -290,15 +290,15 @@ gimp_palette_import_from_image (GimpImage *gimage, g_return_val_if_fail (threshold > 0, NULL); /* Get the image information */ - d_type = gimp_image_projection_type (gimage); - bytes = gimp_image_projection_bytes (gimage); + d_type = gimp_projection_get_image_type (gimage->projection); + bytes = gimp_projection_get_bytes (gimage->projection); has_alpha = GIMP_IMAGE_TYPE_HAS_ALPHA (d_type); indexed = GIMP_IMAGE_TYPE_IS_INDEXED (d_type); width = gimage->width; height = gimage->height; - pixel_region_init (&imagePR, gimp_image_projection (gimage), 0, 0, - width, height, FALSE); + pixel_region_init (&imagePR, gimp_projection_get_tiles (gimage->projection), + 0, 0, width, height, FALSE); alpha = bytes - 1; diff --git a/app/core/gimpprojection-construct.c b/app/core/gimpprojection-construct.c index c229177d10..b0d7146b53 100644 --- a/app/core/gimpprojection-construct.c +++ b/app/core/gimpprojection-construct.c @@ -26,567 +26,71 @@ #include "base/pixel-region.h" #include "base/tile-manager.h" -#include "base/tile.h" #include "paint-funcs/paint-funcs.h" -#include "gimp.h" #include "gimpimage.h" -#include "gimpimage-projection.h" #include "gimplayer.h" #include "gimplayer-floating-sel.h" #include "gimplayermask.h" #include "gimplist.h" +#include "gimpprojection.h" +#include "gimpprojection-construct.h" /* local function prototypes */ -static void gimp_image_projection_validate_tile (TileManager *tm, - Tile *tile); -static void gimp_image_construct_layers (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h); -static void gimp_image_construct_channels (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h); -static void gimp_image_initialize_projection (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h); -static void gimp_image_construct (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h); +static void gimp_projection_construct_layers (GimpProjection *proj, + gint x, + gint y, + gint w, + gint h); +static void gimp_projection_construct_channels (GimpProjection *proj, + gint x, + gint y, + gint w, + gint h); +static void gimp_projection_initialize (GimpProjection *proj, + gint x, + gint y, + gint w, + gint h); -static void project_intensity (GimpImage *gimage, - GimpLayer *layer, - PixelRegion *src, - PixelRegion *dest, - PixelRegion *mask); -static void project_intensity_alpha (GimpImage *gimage, - GimpLayer *layer, - PixelRegion *src, - PixelRegion *dest, - PixelRegion *mask); -static void project_indexed (GimpImage *gimage, - GimpLayer *layer, - PixelRegion *src, - PixelRegion *dest); -static void project_indexed_alpha (GimpImage *gimage, - GimpLayer *layer, - PixelRegion *src, - PixelRegion *dest, - PixelRegion *mask); -static void project_channel (GimpImage *gimage, - GimpChannel *channel, - PixelRegion *src, - PixelRegion *src2); +static void project_intensity (GimpProjection *proj, + GimpLayer *layer, + PixelRegion *src, + PixelRegion *dest, + PixelRegion *mask); +static void project_intensity_alpha (GimpProjection *proj, + GimpLayer *layer, + PixelRegion *src, + PixelRegion *dest, + PixelRegion *mask); +static void project_indexed (GimpProjection *proj, + GimpLayer *layer, + PixelRegion *src, + PixelRegion *dest); +static void project_indexed_alpha (GimpProjection *proj, + GimpLayer *layer, + PixelRegion *src, + PixelRegion *dest, + PixelRegion *mask); +static void project_channel (GimpProjection *proj, + GimpChannel *channel, + PixelRegion *src, + PixelRegion *src2); /* public functions */ void -gimp_image_projection_allocate (GimpImage *gimage) +gimp_projection_construct (GimpProjection *proj, + gint x, + gint y, + gint w, + gint h) { - GimpImageType proj_type = 0; - gint proj_bytes = 0; - - g_return_if_fail (GIMP_IS_IMAGE (gimage)); - - /* Find the number of bytes required for the projection. - * This includes the intensity channels and an alpha channel - * if one doesn't exist. - */ - switch (gimp_image_base_type (gimage)) - { - case GIMP_RGB: - case GIMP_INDEXED: - proj_bytes = 4; - proj_type = GIMP_RGBA_IMAGE; - break; - - case GIMP_GRAY: - proj_bytes = 2; - proj_type = GIMP_GRAYA_IMAGE; - break; - - default: - g_assert_not_reached (); - } - - if (gimage->projection) - { - if (proj_type != gimage->proj_type || - proj_bytes != gimage->proj_bytes || - gimage->width != tile_manager_width (gimage->projection) || - gimage->height != tile_manager_height (gimage->projection)) - { - gimp_image_projection_free (gimage); - } - } - - if (! gimage->projection) - { - gimage->proj_type = proj_type; - gimage->proj_bytes = proj_bytes; - - gimage->projection = tile_manager_new (gimage->width, gimage->height, - gimage->proj_bytes); - tile_manager_set_user_data (gimage->projection, gimage); - tile_manager_set_validate_proc (gimage->projection, - gimp_image_projection_validate_tile); - } -} - -void -gimp_image_projection_free (GimpImage *gimage) -{ - g_return_if_fail (GIMP_IS_IMAGE (gimage)); - - if (gimage->projection) - { - tile_manager_unref (gimage->projection); - gimage->projection = NULL; - } -} - -TileManager * -gimp_image_projection (GimpImage *gimage) -{ - g_return_val_if_fail (GIMP_IS_IMAGE (gimage), NULL); - - if (gimage->projection == NULL || - tile_manager_width (gimage->projection) != gimage->width || - tile_manager_height (gimage->projection) != gimage->height) - { - gimp_image_projection_allocate (gimage); - } - - return gimage->projection; -} - -GimpImageType -gimp_image_projection_type (const GimpImage *gimage) -{ - g_return_val_if_fail (GIMP_IS_IMAGE (gimage), -1); - - return gimage->proj_type; -} - -gint -gimp_image_projection_bytes (const GimpImage *gimage) -{ - g_return_val_if_fail (GIMP_IS_IMAGE (gimage), -1); - - return gimage->proj_bytes; -} - -gdouble -gimp_image_projection_opacity (const GimpImage *gimage) -{ - g_return_val_if_fail (GIMP_IS_IMAGE (gimage), GIMP_OPACITY_OPAQUE); - - return GIMP_OPACITY_OPAQUE; -} - -guchar * -gimp_image_projection_get_color_at (GimpImage *gimage, - gint x, - gint y) -{ - Tile *tile; - guchar *src; - guchar *dest; - - g_return_val_if_fail (GIMP_IS_IMAGE (gimage), NULL); - - if (x < 0 || y < 0 || x >= gimage->width || y >= gimage->height) - return NULL; - - dest = g_new (guchar, 5); - tile = tile_manager_get_tile (gimp_image_projection (gimage), x, y, - TRUE, FALSE); - src = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT); - gimp_image_get_color (gimage, gimp_image_projection_type (gimage), src, dest); - - dest[4] = 0; - tile_release (tile, FALSE); - - return dest; -} - -void -gimp_image_invalidate (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h, - gint x1, - gint y1, - gint x2, - gint y2) -{ - Tile *tile; - TileManager *tm; - gint i, j; - gint startx, starty; - gint endx, endy; - gint tilex, tiley; - - g_return_if_fail (GIMP_IS_IMAGE (gimage)); - - tm = gimp_image_projection (gimage); - - startx = x; - starty = y; - endx = x + w; - endy = y + h; - - /* invalidate all tiles which are located outside of the displayed area - * all tiles inside the displayed area are constructed. - */ - for (i = y; i < (y + h); i += (TILE_HEIGHT - (i % TILE_HEIGHT))) - for (j = x; j < (x + w); j += (TILE_WIDTH - (j % TILE_WIDTH))) - { - tile = tile_manager_get_tile (tm, j, i, FALSE, FALSE); - - /* check if the tile is outside the bounds */ - if ((MIN ((j + tile_ewidth (tile)), x2) - MAX (j, x1)) <= 0) - { - tile_invalidate_tile (&tile, tm, j, i); - - if (j < x1) - startx = MAX (startx, - (j - (j % TILE_WIDTH) + tile_ewidth (tile))); - else - endx = MIN (endx, j); - } - else if (MIN ((i + tile_eheight (tile)), y2) - MAX (i, y1) <= 0) - { - tile_invalidate_tile (&tile, tm, j, i); - - if (i < y1) - starty = MAX (starty, - (i - (i % TILE_HEIGHT) + tile_eheight (tile))); - else - endy = MIN (endy, i); - } - else - { - /* If the tile is not valid, make sure we get the entire tile - * in the construction extents - */ - if (! tile_is_valid (tile)) - { - tilex = j - (j % TILE_WIDTH); - tiley = i - (i % TILE_HEIGHT); - - startx = MIN (startx, tilex); - endx = MAX (endx, tilex + tile_ewidth (tile)); - starty = MIN (starty, tiley); - endy = MAX (endy, tiley + tile_eheight (tile)); - - tile_mark_valid (tile); /* hmmmmmmm..... */ - } - } - } - - if ((endx - startx) > 0 && (endy - starty) > 0) - gimp_image_construct (gimage, - startx, starty, - (endx - startx), (endy - starty)); -} - -void -gimp_image_invalidate_without_render (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h, - gint x1, - gint y1, - gint x2, - gint y2) -{ - Tile *tile; - TileManager *tm; - gint i, j; - - g_return_if_fail (GIMP_IS_IMAGE (gimage)); - - tm = gimp_image_projection (gimage); - - /* invalidate all tiles which are located outside of the displayed area - * all tiles inside the displayed area are constructed. - */ - for (i = y; i < (y + h); i += (TILE_HEIGHT - (i % TILE_HEIGHT))) - for (j = x; j < (x + w); j += (TILE_WIDTH - (j % TILE_WIDTH))) - { - tile = tile_manager_get_tile (tm, j, i, FALSE, FALSE); - - /* check if the tile is outside the bounds */ - if ((MIN ((j + tile_ewidth(tile)), x2) - MAX (j, x1)) <= 0) - { - tile_invalidate_tile (&tile, tm, j, i); - } - else if (MIN ((i + tile_eheight(tile)), y2) - MAX (i, y1) <= 0) - { - tile_invalidate_tile (&tile, tm, j, i); - } - } -} - - -/* private functions */ - -static void -gimp_image_projection_validate_tile (TileManager *tm, - Tile *tile) -{ - GimpImage *gimage; - gint x, y; - gint w, h; - - /* Get the gimage from the tilemanager */ - gimage = (GimpImage *) tile_manager_get_user_data (tm); - - gimp_set_busy_until_idle (gimage->gimp); - - /* Find the coordinates of this tile */ - tile_manager_get_tile_coordinates (tm, tile, &x, &y); - w = tile_ewidth (tile); - h = tile_eheight (tile); - - gimp_image_construct (gimage, x, y, w, h); -} - -static void -gimp_image_construct_layers (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h) -{ - GimpLayer *layer; - gint x1, y1, x2, y2; - PixelRegion src1PR, src2PR, maskPR; - PixelRegion * mask; - GList *list; - GList *reverse_list; - gint off_x; - gint off_y; - - /* composite the floating selection if it exists */ - if ((layer = gimp_image_floating_sel (gimage))) - floating_sel_composite (layer, x, y, w, h, FALSE); - - - reverse_list = NULL; - - for (list = GIMP_LIST (gimage->layers)->list; - list; - list = g_list_next (list)) - { - layer = (GimpLayer *) list->data; - - /* only add layers that are visible and not floating selections - * to the list - */ - if (! gimp_layer_is_floating_sel (layer) && - gimp_item_get_visible (GIMP_ITEM (layer))) - { - reverse_list = g_list_prepend (reverse_list, layer); - } - } - - for (list = reverse_list; list; list = g_list_next (list)) - { - layer = (GimpLayer *) list->data; - - gimp_item_offsets (GIMP_ITEM (layer), &off_x, &off_y); - - x1 = CLAMP (off_x, x, x + w); - y1 = CLAMP (off_y, y, y + h); - x2 = CLAMP (off_x + gimp_item_width (GIMP_ITEM (layer)), x, x + w); - y2 = CLAMP (off_y + gimp_item_height (GIMP_ITEM (layer)), y, y + h); - - /* configure the pixel regions */ - pixel_region_init (&src1PR, gimp_image_projection (gimage), - x1, y1, (x2 - x1), (y2 - y1), - TRUE); - - /* If we're showing the layer mask instead of the layer... */ - if (layer->mask && layer->mask->show_mask) - { - pixel_region_init (&src2PR, - gimp_drawable_data (GIMP_DRAWABLE (layer->mask)), - (x1 - off_x), (y1 - off_y), - (x2 - x1), (y2 - y1), FALSE); - - copy_gray_to_region (&src2PR, &src1PR); - } - /* Otherwise, normal */ - else - { - pixel_region_init (&src2PR, - gimp_drawable_data (GIMP_DRAWABLE (layer)), - (x1 - off_x), (y1 - off_y), - (x2 - x1), (y2 - y1), FALSE); - - if (layer->mask && layer->mask->apply_mask) - { - pixel_region_init (&maskPR, - gimp_drawable_data (GIMP_DRAWABLE (layer->mask)), - (x1 - off_x), (y1 - off_y), - (x2 - x1), (y2 - y1), FALSE); - mask = &maskPR; - } - else - mask = NULL; - - /* Based on the type of the layer, project the layer onto the - * projection image... - */ - switch (gimp_drawable_type (GIMP_DRAWABLE (layer))) - { - case GIMP_RGB_IMAGE: case GIMP_GRAY_IMAGE: - /* no mask possible */ - project_intensity (gimage, layer, &src2PR, &src1PR, mask); - break; - - case GIMP_RGBA_IMAGE: case GIMP_GRAYA_IMAGE: - project_intensity_alpha (gimage, layer, &src2PR, &src1PR, mask); - break; - - case GIMP_INDEXED_IMAGE: - /* no mask possible */ - project_indexed (gimage, layer, &src2PR, &src1PR); - break; - - case GIMP_INDEXEDA_IMAGE: - project_indexed_alpha (gimage, layer, &src2PR, &src1PR, mask); - break; - - default: - break; - } - } - - gimage->construct_flag = TRUE; /* something was projected */ - } - - g_list_free (reverse_list); -} - -static void -gimp_image_construct_channels (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h) -{ - GimpChannel *channel; - PixelRegion src1PR; - PixelRegion src2PR; - GList *list; - GList *reverse_list = NULL; - - /* reverse the channel list */ - for (list = GIMP_LIST (gimage->channels)->list; - list; - list = g_list_next (list)) - { - reverse_list = g_list_prepend (reverse_list, list->data); - } - - for (list = reverse_list; list; list = g_list_next (list)) - { - channel = (GimpChannel *) list->data; - - if (gimp_item_get_visible (GIMP_ITEM (channel))) - { - /* configure the pixel regions */ - pixel_region_init (&src1PR, - gimp_image_projection (gimage), - x, y, w, h, - TRUE); - pixel_region_init (&src2PR, - gimp_drawable_data (GIMP_DRAWABLE (channel)), - x, y, w, h, - FALSE); - - project_channel (gimage, channel, &src1PR, &src2PR); - - gimage->construct_flag = TRUE; - } - } - - g_list_free (reverse_list); -} - -static void -gimp_image_initialize_projection (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h) -{ - - GList *list; - gint coverage = 0; - PixelRegion PR; - guchar clear[4] = { 0, 0, 0, 0 }; - - /* this function determines whether a visible layer - * provides complete coverage over the image. If not, - * the projection is initialized to transparent - */ - - for (list = GIMP_LIST (gimage->layers)->list; - list; - list = g_list_next (list)) - { - GimpItem *item; - gint off_x, off_y; - - item = (GimpItem *) list->data; - - gimp_item_offsets (item, &off_x, &off_y); - - if (gimp_item_get_visible (GIMP_ITEM (item)) && - ! gimp_drawable_has_alpha (GIMP_DRAWABLE (item)) && - (off_x <= x) && - (off_y <= y) && - (off_x + gimp_item_width (item) >= x + w) && - (off_y + gimp_item_height (item) >= y + h)) - { - coverage = 1; - break; - } - } - - if (!coverage) - { - pixel_region_init (&PR, gimp_image_projection (gimage), - x, y, w, h, TRUE); - color_region (&PR, clear); - } -} - -static void -gimp_image_construct (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h) -{ - g_return_if_fail (GIMP_IS_IMAGE (gimage)); + g_return_if_fail (GIMP_IS_PROJECTION (proj)); #if 0 gint xoff; @@ -652,7 +156,7 @@ gimp_image_construct (GimpImage *gimage, } } #else - gimage->construct_flag = FALSE; + proj->construct_flag = FALSE; #endif /* First, determine if the projection image needs to be @@ -660,103 +164,317 @@ gimp_image_construct (GimpImage *gimage, * layers that cover the entire canvas--either because layers * are offset or only a floating selection is visible */ - gimp_image_initialize_projection (gimage, x, y, w, h); + gimp_projection_initialize (proj, x, y, w, h); /* call functions which process the list of layers and * the list of channels */ - gimp_image_construct_layers (gimage, x, y, w, h); - gimp_image_construct_channels (gimage, x, y, w, h); + gimp_projection_construct_layers (proj, x, y, w, h); + gimp_projection_construct_channels (proj, x, y, w, h); +} + + +/* private functions */ + +static void +gimp_projection_construct_layers (GimpProjection *proj, + gint x, + gint y, + gint w, + gint h) +{ + GimpLayer *layer; + gint x1, y1, x2, y2; + PixelRegion src1PR, src2PR, maskPR; + PixelRegion * mask; + GList *list; + GList *reverse_list; + gint off_x; + gint off_y; + + /* composite the floating selection if it exists */ + if ((layer = gimp_image_floating_sel (proj->gimage))) + floating_sel_composite (layer, x, y, w, h, FALSE); + + reverse_list = NULL; + + for (list = GIMP_LIST (proj->gimage->layers)->list; + list; + list = g_list_next (list)) + { + layer = (GimpLayer *) list->data; + + /* only add layers that are visible and not floating selections + * to the list + */ + if (! gimp_layer_is_floating_sel (layer) && + gimp_item_get_visible (GIMP_ITEM (layer))) + { + reverse_list = g_list_prepend (reverse_list, layer); + } + } + + for (list = reverse_list; list; list = g_list_next (list)) + { + layer = (GimpLayer *) list->data; + + gimp_item_offsets (GIMP_ITEM (layer), &off_x, &off_y); + + x1 = CLAMP (off_x, x, x + w); + y1 = CLAMP (off_y, y, y + h); + x2 = CLAMP (off_x + gimp_item_width (GIMP_ITEM (layer)), x, x + w); + y2 = CLAMP (off_y + gimp_item_height (GIMP_ITEM (layer)), y, y + h); + + /* configure the pixel regions */ + pixel_region_init (&src1PR, gimp_projection_get_tiles (proj), + x1, y1, (x2 - x1), (y2 - y1), + TRUE); + + /* If we're showing the layer mask instead of the layer... */ + if (layer->mask && layer->mask->show_mask) + { + pixel_region_init (&src2PR, + gimp_drawable_data (GIMP_DRAWABLE (layer->mask)), + (x1 - off_x), (y1 - off_y), + (x2 - x1), (y2 - y1), FALSE); + + copy_gray_to_region (&src2PR, &src1PR); + } + /* Otherwise, normal */ + else + { + pixel_region_init (&src2PR, + gimp_drawable_data (GIMP_DRAWABLE (layer)), + (x1 - off_x), (y1 - off_y), + (x2 - x1), (y2 - y1), FALSE); + + if (layer->mask && layer->mask->apply_mask) + { + pixel_region_init (&maskPR, + gimp_drawable_data (GIMP_DRAWABLE (layer->mask)), + (x1 - off_x), (y1 - off_y), + (x2 - x1), (y2 - y1), FALSE); + mask = &maskPR; + } + else + mask = NULL; + + /* Based on the type of the layer, project the layer onto the + * projection image... + */ + switch (gimp_drawable_type (GIMP_DRAWABLE (layer))) + { + case GIMP_RGB_IMAGE: case GIMP_GRAY_IMAGE: + /* no mask possible */ + project_intensity (proj, layer, &src2PR, &src1PR, mask); + break; + + case GIMP_RGBA_IMAGE: case GIMP_GRAYA_IMAGE: + project_intensity_alpha (proj, layer, &src2PR, &src1PR, mask); + break; + + case GIMP_INDEXED_IMAGE: + /* no mask possible */ + project_indexed (proj, layer, &src2PR, &src1PR); + break; + + case GIMP_INDEXEDA_IMAGE: + project_indexed_alpha (proj, layer, &src2PR, &src1PR, mask); + break; + + default: + break; + } + } + + proj->construct_flag = TRUE; /* something was projected */ + } + + g_list_free (reverse_list); } static void -project_intensity (GimpImage *gimage, - GimpLayer *layer, - PixelRegion *src, - PixelRegion *dest, - PixelRegion *mask) +gimp_projection_construct_channels (GimpProjection *proj, + gint x, + gint y, + gint w, + gint h) { - if (! gimage->construct_flag) + GimpChannel *channel; + PixelRegion src1PR; + PixelRegion src2PR; + GList *list; + GList *reverse_list = NULL; + + /* reverse the channel list */ + for (list = GIMP_LIST (proj->gimage->channels)->list; + list; + list = g_list_next (list)) + { + reverse_list = g_list_prepend (reverse_list, list->data); + } + + for (list = reverse_list; list; list = g_list_next (list)) + { + channel = (GimpChannel *) list->data; + + if (gimp_item_get_visible (GIMP_ITEM (channel))) + { + /* configure the pixel regions */ + pixel_region_init (&src1PR, + gimp_projection_get_tiles (proj), + x, y, w, h, + TRUE); + pixel_region_init (&src2PR, + gimp_drawable_data (GIMP_DRAWABLE (channel)), + x, y, w, h, + FALSE); + + project_channel (proj, channel, &src1PR, &src2PR); + + proj->construct_flag = TRUE; + } + } + + g_list_free (reverse_list); +} + +static void +gimp_projection_initialize (GimpProjection *proj, + gint x, + gint y, + gint w, + gint h) +{ + + GList *list; + gboolean coverage = FALSE; + + /* this function determines whether a visible layer + * provides complete coverage over the image. If not, + * the projection is initialized to transparent + */ + + for (list = GIMP_LIST (proj->gimage->layers)->list; + list; + list = g_list_next (list)) + { + GimpItem *item = list->data; + gint off_x, off_y; + + gimp_item_offsets (item, &off_x, &off_y); + + if (gimp_item_get_visible (item) && + ! gimp_drawable_has_alpha (GIMP_DRAWABLE (item)) && + (off_x <= x) && + (off_y <= y) && + (off_x + gimp_item_width (item) >= x + w) && + (off_y + gimp_item_height (item) >= y + h)) + { + coverage = TRUE; + break; + } + } + + if (!coverage) + { + PixelRegion PR; + guchar clear[4] = { 0, 0, 0, 0 }; + + pixel_region_init (&PR, gimp_projection_get_tiles (proj), + x, y, w, h, TRUE); + color_region (&PR, clear); + } +} + +static void +project_intensity (GimpProjection *proj, + GimpLayer *layer, + PixelRegion *src, + PixelRegion *dest, + PixelRegion *mask) +{ + if (! proj->construct_flag) initial_region (src, dest, mask, NULL, layer->opacity * 255.999, layer->mode, - gimage->visible, + proj->gimage->visible, INITIAL_INTENSITY); else combine_regions (dest, src, dest, mask, NULL, layer->opacity * 255.999, layer->mode, - gimage->visible, + proj->gimage->visible, COMBINE_INTEN_A_INTEN); } static void -project_intensity_alpha (GimpImage *gimage, - GimpLayer *layer, - PixelRegion *src, - PixelRegion *dest, - PixelRegion *mask) +project_intensity_alpha (GimpProjection *proj, + GimpLayer *layer, + PixelRegion *src, + PixelRegion *dest, + PixelRegion *mask) { - if (! gimage->construct_flag) + if (! proj->construct_flag) initial_region (src, dest, mask, NULL, layer->opacity * 255.999, layer->mode, - gimage->visible, + proj->gimage->visible, INITIAL_INTENSITY_ALPHA); else combine_regions (dest, src, dest, mask, NULL, layer->opacity * 255.999, layer->mode, - gimage->visible, + proj->gimage->visible, COMBINE_INTEN_A_INTEN_A); } static void -project_indexed (GimpImage *gimage, - GimpLayer *layer, - PixelRegion *src, - PixelRegion *dest) +project_indexed (GimpProjection *proj, + GimpLayer *layer, + PixelRegion *src, + PixelRegion *dest) { - g_return_if_fail (gimage->cmap != NULL); + g_return_if_fail (proj->gimage->cmap != NULL); - if (! gimage->construct_flag) - initial_region (src, dest, NULL, gimage->cmap, + if (! proj->construct_flag) + initial_region (src, dest, NULL, proj->gimage->cmap, layer->opacity * 255.999, layer->mode, - gimage->visible, + proj->gimage->visible, INITIAL_INDEXED); else g_warning ("%s: unable to project indexed image.", G_STRFUNC); } static void -project_indexed_alpha (GimpImage *gimage, - GimpLayer *layer, - PixelRegion *src, - PixelRegion *dest, - PixelRegion *mask) +project_indexed_alpha (GimpProjection *proj, + GimpLayer *layer, + PixelRegion *src, + PixelRegion *dest, + PixelRegion *mask) { - g_return_if_fail (gimage->cmap != NULL); + g_return_if_fail (proj->gimage->cmap != NULL); - if (! gimage->construct_flag) - initial_region (src, dest, mask, gimage->cmap, + if (! proj->construct_flag) + initial_region (src, dest, mask, proj->gimage->cmap, layer->opacity * 255.999, layer->mode, - gimage->visible, + proj->gimage->visible, INITIAL_INDEXED_ALPHA); else - combine_regions (dest, src, dest, mask, gimage->cmap, + combine_regions (dest, src, dest, mask, proj->gimage->cmap, layer->opacity * 255.999, layer->mode, - gimage->visible, + proj->gimage->visible, COMBINE_INTEN_A_INDEXED_A); } static void -project_channel (GimpImage *gimage, - GimpChannel *channel, - PixelRegion *src, - PixelRegion *src2) +project_channel (GimpProjection *proj, + GimpChannel *channel, + PixelRegion *src, + PixelRegion *src2) { guchar col[3]; guchar opacity; @@ -765,7 +483,7 @@ project_channel (GimpImage *gimage, gimp_rgba_get_uchar (&channel->color, &col[0], &col[1], &col[2], &opacity); - if (! gimage->construct_flag) + if (! proj->construct_flag) { type = (channel->show_masked) ? INITIAL_CHANNEL_MASK : INITIAL_CHANNEL_SELECTION; diff --git a/app/core/gimpprojection-construct.h b/app/core/gimpprojection-construct.h index 9ebf84946d..aaf313851e 100644 --- a/app/core/gimpprojection-construct.h +++ b/app/core/gimpprojection-construct.h @@ -16,40 +16,15 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#ifndef __GIMP_IMAGE_PROJECTION_H__ -#define __GIMP_IMAGE_PROJECTION_H__ +#ifndef __GIMP_PROJECTION_CONSTRUCT_H__ +#define __GIMP_PROJECTION_CONSTRUCT_H__ -void gimp_image_projection_allocate (GimpImage *gimage); -void gimp_image_projection_free (GimpImage *gimage); - -TileManager * gimp_image_projection (GimpImage *gimage); -GimpImageType gimp_image_projection_type (const GimpImage *gimage); -gint gimp_image_projection_bytes (const GimpImage *gimage); -gdouble gimp_image_projection_opacity (const GimpImage *gimage); - -guchar * gimp_image_projection_get_color_at (GimpImage *gimage, - gint x, - gint y); - -void gimp_image_invalidate (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h, - gint x1, - gint y1, - gint x2, - gint y2); -void gimp_image_invalidate_without_render (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h, - gint x1, - gint y1, - gint x2, - gint y2); +void gimp_projection_construct (GimpProjection *proj, + gint x, + gint y, + gint w, + gint h); -#endif /* __GIMP_IMAGE_PROJECTION_H__ */ +#endif /* __GIMP_PROJECTION_CONSTRUCT_H__ */ diff --git a/app/core/gimpprojection.c b/app/core/gimpprojection.c index 55ea956082..6dae7cb6a5 100644 --- a/app/core/gimpprojection.c +++ b/app/core/gimpprojection.c @@ -18,601 +18,531 @@ #include "config.h" -#include +#include -#include "display-types.h" -#include "tools/tools-types.h" +#include "core-types.h" -#include "core/gimp.h" -#include "core/gimpcontainer.h" -#include "core/gimpcontext.h" -#include "core/gimpdrawable.h" -#include "core/gimpimage.h" -#include "core/gimpimage-projection.h" -#include "core/gimplist.h" +#include "base/tile.h" +#include "base/tile-manager.h" -#include "widgets/gimpuimanager.h" - -#include "tools/gimptool.h" -#include "tools/tool_manager.h" - -#include "gimpdisplay.h" -#include "gimpdisplay-area.h" -#include "gimpdisplay-handlers.h" -#include "gimpdisplayshell.h" -#include "gimpdisplayshell-handlers.h" -#include "gimpdisplayshell-transform.h" - -#include "gimp-intl.h" +#include "gimp.h" +#include "gimparea.h" +#include "gimpimage.h" +#include "gimpmarshal.h" +#include "gimpprojection.h" +#include "gimpprojection-construct.h" enum { - PROP_0, - PROP_ID, - PROP_IMAGE + UPDATE, + LAST_SIGNAL }; /* local function prototypes */ -static void gimp_display_class_init (GimpDisplayClass *klass); -static void gimp_display_init (GimpDisplay *gdisp); +static void gimp_projection_class_init (GimpProjectionClass *klass); +static void gimp_projection_init (GimpProjection *proj); -static void gimp_display_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec); -static void gimp_display_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec); +static void gimp_projection_finalize (GObject *object); -static void gimp_display_flush_whenever (GimpDisplay *gdisp, - gboolean now); -static void gimp_display_idlerender_init (GimpDisplay *gdisp); -static gboolean gimp_display_idlerender_callback (gpointer data); -static gboolean gimp_display_idle_render_next_area (GimpDisplay *gdisp); -static void gimp_display_paint_area (GimpDisplay *gdisp, - gint x, - gint y, - gint w, - gint h); +static gint64 gimp_projection_get_memsize (GimpObject *object, + gint64 *gui_size); +static void gimp_projection_alloc_tiles (GimpProjection *proj); +static void gimp_projection_flush_whenever (GimpProjection *proj, + gboolean now); +static void gimp_projection_idlerender_init (GimpProjection *proj); +static gboolean gimp_projection_idlerender_callback (gpointer data); +static gboolean gimp_projection_idle_render_next_area (GimpProjection *proj); +static void gimp_projection_paint_area (GimpProjection *proj, + gboolean now, + gint x, + gint y, + gint w, + gint h); +static void gimp_projection_invalidate (GimpProjection *proj, + gint x, + gint y, + gint w, + gint h); +static void gimp_projection_validate_tile (TileManager *tm, + Tile *tile); + +static void gimp_projection_image_update (GimpImage *gimage, + gint x, + gint y, + gint w, + gint h, + GimpProjection *proj); +static void gimp_projection_image_size_changed (GimpImage *gimage, + GimpProjection *proj); +static void gimp_projection_image_mode_changed (GimpImage *gimage, + GimpProjection *proj); +static void gimp_projection_image_flush (GimpImage *gimage, + GimpProjection *proj); + + +static guint projection_signals[LAST_SIGNAL] = { 0 }; static GimpObjectClass *parent_class = NULL; GType -gimp_display_get_type (void) +gimp_projection_get_type (void) { - static GType display_type = 0; + static GType projection_type = 0; - if (! display_type) + if (! projection_type) { - static const GTypeInfo display_info = + static const GTypeInfo projection_info = { - sizeof (GimpDisplayClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) gimp_display_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GimpDisplay), - 0, /* n_preallocs */ - (GInstanceInitFunc) gimp_display_init, + sizeof (GimpProjectionClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gimp_projection_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GimpProjection), + 0, /* n_preallocs */ + (GInstanceInitFunc) gimp_projection_init, }; - display_type = g_type_register_static (GIMP_TYPE_OBJECT, - "GimpDisplay", - &display_info, 0); + projection_type = g_type_register_static (GIMP_TYPE_OBJECT, + "GimpProjection", + &projection_info, 0); } - return display_type; + return projection_type; } static void -gimp_display_class_init (GimpDisplayClass *klass) +gimp_projection_class_init (GimpProjectionClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass); parent_class = g_type_class_peek_parent (klass); - object_class->set_property = gimp_display_set_property; - object_class->get_property = gimp_display_get_property; + projection_signals[UPDATE] = + g_signal_new ("update", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GimpProjectionClass, update), + NULL, NULL, + gimp_marshal_VOID__BOOLEAN_INT_INT_INT_INT, + G_TYPE_NONE, 5, + G_TYPE_BOOLEAN, + G_TYPE_INT, + G_TYPE_INT, + G_TYPE_INT, + G_TYPE_INT); - g_object_class_install_property (object_class, PROP_ID, - g_param_spec_int ("id", - NULL, NULL, - 0, G_MAXINT, 0, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY)); + object_class->finalize = gimp_projection_finalize; - g_object_class_install_property (object_class, PROP_IMAGE, - g_param_spec_object ("image", - NULL, NULL, - GIMP_TYPE_IMAGE, - G_PARAM_READABLE)); + gimp_object_class->get_memsize = gimp_projection_get_memsize; } static void -gimp_display_init (GimpDisplay *gdisp) +gimp_projection_init (GimpProjection *proj) { - gdisp->ID = 0; + proj->gimage = NULL; - gdisp->gimage = NULL; - gdisp->instance = 0; + proj->type = -1; + proj->bytes = 0; + proj->tiles = NULL; - gdisp->shell = NULL; + proj->update_areas = NULL; - gdisp->update_areas = NULL; + proj->idle_render.idle_id = 0; + proj->idle_render.update_areas = NULL; - gdisp->idle_render.idle_id = 0; - gdisp->idle_render.update_areas = NULL; + proj->construct_flag = FALSE; } static void -gimp_display_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) +gimp_projection_finalize (GObject *object) { - GimpDisplay *gdisp = GIMP_DISPLAY (object); + GimpProjection *proj = GIMP_PROJECTION (object); - switch (property_id) + if (proj->idle_render.idle_id) { - case PROP_ID: - gdisp->ID = g_value_get_int (value); - break; - case PROP_IMAGE: - g_assert_not_reached (); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; + g_source_remove (proj->idle_render.idle_id); + proj->idle_render.idle_id = 0; } -} -static void -gimp_display_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - GimpDisplay *gdisp = GIMP_DISPLAY (object); + gimp_area_list_free (proj->update_areas); + gimp_area_list_free (proj->idle_render.update_areas); - switch (property_id) + if (proj->tiles) { - case PROP_ID: - g_value_set_int (value, gdisp->ID); - break; - case PROP_IMAGE: - g_value_set_object (value, gdisp->gimage); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; + tile_manager_unref (proj->tiles); + proj->tiles = NULL; } + + G_OBJECT_CLASS (parent_class)->finalize (object); } -GimpDisplay * -gimp_display_new (GimpImage *gimage, - GimpUnit unit, - gdouble scale, - GimpMenuFactory *menu_factory, - GimpUIManager *popup_manager) +static gint64 +gimp_projection_get_memsize (GimpObject *object, + gint64 *gui_size) { - GimpDisplay *gdisp; + GimpProjection *projection = GIMP_PROJECTION (object); + gint64 memsize = 0; + + if (projection->tiles) + memsize += tile_manager_get_memsize (projection->tiles); + + return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object, + gui_size); +} + +GimpProjection * +gimp_projection_new (GimpImage *gimage) +{ + GimpProjection *proj; g_return_val_if_fail (GIMP_IS_IMAGE (gimage), NULL); - /* If there isn't an interface, never create a gdisplay */ - if (gimage->gimp->no_interface) - return NULL; + proj = g_object_new (GIMP_TYPE_PROJECTION, NULL); - gdisp = g_object_new (GIMP_TYPE_DISPLAY, - "id", gimage->gimp->next_display_ID++, - NULL); + proj->gimage = gimage; - /* refs the image */ - gimp_display_connect (gdisp, gimage); + g_signal_connect_object (gimage, "update", + G_CALLBACK (gimp_projection_image_update), + proj, 0); + g_signal_connect_object (gimage, "size_changed", + G_CALLBACK (gimp_projection_image_size_changed), + proj, 0); + g_signal_connect_object (gimage, "mode_changed", + G_CALLBACK (gimp_projection_image_mode_changed), + proj, 0); + g_signal_connect_object (gimage, "flush", + G_CALLBACK (gimp_projection_image_flush), + proj, 0); - /* create the shell for the image */ - gdisp->shell = gimp_display_shell_new (gdisp, unit, scale, - menu_factory, popup_manager); - - gtk_widget_show (gdisp->shell); - - return gdisp; + return proj; } void -gimp_display_delete (GimpDisplay *gdisp) -{ - GimpTool *active_tool; - - g_return_if_fail (GIMP_IS_DISPLAY (gdisp)); - - /* remove the display from the list */ - gimp_container_remove (gdisp->gimage->gimp->displays, - GIMP_OBJECT (gdisp)); - - /* stop any active tool */ - tool_manager_control_active (gdisp->gimage->gimp, HALT, gdisp); - - active_tool = tool_manager_get_active (gdisp->gimage->gimp); - - if (active_tool) - { - if (active_tool->focus_display == gdisp) - tool_manager_focus_display_active (gdisp->gimage->gimp, NULL); - - /* clear out the pointer to this gdisp from the active tool */ - if (active_tool->gdisp == gdisp) - { - active_tool->drawable = NULL; - active_tool->gdisp = NULL; - } - } - - /* If this gdisplay was idlerendering at the time when it was deleted, - * deactivate the idlerendering thread before deletion! - */ - if (gdisp->idle_render.idle_id) - { - g_source_remove (gdisp->idle_render.idle_id); - gdisp->idle_render.idle_id = 0; - } - - /* free the update area lists */ - gimp_display_area_list_free (gdisp->update_areas); - gimp_display_area_list_free (gdisp->idle_render.update_areas); - - if (gdisp->shell) - { - GtkWidget *shell = gdisp->shell; - - /* set gdisp->shell to NULL *before* destroying the shell. - * all callbacks in gimpdisplayshell-callbacks.c will check - * this pointer and do nothing if the shell is in destruction. - */ - gdisp->shell = NULL; - gtk_widget_destroy (shell); - } - - /* unrefs the gimage */ - gimp_display_disconnect (gdisp); - - g_object_unref (gdisp); -} - -gint -gimp_display_get_ID (GimpDisplay *gdisp) -{ - g_return_val_if_fail (GIMP_IS_DISPLAY (gdisp), -1); - - return gdisp->ID; -} - -GimpDisplay * -gimp_display_get_by_ID (Gimp *gimp, - gint ID) -{ - GList *list; - - g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL); - - for (list = GIMP_LIST (gimp->displays)->list; - list; - list = g_list_next (list)) - { - GimpDisplay *gdisp = list->data; - - if (gdisp->ID == ID) - return gdisp; - } - - return NULL; -} - -void -gimp_display_reconnect (GimpDisplay *gdisp, - GimpImage *gimage) -{ - g_return_if_fail (GIMP_IS_DISPLAY (gdisp)); - g_return_if_fail (GIMP_IS_IMAGE (gimage)); - - if (gdisp->idle_render.idle_id) - { - g_source_remove (gdisp->idle_render.idle_id); - gdisp->idle_render.idle_id = 0; - } - - /* stop any active tool */ - tool_manager_control_active (gdisp->gimage->gimp, HALT, gdisp); - - gimp_display_shell_disconnect (GIMP_DISPLAY_SHELL (gdisp->shell)); - - gimp_display_disconnect (gdisp); - - gimp_display_connect (gdisp, gimage); - - gimp_display_add_update_area (gdisp, - 0, 0, - gdisp->gimage->width, - gdisp->gimage->height); - - gimp_display_shell_reconnect (GIMP_DISPLAY_SHELL (gdisp->shell)); -} - -void -gimp_display_add_update_area (GimpDisplay *gdisp, - gint x, - gint y, - gint w, - gint h) +gimp_projection_add_update_area (GimpProjection *proj, + gint x, + gint y, + gint w, + gint h) { GimpArea *area; - g_return_if_fail (GIMP_IS_DISPLAY (gdisp)); + g_return_if_fail (GIMP_IS_PROJECTION (proj)); - area = gimp_area_new (CLAMP (x, 0, gdisp->gimage->width), - CLAMP (y, 0, gdisp->gimage->height), - CLAMP (x + w, 0, gdisp->gimage->width), - CLAMP (y + h, 0, gdisp->gimage->height)); + area = gimp_area_new (CLAMP (x, 0, proj->gimage->width), + CLAMP (y, 0, proj->gimage->height), + CLAMP (x + w, 0, proj->gimage->width), + CLAMP (y + h, 0, proj->gimage->height)); - gdisp->update_areas = gimp_display_area_list_process (gdisp->update_areas, - area); + proj->update_areas = gimp_area_list_process (proj->update_areas, area); } -void -gimp_display_flush (GimpDisplay *gdisp) +TileManager * +gimp_projection_get_tiles (GimpProjection *proj) { - g_return_if_fail (GIMP_IS_DISPLAY (gdisp)); + g_return_val_if_fail (GIMP_IS_PROJECTION (proj), NULL); - /* Redraw on idle time */ - gimp_display_flush_whenever (gdisp, FALSE); -} - -void -gimp_display_flush_now (GimpDisplay *gdisp) -{ - g_return_if_fail (GIMP_IS_DISPLAY (gdisp)); - - /* Redraw NOW */ - gimp_display_flush_whenever (gdisp, TRUE); -} - -/* Force all gdisplays to finish their idlerender projection */ -void -gimp_display_finish_draw (GimpDisplay *gdisp) -{ - g_return_if_fail (GIMP_IS_DISPLAY (gdisp)); - - if (gdisp->idle_render.idle_id) + if (proj->tiles == NULL || + tile_manager_width (proj->tiles) != proj->gimage->width || + tile_manager_height (proj->tiles) != proj->gimage->height) { - g_source_remove (gdisp->idle_render.idle_id); - gdisp->idle_render.idle_id = 0; - - while (gimp_display_idlerender_callback (gdisp)); - } -} - -/* utility function to check if the cursor is inside the active drawable */ -gboolean -gimp_display_coords_in_active_drawable (GimpDisplay *gdisp, - const GimpCoords *coords) -{ - GimpDrawable *drawable; - - g_return_val_if_fail (GIMP_IS_DISPLAY (gdisp), FALSE); - - if (!gdisp->gimage) - return FALSE; - - drawable = gimp_image_active_drawable (gdisp->gimage); - - if (drawable) - { - GimpItem *item; - gint x, y; - - item = GIMP_ITEM (drawable); - - gimp_item_offsets (item, &x, &y); - - x = ROUND (coords->x) - x; - y = ROUND (coords->y) - y; - - if (x < 0 || x > gimp_item_width (item)) - return FALSE; - - if (y < 0 || y > gimp_item_height (item)) - return FALSE; - - return TRUE; + gimp_projection_alloc_tiles (proj); } - return FALSE; + return proj->tiles; } +GimpImageType +gimp_projection_get_image_type (const GimpProjection *proj) +{ + g_return_val_if_fail (GIMP_IS_PROJECTION (proj), -1); + + return proj->type; +} + +gint +gimp_projection_get_bytes (const GimpProjection *proj) +{ + g_return_val_if_fail (GIMP_IS_PROJECTION (proj), 0); + + return proj->bytes; +} + +gdouble +gimp_projection_get_opacity (const GimpProjection *proj) +{ + g_return_val_if_fail (GIMP_IS_PROJECTION (proj), GIMP_OPACITY_OPAQUE); + + return GIMP_OPACITY_OPAQUE; +} + +guchar * +gimp_projection_get_color_at (GimpProjection *proj, + gint x, + gint y) +{ + Tile *tile; + guchar *src; + guchar *dest; + + g_return_val_if_fail (GIMP_IS_PROJECTION (proj), NULL); + + if (x < 0 || y < 0 || x >= proj->gimage->width || y >= proj->gimage->height) + return NULL; + + dest = g_new (guchar, 5); + tile = tile_manager_get_tile (gimp_projection_get_tiles (proj), + x, y, TRUE, FALSE); + src = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT); + gimp_image_get_color (proj->gimage, gimp_projection_get_image_type (proj), + src, dest); + + dest[4] = 0; + tile_release (tile, FALSE); + + return dest; +} + +void +gimp_projection_flush (GimpProjection *proj) +{ + g_return_if_fail (GIMP_IS_PROJECTION (proj)); + + /* Construct on idle time */ + gimp_projection_flush_whenever (proj, FALSE); +} + +void +gimp_projection_flush_now (GimpProjection *proj) +{ + g_return_if_fail (GIMP_IS_PROJECTION (proj)); + + /* Construct NOW */ + gimp_projection_flush_whenever (proj, TRUE); +} + + /* private functions */ static void -gimp_display_flush_whenever (GimpDisplay *gdisp, - gboolean now) +gimp_projection_alloc_tiles (GimpProjection *proj) { - GimpDisplayShell *shell = GIMP_DISPLAY_SHELL (gdisp->shell); + GimpImageType proj_type = 0; + gint proj_bytes = 0; - /* Flush the items in the displays and updates lists - - * but only if gdisplay has been mapped and exposed + g_return_if_fail (GIMP_IS_PROJECTION (proj)); + + /* Find the number of bytes required for the projection. + * This includes the intensity channels and an alpha channel + * if one doesn't exist. */ - if (! shell->select) + switch (gimp_image_base_type (proj->gimage)) { - g_warning ("%s: called unrealized", G_STRFUNC); - return; + case GIMP_RGB: + case GIMP_INDEXED: + proj_bytes = 4; + proj_type = GIMP_RGBA_IMAGE; + break; + + case GIMP_GRAY: + proj_bytes = 2; + proj_type = GIMP_GRAYA_IMAGE; + break; + + default: + g_assert_not_reached (); } + if (proj->tiles) + { + if (proj_type != proj->type || + proj_bytes != proj->bytes || + proj->gimage->width != tile_manager_width (proj->tiles) || + proj->gimage->height != tile_manager_height (proj->tiles)) + { + tile_manager_unref (proj->tiles); + proj->tiles = NULL; + } + } + + if (! proj->tiles) + { + proj->type = proj_type; + proj->bytes = proj_bytes; + + proj->tiles = tile_manager_new (proj->gimage->width, + proj->gimage->height, + proj->bytes); + tile_manager_set_user_data (proj->tiles, proj); + tile_manager_set_validate_proc (proj->tiles, + gimp_projection_validate_tile); + } +} + +static void +gimp_projection_flush_whenever (GimpProjection *proj, + gboolean now) +{ /* First the updates... */ - if (gdisp->update_areas) + if (proj->update_areas) { if (now) /* Synchronous */ { GSList *list; - for (list = gdisp->update_areas; list; list = g_slist_next (list)) + for (list = proj->update_areas; list; list = g_slist_next (list)) { GimpArea *area = list->data; if ((area->x1 != area->x2) && (area->y1 != area->y2)) { - gimp_display_paint_area (gdisp, - area->x1, - area->y1, - (area->x2 - area->x1), - (area->y2 - area->y1)); + gimp_projection_paint_area (proj, + FALSE, /* sic! */ + area->x1, + area->y1, + (area->x2 - area->x1), + (area->y2 - area->y1)); } } } else /* Asynchronous */ { - gimp_display_idlerender_init (gdisp); + gimp_projection_idlerender_init (proj); } /* Free the update lists */ - gdisp->update_areas = gimp_display_area_list_free (gdisp->update_areas); + proj->update_areas = gimp_area_list_free (proj->update_areas); } - else +} + +void +gimp_projection_finish_draw (GimpProjection *proj) +{ + g_return_if_fail (GIMP_IS_PROJECTION (proj)); + + if (proj->idle_render.idle_id) { - /* if there was nothing to update, we still need to start the - * selection --mitch - */ - gimp_display_shell_selection_visibility (shell, GIMP_SELECTION_ON); - } + g_source_remove (proj->idle_render.idle_id); + proj->idle_render.idle_id = 0; - /* Next the displays... */ - gimp_display_shell_flush (shell, now); - - /* ensure the consistency of the menus */ - if (! now) - { - GimpContext *user_context; - - gimp_ui_manager_update (shell->menubar_manager, shell); - - user_context = gimp_get_user_context (gdisp->gimage->gimp); - - if (gdisp == gimp_context_get_display (user_context)) - gimp_ui_manager_update (shell->popup_manager, shell); + while (gimp_projection_idlerender_callback (proj)); } } static void -gimp_display_idlerender_init (GimpDisplay *gdisp) +gimp_projection_idlerender_init (GimpProjection *proj) { GSList *list; GimpArea *area; - /* We need to merge the IdleRender's and the GimpDisplay's update_areas list + /* We need to merge the IdleRender'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. */ - for (list = gdisp->update_areas; list; list = g_slist_next (list)) + for (list = proj->update_areas; list; list = g_slist_next (list)) { area = g_memdup (list->data, sizeof (GimpArea)); - gdisp->idle_render.update_areas = - gimp_display_area_list_process (gdisp->idle_render.update_areas, area); + proj->idle_render.update_areas = + gimp_area_list_process (proj->idle_render.update_areas, area); } /* If an idlerender was already running, merge the remainder of its * unrendered area with the update_areas list, and make it start work * on the next unrendered area in the list. */ - if (gdisp->idle_render.idle_id) + if (proj->idle_render.idle_id) { area = - gimp_area_new (gdisp->idle_render.basex, - gdisp->idle_render.y, - gdisp->idle_render.basex + gdisp->idle_render.width, - gdisp->idle_render.y + (gdisp->idle_render.height - - (gdisp->idle_render.y - - gdisp->idle_render.basey))); + gimp_area_new (proj->idle_render.basex, + proj->idle_render.y, + proj->idle_render.basex + proj->idle_render.width, + proj->idle_render.y + (proj->idle_render.height - + (proj->idle_render.y - + proj->idle_render.basey))); - gdisp->idle_render.update_areas = - gimp_display_area_list_process (gdisp->idle_render.update_areas, area); + proj->idle_render.update_areas = + gimp_area_list_process (proj->idle_render.update_areas, area); - gimp_display_idle_render_next_area (gdisp); + gimp_projection_idle_render_next_area (proj); } else { - if (gdisp->idle_render.update_areas == NULL) - { - g_warning ("Wanted to start idlerender thread with no update_areas. (+memleak)"); - return; - } + if (proj->idle_render.update_areas == NULL) + { + g_warning ("Wanted to start idlerender thread with no update_areas. (+memleak)"); + return; + } - gimp_display_idle_render_next_area (gdisp); + gimp_projection_idle_render_next_area (proj); - gdisp->idle_render.idle_id = g_idle_add_full (G_PRIORITY_LOW, - gimp_display_idlerender_callback, - gdisp, - NULL); + proj->idle_render.idle_id = g_idle_add_full (G_PRIORITY_LOW, + gimp_projection_idlerender_callback, + proj, + NULL); } - /* Caller frees gdisp->update_areas */ + /* Caller frees proj->update_areas */ } -/* Unless specified otherwise, display re-rendering is organised by +/* Unless specified otherwise, projection re-rendering is organised by * IdleRender, which amalgamates areas to be re-rendered and breaks * them into bite-sized chunks which are chewed on in a low- priority * idle thread. This greatly improves responsiveness for many GIMP * operations. -- Adam */ static gboolean -gimp_display_idlerender_callback (gpointer data) +gimp_projection_idlerender_callback (gpointer data) { const gint CHUNK_WIDTH = 256; const gint CHUNK_HEIGHT = 128; gint workx, worky, workw, workh; - GimpDisplay *gdisp = data; + GimpProjection *proj = data; workw = CHUNK_WIDTH; workh = CHUNK_HEIGHT; - workx = gdisp->idle_render.x; - worky = gdisp->idle_render.y; + workx = proj->idle_render.x; + worky = proj->idle_render.y; - if (workx + workw > gdisp->idle_render.basex + gdisp->idle_render.width) + if (workx + workw > proj->idle_render.basex + proj->idle_render.width) { - workw = gdisp->idle_render.basex + gdisp->idle_render.width - workx; + workw = proj->idle_render.basex + proj->idle_render.width - workx; } - if (worky + workh > gdisp->idle_render.basey + gdisp->idle_render.height) + if (worky + workh > proj->idle_render.basey + proj->idle_render.height) { - workh = gdisp->idle_render.basey + gdisp->idle_render.height - worky; + workh = proj->idle_render.basey + proj->idle_render.height - worky; } - gimp_display_paint_area (gdisp, workx, worky, workw, workh); + gimp_projection_paint_area (proj, TRUE, /* sic! */ + workx, worky, workw, workh); - gdisp->idle_render.x += CHUNK_WIDTH; + proj->idle_render.x += CHUNK_WIDTH; - if (gdisp->idle_render.x >= - gdisp->idle_render.basex + gdisp->idle_render.width) + if (proj->idle_render.x >= + proj->idle_render.basex + proj->idle_render.width) { - gdisp->idle_render.x = gdisp->idle_render.basex; - gdisp->idle_render.y += CHUNK_HEIGHT; + proj->idle_render.x = proj->idle_render.basex; + proj->idle_render.y += CHUNK_HEIGHT; - if (gdisp->idle_render.y >= - gdisp->idle_render.basey + gdisp->idle_render.height) - { - if (! gimp_display_idle_render_next_area (gdisp)) - { - /* FINISHED */ - gdisp->idle_render.idle_id = 0; + if (proj->idle_render.y >= + proj->idle_render.basey + proj->idle_render.height) + { + if (! gimp_projection_idle_render_next_area (proj)) + { + /* FINISHED */ + proj->idle_render.idle_id = 0; - return FALSE; - } - } + return FALSE; + } + } } /* Still work to do. */ @@ -620,22 +550,22 @@ gimp_display_idlerender_callback (gpointer data) } static gboolean -gimp_display_idle_render_next_area (GimpDisplay *gdisp) +gimp_projection_idle_render_next_area (GimpProjection *proj) { GimpArea *area; - if (! gdisp->idle_render.update_areas) + if (! proj->idle_render.update_areas) return FALSE; - area = (GimpArea *) gdisp->idle_render.update_areas->data; + area = (GimpArea *) proj->idle_render.update_areas->data; - gdisp->idle_render.update_areas = - g_slist_remove (gdisp->idle_render.update_areas, area); + proj->idle_render.update_areas = + g_slist_remove (proj->idle_render.update_areas, area); - gdisp->idle_render.x = gdisp->idle_render.basex = area->x1; - gdisp->idle_render.y = gdisp->idle_render.basey = area->y1; - gdisp->idle_render.width = area->x2 - area->x1; - gdisp->idle_render.height = area->y2 - area->y1; + proj->idle_render.x = proj->idle_render.basex = area->x1; + proj->idle_render.y = proj->idle_render.basey = area->y1; + proj->idle_render.width = area->x2 - area->x1; + proj->idle_render.height = area->y2 - area->y1; g_free (area); @@ -643,58 +573,103 @@ gimp_display_idle_render_next_area (GimpDisplay *gdisp) } static void -gimp_display_paint_area (GimpDisplay *gdisp, - gint x, - gint y, - gint w, - gint h) +gimp_projection_paint_area (GimpProjection *proj, + gboolean now, + gint x, + gint y, + gint w, + gint h) { - GimpDisplayShell *shell = GIMP_DISPLAY_SHELL (gdisp->shell); - gint x1, y1, x2, y2; - gdouble x1_f, y1_f, x2_f, y2_f; + gint x1, y1, x2, y2; /* Bounds check */ - x1 = CLAMP (x, 0, gdisp->gimage->width); - y1 = CLAMP (y, 0, gdisp->gimage->height); - x2 = CLAMP (x + w, 0, gdisp->gimage->width); - y2 = CLAMP (y + h, 0, gdisp->gimage->height); + x1 = CLAMP (x, 0, proj->gimage->width); + y1 = CLAMP (y, 0, proj->gimage->height); + x2 = CLAMP (x + w, 0, proj->gimage->width); + y2 = CLAMP (y + h, 0, proj->gimage->height); x = x1; y = y1; w = (x2 - x1); h = (y2 - y1); - /* calculate the extents of the update as limited by what's visible */ - gimp_display_shell_untransform_xy_f (shell, - 0, 0, - &x1_f, &y1_f, - FALSE); - gimp_display_shell_untransform_xy_f (shell, - shell->disp_width, shell->disp_height, - &x2_f, &y2_f, - FALSE); + gimp_projection_invalidate (proj, x, y, w, h); - /* make sure to limit the invalidated area to a superset of the - * untransformed sub-pixel display area, not a subset. - * bug #116765. --mitch - */ - x1 = floor (x1_f); - y1 = floor (y1_f); - x2 = ceil (x2_f); - y2 = ceil (y2_f); - - gimp_image_invalidate (gdisp->gimage, x, y, w, h, x1, y1, x2, y2); - - /* display the area */ - gimp_display_shell_transform_xy_f (shell, x, y, &x1_f, &y1_f, FALSE); - gimp_display_shell_transform_xy_f (shell, x + w, y + h, &x2_f, &y2_f, FALSE); - - /* make sure to expose a superset of the transformed sub-pixel expose - * area, not a subset. bug #126942. --mitch - */ - x1 = floor (x1_f); - y1 = floor (y1_f); - x2 = ceil (x2_f); - y2 = ceil (y2_f); - - gimp_display_shell_expose_area (shell, x1, y1, x2 - x1, y2 - y1); + g_signal_emit (proj, projection_signals[UPDATE], 0, + now, x, y, w, h); } + +static void +gimp_projection_invalidate (GimpProjection *proj, + gint x, + gint y, + gint w, + gint h) +{ + Tile *tile; + TileManager *tm; + gint i, j; + + tm = gimp_projection_get_tiles (proj); + + for (i = y; i < (y + h); i += (TILE_HEIGHT - (i % TILE_HEIGHT))) + for (j = x; j < (x + w); j += (TILE_WIDTH - (j % TILE_WIDTH))) + { + tile = tile_manager_get_tile (tm, j, i, FALSE, FALSE); + + tile_invalidate_tile (&tile, tm, j, i); + } +} + +static void +gimp_projection_validate_tile (TileManager *tm, + Tile *tile) +{ + GimpProjection *proj = tile_manager_get_user_data (tm); + gint x, y; + gint w, h; + + /* Find the coordinates of this tile */ + tile_manager_get_tile_coordinates (tm, tile, &x, &y); + w = tile_ewidth (tile); + h = tile_eheight (tile); + + gimp_projection_construct (proj, x, y, w, h); +} + + +/* image callbacks */ + +static void +gimp_projection_image_update (GimpImage *gimage, + gint x, + gint y, + gint w, + gint h, + GimpProjection *proj) +{ + gimp_projection_add_update_area (proj, x, y, w, h); +} + +static void +gimp_projection_image_size_changed (GimpImage *gimage, + GimpProjection *proj) +{ + gimp_projection_alloc_tiles (proj); + gimp_projection_add_update_area (proj, 0, 0, gimage->width, gimage->height); +} + +static void +gimp_projection_image_mode_changed (GimpImage *gimage, + GimpProjection *proj) +{ + gimp_projection_alloc_tiles (proj); + gimp_projection_add_update_area (proj, 0, 0, gimage->width, gimage->height); +} + +static void +gimp_projection_image_flush (GimpImage *gimage, + GimpProjection *proj) +{ + gimp_projection_flush (proj); +} + diff --git a/app/core/gimpprojection.h b/app/core/gimpprojection.h index 89b235aa59..84057b9470 100644 --- a/app/core/gimpprojection.h +++ b/app/core/gimpprojection.h @@ -16,11 +16,11 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#ifndef __GIMP_DISPLAY_H__ -#define __GIMP_DISPLAY_H__ +#ifndef __GIMP_PROJECTION_H__ +#define __GIMP_PROJECTION_H__ -#include "core/gimpobject.h" +#include "gimpobject.h" typedef struct _IdleRenderStruct IdleRenderStruct; @@ -38,67 +38,60 @@ struct _IdleRenderStruct }; -#define GIMP_TYPE_DISPLAY (gimp_display_get_type ()) -#define GIMP_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_DISPLAY, GimpDisplay)) -#define GIMP_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_DISPLAY, GimpDisplayClass)) -#define GIMP_IS_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_DISPLAY)) -#define GIMP_IS_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_DISPLAY)) -#define GIMP_DISPLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_DISPLAY, GimpDisplayClass)) +#define GIMP_TYPE_PROJECTION (gimp_projection_get_type ()) +#define GIMP_PROJECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_PROJECTION, GimpProjection)) +#define GIMP_PROJECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_PROJECTION, GimpProjectionClass)) +#define GIMP_IS_PROJECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_PROJECTION)) +#define GIMP_IS_PROJECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_PROJECTION)) +#define GIMP_PROJECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_PROJECTION, GimpProjectionClass)) -typedef struct _GimpDisplayClass GimpDisplayClass; +typedef struct _GimpProjectionClass GimpProjectionClass; -struct _GimpDisplay +struct _GimpProjection { - GimpObject parent_instance; + GimpObject parent_instance; - gint ID; /* unique identifier for this gdisplay */ + GimpImage *gimage; - GimpImage *gimage; /* pointer to the associated gimage */ - gint instance; /* the instance # of this gdisplay as */ - /* taken from the gimage at creation */ + GimpImageType type; + gint bytes; + TileManager *tiles; - GtkWidget *shell; /* shell widget for this gdisplay */ + GSList *update_areas; + IdleRenderStruct idle_render; - GSList *update_areas; /* Update areas list */ - - IdleRenderStruct idle_render; /* state of this gdisplay's render thread */ + gboolean construct_flag; }; -struct _GimpDisplayClass +struct _GimpProjectionClass { GimpObjectClass parent_class; + + void (* update) (GimpProjection *gimage, + gboolean now, + gint x, + gint y, + gint width, + gint height); }; -GType gimp_display_get_type (void) G_GNUC_CONST; +GType gimp_projection_get_type (void) G_GNUC_CONST; -GimpDisplay * gimp_display_new (GimpImage *gimage, - GimpUnit unit, - gdouble scale, - GimpMenuFactory *menu_factory, - GimpUIManager *popup_manager); -void gimp_display_delete (GimpDisplay *gdisp); +GimpProjection * gimp_projection_new (GimpImage *gimage); -gint gimp_display_get_ID (GimpDisplay *gdisp); -GimpDisplay * gimp_display_get_by_ID (Gimp *gimp, - gint ID); +TileManager * gimp_projection_get_tiles (GimpProjection *proj); +GimpImageType gimp_projection_get_image_type (const GimpProjection *proj); +gint gimp_projection_get_bytes (const GimpProjection *proj); +gdouble gimp_projection_get_opacity (const GimpProjection *proj); -void gimp_display_reconnect (GimpDisplay *gdisp, - GimpImage *gimage); +guchar * gimp_projection_get_color_at (GimpProjection *proj, + gint x, + gint y); -void gimp_display_add_update_area (GimpDisplay *gdisp, - gint x, - gint y, - gint w, - gint h); +void gimp_projection_flush (GimpProjection *proj); +void gimp_projection_flush_now (GimpProjection *proj); -void gimp_display_flush (GimpDisplay *gdisp); -void gimp_display_flush_now (GimpDisplay *gdisp); -void gimp_display_finish_draw (GimpDisplay *gdisp); - -gboolean gimp_display_coords_in_active_drawable (GimpDisplay *gdisp, - const GimpCoords *coords); - -#endif /* __GIMP_DISPLAY_H__ */ +#endif /* __GIMP_PROJECTION_H__ */ diff --git a/app/dialogs/info-window.c b/app/dialogs/info-window.c index 0e8ac66bb0..02e9b83f6c 100644 --- a/app/dialogs/info-window.c +++ b/app/dialogs/info-window.c @@ -32,7 +32,7 @@ #include "core/gimpcontainer.h" #include "core/gimpcontext.h" #include "core/gimpimage.h" -#include "core/gimpimage-projection.h" +#include "core/gimpprojection.h" #include "core/gimptemplate.h" #include "core/gimpunit.h" @@ -402,7 +402,7 @@ info_window_update_extended (GimpDisplay *gdisp, } /* fill in color information */ - color = gimp_image_projection_get_color_at (gdisp->gimage, tx, ty); + color = gimp_projection_get_color_at (gdisp->gimage->projection, tx, ty); if (! color || (tx < 0.0 && ty < 0.0)) { @@ -414,7 +414,7 @@ info_window_update_extended (GimpDisplay *gdisp, GimpImageType sample_type; GimpRGB rgb; - sample_type = gimp_image_projection_type (gdisp->gimage); + sample_type = gimp_projection_get_image_type (gdisp->gimage->projection); gimp_rgba_set_uchar (&rgb, color[RED_PIX], diff --git a/app/display/Makefile.am b/app/display/Makefile.am index 1eb7f0bfdf..07d3fa592d 100644 --- a/app/display/Makefile.am +++ b/app/display/Makefile.am @@ -22,8 +22,6 @@ libappdisplay_a_sources = \ gimpdisplay.h \ gimpdisplayoptions.c \ gimpdisplayoptions.h \ - gimpdisplay-area.c \ - gimpdisplay-area.h \ gimpdisplay-foreach.c \ gimpdisplay-foreach.h \ gimpdisplay-handlers.c \ diff --git a/app/display/gimpdisplay-area.c b/app/display/gimpdisplay-area.c deleted file mode 100644 index 29c411d36e..0000000000 --- a/app/display/gimpdisplay-area.c +++ /dev/null @@ -1,105 +0,0 @@ -/* The GIMP -- an 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include "display-types.h" - -#include "gimpdisplay-area.h" - - -#define OVERHEAD 25 /* in units of pixel area */ - - -GimpArea * -gimp_area_new (gint x1, - gint y1, - gint x2, - gint y2) -{ - GimpArea *area; - - area = g_new (GimpArea, 1); - - area->x1 = x1; - area->y1 = y1; - area->x2 = x2; - area->y2 = y2; - - return 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_display_area_list_process (GSList *list, - GimpArea *area) -{ - GSList *new_list; - GSList *l; - gint area1, area2, area3; - GimpArea *ga2; - - /* start new list off */ - new_list = g_slist_prepend (NULL, area); - - for (l = list; l; l = g_slist_next (l)) - { - ga2 = (GimpArea *) l->data; - - area1 = (area->x2 - area->x1) * (area->y2 - area->y1) + OVERHEAD; - area2 = (ga2->x2 - ga2->x1) * (ga2->y2 - ga2->y1) + OVERHEAD; - area3 = (MAX (ga2->x2, area->x2) - MIN (ga2->x1, area->x1)) * - (MAX (ga2->y2, area->y2) - MIN (ga2->y1, area->y1)) + OVERHEAD; - - if ((area1 + area2) < area3) - { - new_list = g_slist_prepend (new_list, ga2); - } - else - { - area->x1 = MIN (area->x1, ga2->x1); - area->y1 = MIN (area->y1, ga2->y1); - area->x2 = MAX (area->x2, ga2->x2); - area->y2 = MAX (area->y2, ga2->y2); - - g_free (ga2); - } - } - - if (list) - g_slist_free (list); - - return new_list; -} - -GSList * -gimp_display_area_list_free (GSList *list) -{ - if (list) - { - g_slist_foreach (list, (GFunc) g_free, NULL); - g_slist_free (list); - } - - return NULL; -} diff --git a/app/display/gimpdisplay-area.h b/app/display/gimpdisplay-area.h deleted file mode 100644 index 81067df212..0000000000 --- a/app/display/gimpdisplay-area.h +++ /dev/null @@ -1,41 +0,0 @@ -/* The GIMP -- an 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __GIMP_DISPLAY_AREA_H__ -#define __GIMP_DISPLAY_AREA_H__ - - -typedef struct _GimpArea GimpArea; - -struct _GimpArea -{ - gint x1, y1, x2, y2; /* area bounds */ -}; - - -GimpArea * gimp_area_new (gint x1, - gint y1, - gint x2, - gint y2); - -GSList * gimp_display_area_list_process (GSList *list, - GimpArea *area); -GSList * gimp_display_area_list_free (GSList *list); - - -#endif /* __GIMP_DISPLAY_AREA_H__ */ diff --git a/app/display/gimpdisplay-foreach.c b/app/display/gimpdisplay-foreach.c index 3746db6342..79605ad4b7 100644 --- a/app/display/gimpdisplay-foreach.c +++ b/app/display/gimpdisplay-foreach.c @@ -102,25 +102,6 @@ gimp_displays_delete (Gimp *gimp) } } -/* Force all gdisplays to finish their idlerender projection */ -void -gimp_displays_finish_draw (Gimp *gimp) -{ - GList *list; - GimpDisplay *gdisp; - - g_return_if_fail (GIMP_IS_GIMP (gimp)); - - for (list = GIMP_LIST (gimp->displays)->list; - list; - list = g_list_next (list)) - { - gdisp = (GimpDisplay *) list->data; - - gimp_display_finish_draw (gdisp); - } -} - void gimp_displays_reconnect (Gimp *gimp, GimpImage *old, diff --git a/app/display/gimpdisplay-foreach.h b/app/display/gimpdisplay-foreach.h index 2b7089b029..8356abfd5a 100644 --- a/app/display/gimpdisplay-foreach.h +++ b/app/display/gimpdisplay-foreach.h @@ -23,7 +23,6 @@ gboolean gimp_displays_dirty (Gimp *gimp); GimpContainer * gimp_displays_get_dirty_images (Gimp *gimp); void gimp_displays_delete (Gimp *gimp); -void gimp_displays_finish_draw (Gimp *gimp); void gimp_displays_reconnect (Gimp *gimp, GimpImage *old, GimpImage *new); diff --git a/app/display/gimpdisplay-handlers.c b/app/display/gimpdisplay-handlers.c index 153adbbd60..6c2529eda0 100644 --- a/app/display/gimpdisplay-handlers.c +++ b/app/display/gimpdisplay-handlers.c @@ -26,6 +26,7 @@ #include "core/gimp.h" #include "core/gimpimage.h" +#include "core/gimpprojection.h" #include "gimpdisplay.h" #include "gimpdisplay-handlers.h" @@ -33,16 +34,15 @@ /* local function prototypes */ -static void gimp_display_update_handler (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h, - GimpDisplay *gdisp); -static void gimp_display_size_changed_handler (GimpImage *gimage, - GimpDisplay *gdisp); -static void gimp_display_flush_handler (GimpImage *gimage, - GimpDisplay *gdisp); +static void gimp_display_update_handler (GimpProjection *projection, + gboolean now, + gint x, + gint y, + gint w, + gint h, + GimpDisplay *gdisp); +static void gimp_display_flush_handler (GimpImage *gimage, + GimpDisplay *gdisp); /* public functions */ @@ -68,12 +68,9 @@ gimp_display_connect (GimpDisplay *gdisp, g_object_ref (gimage); - g_signal_connect (gimage, "update", + g_signal_connect (gimage->projection, "update", G_CALLBACK (gimp_display_update_handler), gdisp); - g_signal_connect (gimage, "size_changed", - G_CALLBACK (gimp_display_size_changed_handler), - gdisp); g_signal_connect (gimage, "flush", G_CALLBACK (gimp_display_flush_handler), gdisp); @@ -90,10 +87,7 @@ gimp_display_disconnect (GimpDisplay *gdisp) g_signal_handlers_disconnect_by_func (gdisp->gimage, gimp_display_flush_handler, gdisp); - g_signal_handlers_disconnect_by_func (gdisp->gimage, - gimp_display_size_changed_handler, - gdisp); - g_signal_handlers_disconnect_by_func (gdisp->gimage, + g_signal_handlers_disconnect_by_func (gdisp->gimage->projection, gimp_display_update_handler, gdisp); @@ -118,40 +112,15 @@ gimp_display_disconnect (GimpDisplay *gdisp) /* private functions */ static void -gimp_display_update_handler (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h, - GimpDisplay *gdisp) +gimp_display_update_handler (GimpProjection *projection, + gboolean now, + gint x, + gint y, + gint w, + gint h, + GimpDisplay *gdisp) { - gimp_display_add_update_area (gdisp, x, y, w, h); -} - -static void -gimp_display_size_changed_handler (GimpImage *gimage, - GimpDisplay *gdisp) -{ -#if 0 - /* stop rendering and free all update area lists because - * their coordinates have been invalidated by the resize - */ - if (gdisp->idle_render.idle_id) - { - g_source_remove (gdisp->idle_render.idle_id); - gdisp->idle_render.idle_id = 0; - } - - gimp_display_area_list_free (gdisp->update_areas); - gimp_display_area_list_free (gdisp->idle_render.update_areas); - gdisp->update_areas = NULL; - gdisp->idle_render.update_areas = NULL; -#endif - - gimp_display_add_update_area (gdisp, - 0, 0, - gdisp->gimage->width, - gdisp->gimage->height); + gimp_display_update_area (gdisp, now, x, y, w, h); } static void diff --git a/app/display/gimpdisplay.c b/app/display/gimpdisplay.c index 55ea956082..c3ad159c43 100644 --- a/app/display/gimpdisplay.c +++ b/app/display/gimpdisplay.c @@ -24,20 +24,16 @@ #include "tools/tools-types.h" #include "core/gimp.h" -#include "core/gimpcontainer.h" -#include "core/gimpcontext.h" +#include "core/gimparea.h" #include "core/gimpdrawable.h" #include "core/gimpimage.h" -#include "core/gimpimage-projection.h" #include "core/gimplist.h" - -#include "widgets/gimpuimanager.h" +#include "core/gimpprojection.h" #include "tools/gimptool.h" #include "tools/tool_manager.h" #include "gimpdisplay.h" -#include "gimpdisplay-area.h" #include "gimpdisplay-handlers.h" #include "gimpdisplayshell.h" #include "gimpdisplayshell-handlers.h" @@ -56,28 +52,25 @@ enum /* local function prototypes */ -static void gimp_display_class_init (GimpDisplayClass *klass); -static void gimp_display_init (GimpDisplay *gdisp); +static void gimp_display_class_init (GimpDisplayClass *klass); +static void gimp_display_init (GimpDisplay *gdisp); -static void gimp_display_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec); -static void gimp_display_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec); +static void gimp_display_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_display_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); -static void gimp_display_flush_whenever (GimpDisplay *gdisp, - gboolean now); -static void gimp_display_idlerender_init (GimpDisplay *gdisp); -static gboolean gimp_display_idlerender_callback (gpointer data); -static gboolean gimp_display_idle_render_next_area (GimpDisplay *gdisp); -static void gimp_display_paint_area (GimpDisplay *gdisp, - gint x, - gint y, - gint w, - gint h); +static void gimp_display_flush_whenever (GimpDisplay *gdisp, + gboolean now); +static void gimp_display_paint_area (GimpDisplay *gdisp, + gint x, + gint y, + gint w, + gint h); static GimpObjectClass *parent_class = NULL; @@ -93,14 +86,14 @@ gimp_display_get_type (void) static const GTypeInfo display_info = { sizeof (GimpDisplayClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) gimp_display_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GimpDisplay), - 0, /* n_preallocs */ - (GInstanceInitFunc) gimp_display_init, + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gimp_display_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GimpDisplay), + 0, /* n_preallocs */ + (GInstanceInitFunc) gimp_display_init, }; display_type = g_type_register_static (GIMP_TYPE_OBJECT, @@ -138,17 +131,14 @@ gimp_display_class_init (GimpDisplayClass *klass) static void gimp_display_init (GimpDisplay *gdisp) { - gdisp->ID = 0; + gdisp->ID = 0; - gdisp->gimage = NULL; - gdisp->instance = 0; + gdisp->gimage = NULL; + gdisp->instance = 0; - gdisp->shell = NULL; + gdisp->shell = NULL; - gdisp->update_areas = NULL; - - gdisp->idle_render.idle_id = 0; - gdisp->idle_render.update_areas = NULL; + gdisp->update_areas = NULL; } static void @@ -255,18 +245,8 @@ gimp_display_delete (GimpDisplay *gdisp) } } - /* If this gdisplay was idlerendering at the time when it was deleted, - * deactivate the idlerendering thread before deletion! - */ - if (gdisp->idle_render.idle_id) - { - g_source_remove (gdisp->idle_render.idle_id); - gdisp->idle_render.idle_id = 0; - } - /* free the update area lists */ - gimp_display_area_list_free (gdisp->update_areas); - gimp_display_area_list_free (gdisp->idle_render.update_areas); + gdisp->update_areas = gimp_area_list_free (gdisp->update_areas); if (gdisp->shell) { @@ -309,7 +289,7 @@ gimp_display_get_by_ID (Gimp *gimp, GimpDisplay *gdisp = list->data; if (gdisp->ID == ID) - return gdisp; + return gdisp; } return NULL; @@ -322,12 +302,6 @@ gimp_display_reconnect (GimpDisplay *gdisp, g_return_if_fail (GIMP_IS_DISPLAY (gdisp)); g_return_if_fail (GIMP_IS_IMAGE (gimage)); - if (gdisp->idle_render.idle_id) - { - g_source_remove (gdisp->idle_render.idle_id); - gdisp->idle_render.idle_id = 0; - } - /* stop any active tool */ tool_manager_control_active (gdisp->gimage->gimp, HALT, gdisp); @@ -337,32 +311,32 @@ gimp_display_reconnect (GimpDisplay *gdisp, gimp_display_connect (gdisp, gimage); - gimp_display_add_update_area (gdisp, - 0, 0, - gdisp->gimage->width, - gdisp->gimage->height); - gimp_display_shell_reconnect (GIMP_DISPLAY_SHELL (gdisp->shell)); } void -gimp_display_add_update_area (GimpDisplay *gdisp, - gint x, - gint y, - gint w, - gint h) +gimp_display_update_area (GimpDisplay *gdisp, + gboolean now, + gint x, + gint y, + gint w, + gint h) { - GimpArea *area; - g_return_if_fail (GIMP_IS_DISPLAY (gdisp)); - area = gimp_area_new (CLAMP (x, 0, gdisp->gimage->width), - CLAMP (y, 0, gdisp->gimage->height), - CLAMP (x + w, 0, gdisp->gimage->width), - CLAMP (y + h, 0, gdisp->gimage->height)); + if (now) + { + gimp_display_paint_area (gdisp, x, y, w, h); + } + else + { + GimpArea *area = gimp_area_new (CLAMP (x, 0, gdisp->gimage->width), + CLAMP (y, 0, gdisp->gimage->height), + CLAMP (x + w, 0, gdisp->gimage->width), + CLAMP (y + h, 0, gdisp->gimage->height)); - gdisp->update_areas = gimp_display_area_list_process (gdisp->update_areas, - area); + gdisp->update_areas = gimp_area_list_process (gdisp->update_areas, area); + } } void @@ -370,7 +344,6 @@ gimp_display_flush (GimpDisplay *gdisp) { g_return_if_fail (GIMP_IS_DISPLAY (gdisp)); - /* Redraw on idle time */ gimp_display_flush_whenever (gdisp, FALSE); } @@ -379,62 +352,9 @@ gimp_display_flush_now (GimpDisplay *gdisp) { g_return_if_fail (GIMP_IS_DISPLAY (gdisp)); - /* Redraw NOW */ gimp_display_flush_whenever (gdisp, TRUE); } -/* Force all gdisplays to finish their idlerender projection */ -void -gimp_display_finish_draw (GimpDisplay *gdisp) -{ - g_return_if_fail (GIMP_IS_DISPLAY (gdisp)); - - if (gdisp->idle_render.idle_id) - { - g_source_remove (gdisp->idle_render.idle_id); - gdisp->idle_render.idle_id = 0; - - while (gimp_display_idlerender_callback (gdisp)); - } -} - -/* utility function to check if the cursor is inside the active drawable */ -gboolean -gimp_display_coords_in_active_drawable (GimpDisplay *gdisp, - const GimpCoords *coords) -{ - GimpDrawable *drawable; - - g_return_val_if_fail (GIMP_IS_DISPLAY (gdisp), FALSE); - - if (!gdisp->gimage) - return FALSE; - - drawable = gimp_image_active_drawable (gdisp->gimage); - - if (drawable) - { - GimpItem *item; - gint x, y; - - item = GIMP_ITEM (drawable); - - gimp_item_offsets (item, &x, &y); - - x = ROUND (coords->x) - x; - y = ROUND (coords->y) - y; - - if (x < 0 || x > gimp_item_width (item)) - return FALSE; - - if (y < 0 || y > gimp_item_height (item)) - return FALSE; - - return TRUE; - } - - return FALSE; -} /* private functions */ @@ -442,204 +362,28 @@ static void gimp_display_flush_whenever (GimpDisplay *gdisp, gboolean now) { - GimpDisplayShell *shell = GIMP_DISPLAY_SHELL (gdisp->shell); - - /* Flush the items in the displays and updates lists - - * but only if gdisplay has been mapped and exposed - */ - if (! shell->select) - { - g_warning ("%s: called unrealized", G_STRFUNC); - return; - } - - /* First the updates... */ if (gdisp->update_areas) { - if (now) /* Synchronous */ + GSList *list; + + for (list = gdisp->update_areas; list; list = g_slist_next (list)) { - GSList *list; + GimpArea *area = list->data; - for (list = gdisp->update_areas; list; list = g_slist_next (list)) + if ((area->x1 != area->x2) && (area->y1 != area->y2)) { - GimpArea *area = list->data; - - if ((area->x1 != area->x2) && (area->y1 != area->y2)) - { - gimp_display_paint_area (gdisp, - area->x1, - area->y1, - (area->x2 - area->x1), - (area->y2 - area->y1)); - } + gimp_display_paint_area (gdisp, + area->x1, + area->y1, + (area->x2 - area->x1), + (area->y2 - area->y1)); } } - else /* Asynchronous */ - { - gimp_display_idlerender_init (gdisp); - } - /* Free the update lists */ - gdisp->update_areas = gimp_display_area_list_free (gdisp->update_areas); - } - else - { - /* if there was nothing to update, we still need to start the - * selection --mitch - */ - gimp_display_shell_selection_visibility (shell, GIMP_SELECTION_ON); + gdisp->update_areas = gimp_area_list_free (gdisp->update_areas); } - /* Next the displays... */ - gimp_display_shell_flush (shell, now); - - /* ensure the consistency of the menus */ - if (! now) - { - GimpContext *user_context; - - gimp_ui_manager_update (shell->menubar_manager, shell); - - user_context = gimp_get_user_context (gdisp->gimage->gimp); - - if (gdisp == gimp_context_get_display (user_context)) - gimp_ui_manager_update (shell->popup_manager, shell); - } -} - -static void -gimp_display_idlerender_init (GimpDisplay *gdisp) -{ - GSList *list; - GimpArea *area; - - /* We need to merge the IdleRender's and the GimpDisplay's update_areas list - * to keep track of which of the updates have been flushed and hence need - * to be drawn. - */ - for (list = gdisp->update_areas; list; list = g_slist_next (list)) - { - area = g_memdup (list->data, sizeof (GimpArea)); - - gdisp->idle_render.update_areas = - gimp_display_area_list_process (gdisp->idle_render.update_areas, area); - } - - /* If an idlerender was already running, merge the remainder of its - * unrendered area with the update_areas list, and make it start work - * on the next unrendered area in the list. - */ - if (gdisp->idle_render.idle_id) - { - area = - gimp_area_new (gdisp->idle_render.basex, - gdisp->idle_render.y, - gdisp->idle_render.basex + gdisp->idle_render.width, - gdisp->idle_render.y + (gdisp->idle_render.height - - (gdisp->idle_render.y - - gdisp->idle_render.basey))); - - gdisp->idle_render.update_areas = - gimp_display_area_list_process (gdisp->idle_render.update_areas, area); - - gimp_display_idle_render_next_area (gdisp); - } - else - { - if (gdisp->idle_render.update_areas == NULL) - { - g_warning ("Wanted to start idlerender thread with no update_areas. (+memleak)"); - return; - } - - gimp_display_idle_render_next_area (gdisp); - - gdisp->idle_render.idle_id = g_idle_add_full (G_PRIORITY_LOW, - gimp_display_idlerender_callback, - gdisp, - NULL); - } - - /* Caller frees gdisp->update_areas */ -} - -/* Unless specified otherwise, display re-rendering is organised by - * IdleRender, which amalgamates areas to be re-rendered and breaks - * them into bite-sized chunks which are chewed on in a low- priority - * idle thread. This greatly improves responsiveness for many GIMP - * operations. -- Adam - */ -static gboolean -gimp_display_idlerender_callback (gpointer data) -{ - const gint CHUNK_WIDTH = 256; - const gint CHUNK_HEIGHT = 128; - gint workx, worky, workw, workh; - GimpDisplay *gdisp = data; - - workw = CHUNK_WIDTH; - workh = CHUNK_HEIGHT; - workx = gdisp->idle_render.x; - worky = gdisp->idle_render.y; - - if (workx + workw > gdisp->idle_render.basex + gdisp->idle_render.width) - { - workw = gdisp->idle_render.basex + gdisp->idle_render.width - workx; - } - - if (worky + workh > gdisp->idle_render.basey + gdisp->idle_render.height) - { - workh = gdisp->idle_render.basey + gdisp->idle_render.height - worky; - } - - gimp_display_paint_area (gdisp, workx, worky, workw, workh); - - gdisp->idle_render.x += CHUNK_WIDTH; - - if (gdisp->idle_render.x >= - gdisp->idle_render.basex + gdisp->idle_render.width) - { - gdisp->idle_render.x = gdisp->idle_render.basex; - gdisp->idle_render.y += CHUNK_HEIGHT; - - if (gdisp->idle_render.y >= - gdisp->idle_render.basey + gdisp->idle_render.height) - { - if (! gimp_display_idle_render_next_area (gdisp)) - { - /* FINISHED */ - gdisp->idle_render.idle_id = 0; - - return FALSE; - } - } - } - - /* Still work to do. */ - return TRUE; -} - -static gboolean -gimp_display_idle_render_next_area (GimpDisplay *gdisp) -{ - GimpArea *area; - - if (! gdisp->idle_render.update_areas) - return FALSE; - - area = (GimpArea *) gdisp->idle_render.update_areas->data; - - gdisp->idle_render.update_areas = - g_slist_remove (gdisp->idle_render.update_areas, area); - - gdisp->idle_render.x = gdisp->idle_render.basex = area->x1; - gdisp->idle_render.y = gdisp->idle_render.basey = area->y1; - gdisp->idle_render.width = area->x2 - area->x1; - gdisp->idle_render.height = area->y2 - area->y1; - - g_free (area); - - return TRUE; + gimp_display_shell_flush (GIMP_DISPLAY_SHELL (gdisp->shell), now); } static void @@ -663,27 +407,6 @@ gimp_display_paint_area (GimpDisplay *gdisp, w = (x2 - x1); h = (y2 - y1); - /* calculate the extents of the update as limited by what's visible */ - gimp_display_shell_untransform_xy_f (shell, - 0, 0, - &x1_f, &y1_f, - FALSE); - gimp_display_shell_untransform_xy_f (shell, - shell->disp_width, shell->disp_height, - &x2_f, &y2_f, - FALSE); - - /* make sure to limit the invalidated area to a superset of the - * untransformed sub-pixel display area, not a subset. - * bug #116765. --mitch - */ - x1 = floor (x1_f); - y1 = floor (y1_f); - x2 = ceil (x2_f); - y2 = ceil (y2_f); - - gimp_image_invalidate (gdisp->gimage, x, y, w, h, x1, y1, x2, y2); - /* display the area */ gimp_display_shell_transform_xy_f (shell, x, y, &x1_f, &y1_f, FALSE); gimp_display_shell_transform_xy_f (shell, x + w, y + h, &x2_f, &y2_f, FALSE); diff --git a/app/display/gimpdisplay.h b/app/display/gimpdisplay.h index 89b235aa59..7d0e98d097 100644 --- a/app/display/gimpdisplay.h +++ b/app/display/gimpdisplay.h @@ -23,21 +23,6 @@ #include "core/gimpobject.h" -typedef struct _IdleRenderStruct IdleRenderStruct; - -struct _IdleRenderStruct -{ - gint width; - gint height; - gint x; - gint y; - gint basex; - gint basey; - guint idle_id; - GSList *update_areas; /* flushed update areas */ -}; - - #define GIMP_TYPE_DISPLAY (gimp_display_get_type ()) #define GIMP_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_DISPLAY, GimpDisplay)) #define GIMP_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_DISPLAY, GimpDisplayClass)) @@ -61,8 +46,6 @@ struct _GimpDisplay GtkWidget *shell; /* shell widget for this gdisplay */ GSList *update_areas; /* Update areas list */ - - IdleRenderStruct idle_render; /* state of this gdisplay's render thread */ }; struct _GimpDisplayClass @@ -71,34 +54,31 @@ struct _GimpDisplayClass }; -GType gimp_display_get_type (void) G_GNUC_CONST; +GType gimp_display_get_type (void) G_GNUC_CONST; -GimpDisplay * gimp_display_new (GimpImage *gimage, - GimpUnit unit, - gdouble scale, - GimpMenuFactory *menu_factory, - GimpUIManager *popup_manager); -void gimp_display_delete (GimpDisplay *gdisp); +GimpDisplay * gimp_display_new (GimpImage *gimage, + GimpUnit unit, + gdouble scale, + GimpMenuFactory *menu_factory, + GimpUIManager *popup_manager); +void gimp_display_delete (GimpDisplay *gdisp); -gint gimp_display_get_ID (GimpDisplay *gdisp); -GimpDisplay * gimp_display_get_by_ID (Gimp *gimp, - gint ID); +gint gimp_display_get_ID (GimpDisplay *gdisp); +GimpDisplay * gimp_display_get_by_ID (Gimp *gimp, + gint ID); -void gimp_display_reconnect (GimpDisplay *gdisp, - GimpImage *gimage); +void gimp_display_reconnect (GimpDisplay *gdisp, + GimpImage *gimage); -void gimp_display_add_update_area (GimpDisplay *gdisp, - gint x, - gint y, - gint w, - gint h); +void gimp_display_update_area (GimpDisplay *gdisp, + gboolean now, + gint x, + gint y, + gint w, + gint h); -void gimp_display_flush (GimpDisplay *gdisp); -void gimp_display_flush_now (GimpDisplay *gdisp); +void gimp_display_flush (GimpDisplay *gdisp); +void gimp_display_flush_now (GimpDisplay *gdisp); -void gimp_display_finish_draw (GimpDisplay *gdisp); - -gboolean gimp_display_coords_in_active_drawable (GimpDisplay *gdisp, - const GimpCoords *coords); #endif /* __GIMP_DISPLAY_H__ */ diff --git a/app/display/gimpdisplayshell-render.c b/app/display/gimpdisplayshell-render.c index d451ef2aa1..8171c2dc8a 100644 --- a/app/display/gimpdisplayshell-render.c +++ b/app/display/gimpdisplayshell-render.c @@ -33,7 +33,7 @@ #include "core/gimp.h" #include "core/gimpimage.h" #include "core/gimpimage-colormap.h" -#include "core/gimpimage-projection.h" +#include "core/gimpprojection.h" #include "gimpcanvas.h" #include "gimpdisplay.h" @@ -322,7 +322,7 @@ gimp_display_shell_render (GimpDisplayShell *shell, render_image_init_info (&info, shell, x, y, w, h); - image_type = gimp_image_projection_type (shell->gdisp->gimage); + image_type = gimp_projection_get_image_type (shell->gdisp->gimage->projection); if ((image_type < GIMP_RGB_IMAGE) || (image_type > GIMP_INDEXEDA_IMAGE)) { @@ -786,8 +786,10 @@ render_image_init_info (RenderInfo *info, gint w, gint h) { + GimpImage *gimage = shell->gdisp->gimage; + info->shell = shell; - info->src_tiles = gimp_image_projection (shell->gdisp->gimage); + info->src_tiles = gimp_projection_get_tiles (gimage->projection); info->x = x + shell->offset_x; info->y = y + shell->offset_y; info->w = w; @@ -796,7 +798,7 @@ render_image_init_info (RenderInfo *info, info->scaley = SCALEFACTOR_Y (shell); info->src_x = (gdouble) info->x / info->scalex; info->src_y = (gdouble) info->y / info->scaley; - info->src_bpp = gimp_image_projection_bytes (shell->gdisp->gimage); + info->src_bpp = gimp_projection_get_bytes (gimage->projection); info->dest = shell->render_buf; info->dest_bpp = 3; info->dest_bpl = info->dest_bpp * GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH; @@ -806,10 +808,10 @@ render_image_init_info (RenderInfo *info, info->x, info->scalex); info->alpha = NULL; - if (GIMP_IMAGE_TYPE_HAS_ALPHA (gimp_image_projection_type (shell->gdisp->gimage))) + if (GIMP_IMAGE_TYPE_HAS_ALPHA (gimp_projection_get_image_type (gimage->projection))) { info->alpha = - render_image_init_alpha (gimp_image_projection_opacity (shell->gdisp->gimage) * 255.999); + render_image_init_alpha (gimp_projection_get_opacity (gimage->projection) * 255.999); } } diff --git a/app/display/gimpdisplayshell.c b/app/display/gimpdisplayshell.c index d6c797cc44..d2f83af018 100644 --- a/app/display/gimpdisplayshell.c +++ b/app/display/gimpdisplayshell.c @@ -1255,10 +1255,29 @@ gimp_display_shell_flush (GimpDisplayShell *shell, { g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); + if (! shell->select) + { + g_warning ("%s: called unrealized", G_STRFUNC); + return; + } + gimp_display_shell_update_title (shell); if (now) - gdk_window_process_updates (shell->canvas->window, FALSE); + { + gdk_window_process_updates (shell->canvas->window, FALSE); + } + else + { + GimpContext *user_context; + + gimp_ui_manager_update (shell->menubar_manager, shell); + + user_context = gimp_get_user_context (shell->gdisp->gimage->gimp); + + if (shell->gdisp == gimp_context_get_display (user_context)) + gimp_ui_manager_update (shell->popup_manager, shell); + } } void diff --git a/app/gui/info-window.c b/app/gui/info-window.c index 0e8ac66bb0..02e9b83f6c 100644 --- a/app/gui/info-window.c +++ b/app/gui/info-window.c @@ -32,7 +32,7 @@ #include "core/gimpcontainer.h" #include "core/gimpcontext.h" #include "core/gimpimage.h" -#include "core/gimpimage-projection.h" +#include "core/gimpprojection.h" #include "core/gimptemplate.h" #include "core/gimpunit.h" @@ -402,7 +402,7 @@ info_window_update_extended (GimpDisplay *gdisp, } /* fill in color information */ - color = gimp_image_projection_get_color_at (gdisp->gimage, tx, ty); + color = gimp_projection_get_color_at (gdisp->gimage->projection, tx, ty); if (! color || (tx < 0.0 && ty < 0.0)) { @@ -414,7 +414,7 @@ info_window_update_extended (GimpDisplay *gdisp, GimpImageType sample_type; GimpRGB rgb; - sample_type = gimp_image_projection_type (gdisp->gimage); + sample_type = gimp_projection_get_image_type (gdisp->gimage->projection); gimp_rgba_set_uchar (&rgb, color[RED_PIX], diff --git a/app/tools/gimpbrushtool.c b/app/tools/gimpbrushtool.c index 3fef11da88..c34c8c7d3f 100644 --- a/app/tools/gimpbrushtool.c +++ b/app/tools/gimpbrushtool.c @@ -35,6 +35,7 @@ #include "core/gimpdrawable.h" #include "core/gimpimage.h" #include "core/gimppaintinfo.h" +#include "core/gimpprojection.h" #include "core/gimptoolinfo.h" #include "core/gimpunit.h" @@ -461,6 +462,7 @@ gimp_paint_tool_button_press (GimpTool *tool, gimp_paint_core_paint (core, drawable, paint_options, MOTION_PAINT, time); } + gimp_projection_flush_now (gdisp->gimage->projection); gimp_display_flush_now (gdisp); gimp_draw_tool_start (draw_tool, gdisp); @@ -541,6 +543,7 @@ gimp_paint_tool_motion (GimpTool *tool, gimp_paint_core_interpolate (core, drawable, paint_options, time); + gimp_projection_flush_now (gdisp->gimage->projection); gimp_display_flush_now (gdisp); paint_tool->brush_x = coords->x; diff --git a/app/tools/gimpbucketfilltool.c b/app/tools/gimpbucketfilltool.c index aa96b98121..05a8b915f8 100644 --- a/app/tools/gimpbucketfilltool.c +++ b/app/tools/gimpbucketfilltool.c @@ -265,7 +265,7 @@ gimp_bucket_fill_tool_cursor_update (GimpTool *tool, options = GIMP_BUCKET_FILL_OPTIONS (tool->tool_info->tool_options); - if (gimp_display_coords_in_active_drawable (gdisp, coords)) + if (gimp_image_coords_in_active_drawable (gdisp->gimage, coords)) { GimpChannel *selection = gimp_image_get_mask (gdisp->gimage); diff --git a/app/tools/gimpbycolorselecttool.c b/app/tools/gimpbycolorselecttool.c index 4f99567c89..8d0e6a7420 100644 --- a/app/tools/gimpbycolorselecttool.c +++ b/app/tools/gimpbycolorselecttool.c @@ -28,7 +28,7 @@ #include "core/gimpchannel-select.h" #include "core/gimpdrawable.h" #include "core/gimpimage.h" -#include "core/gimpimage-projection.h" +#include "core/gimpprojection.h" #include "core/gimptoolinfo.h" #include "widgets/gimphelp-ids.h" @@ -207,15 +207,15 @@ gimp_by_color_select_tool_button_release (GimpTool *tool, { if (by_color_sel->x >= 0 && by_color_sel->y >= 0 && - by_color_sel->x < gimp_item_width (GIMP_ITEM (drawable)) && + by_color_sel->x < gimp_item_width (GIMP_ITEM (drawable)) && by_color_sel->y < gimp_item_height (GIMP_ITEM (drawable))) { /* Get the start color */ if (options->sample_merged) { - if (!(col = gimp_image_projection_get_color_at (gdisp->gimage, - by_color_sel->x, - by_color_sel->y))) + if (!(col = gimp_projection_get_color_at (gdisp->gimage->projection, + by_color_sel->x, + by_color_sel->y))) return; } else diff --git a/app/tools/gimpclonetool.c b/app/tools/gimpclonetool.c index 3f4a2ec2ca..114de58ef9 100644 --- a/app/tools/gimpclonetool.c +++ b/app/tools/gimpclonetool.c @@ -189,7 +189,7 @@ gimp_clone_tool_cursor_update (GimpTool *tool, options = (GimpCloneOptions *) tool->tool_info->tool_options; - if (gimp_display_coords_in_active_drawable (gdisp, coords)) + if (gimp_image_coords_in_active_drawable (gdisp->gimage, coords)) { GimpChannel *selection = gimp_image_get_mask (gdisp->gimage); diff --git a/app/tools/gimpcolortool.c b/app/tools/gimpcolortool.c index 8322f886ec..5ae33e8cff 100644 --- a/app/tools/gimpcolortool.c +++ b/app/tools/gimpcolortool.c @@ -268,7 +268,7 @@ gimp_color_tool_cursor_update (GimpTool *tool, coords->y > 0 && coords->y < gdisp->gimage->height && (color_tool->options->sample_merged || - gimp_display_coords_in_active_drawable (gdisp, coords))) + gimp_image_coords_in_active_drawable (gdisp->gimage, coords))) { cursor = GIMP_CURSOR_COLOR_PICKER; } diff --git a/app/tools/gimpeditselectiontool.c b/app/tools/gimpeditselectiontool.c index 8b1d86941d..57eb2e0f77 100644 --- a/app/tools/gimpeditselectiontool.c +++ b/app/tools/gimpeditselectiontool.c @@ -39,6 +39,7 @@ #include "core/gimplayer.h" #include "core/gimplayermask.h" #include "core/gimplayer-floating-sel.h" +#include "core/gimpprojection.h" #include "core/gimpselection.h" #include "core/gimpundostack.h" @@ -742,7 +743,7 @@ gimp_edit_selection_tool_motion (GimpTool *tool, } } - gimp_display_flush (gdisp); + gimp_projection_flush (gdisp->gimage->projection); } /********************************************************************/ /********************************************************************/ diff --git a/app/tools/gimpfliptool.c b/app/tools/gimpfliptool.c index c6b990df14..b56cc1278a 100644 --- a/app/tools/gimpfliptool.c +++ b/app/tools/gimpfliptool.c @@ -203,7 +203,7 @@ gimp_flip_tool_cursor_update (GimpTool *tool, options = GIMP_FLIP_OPTIONS (tool->tool_info->tool_options); - if (gimp_display_coords_in_active_drawable (gdisp, coords)) + if (gimp_image_coords_in_active_drawable (gdisp->gimage, coords)) { GimpChannel *selection = gimp_image_get_mask (gdisp->gimage); diff --git a/app/tools/gimpimagemaptool.c b/app/tools/gimpimagemaptool.c index 34fcd04e3b..ca99627eea 100644 --- a/app/tools/gimpimagemaptool.c +++ b/app/tools/gimpimagemaptool.c @@ -34,6 +34,7 @@ #include "core/gimpimage.h" #include "core/gimpimage-pick-color.h" #include "core/gimpimagemap.h" +#include "core/gimpprojection.h" #include "core/gimptoolinfo.h" #include "widgets/gimppropwidgets.h" @@ -394,6 +395,7 @@ gimp_image_map_tool_flush (GimpImageMap *image_map, { GimpTool *tool = GIMP_TOOL (image_map_tool); + gimp_projection_flush_now (tool->gdisp->gimage->projection); gimp_display_flush_now (tool->gdisp); } diff --git a/app/tools/gimpiscissorstool.c b/app/tools/gimpiscissorstool.c index 2696661d9a..f8804084ef 100644 --- a/app/tools/gimpiscissorstool.c +++ b/app/tools/gimpiscissorstool.c @@ -66,7 +66,7 @@ #include "core/gimpchannel.h" #include "core/gimpchannel-select.h" #include "core/gimpimage.h" -#include "core/gimpimage-projection.h" +#include "core/gimpprojection.h" #include "core/gimpscanconvert.h" #include "core/gimptoolinfo.h" @@ -1732,7 +1732,7 @@ gradmap_tile_validate (TileManager *tm, dh = tile_eheight (tile); /* get corresponding tile in the gimage */ - srctile = tile_manager_get_tile (gimp_image_projection (gimage), + srctile = tile_manager_get_tile (gimp_projection_get_tiles (gimage->projection), x, y, TRUE, FALSE); if (!srctile) return; @@ -1742,7 +1742,7 @@ gradmap_tile_validate (TileManager *tm, srcPR.w = MIN (dw, sw); srcPR.h = MIN (dh, sh); - srcPR.bytes = gimp_image_projection_bytes (gimage); + srcPR.bytes = gimp_projection_get_bytes (gimage->projection); srcPR.data = tile_data_pointer (srctile, 0, 0); srcPR.rowstride = srcPR.w * srcPR.bytes; diff --git a/app/tools/gimppainttool.c b/app/tools/gimppainttool.c index 3fef11da88..c34c8c7d3f 100644 --- a/app/tools/gimppainttool.c +++ b/app/tools/gimppainttool.c @@ -35,6 +35,7 @@ #include "core/gimpdrawable.h" #include "core/gimpimage.h" #include "core/gimppaintinfo.h" +#include "core/gimpprojection.h" #include "core/gimptoolinfo.h" #include "core/gimpunit.h" @@ -461,6 +462,7 @@ gimp_paint_tool_button_press (GimpTool *tool, gimp_paint_core_paint (core, drawable, paint_options, MOTION_PAINT, time); } + gimp_projection_flush_now (gdisp->gimage->projection); gimp_display_flush_now (gdisp); gimp_draw_tool_start (draw_tool, gdisp); @@ -541,6 +543,7 @@ gimp_paint_tool_motion (GimpTool *tool, gimp_paint_core_interpolate (core, drawable, paint_options, time); + gimp_projection_flush_now (gdisp->gimage->projection); gimp_display_flush_now (gdisp); paint_tool->brush_x = coords->x; diff --git a/app/tools/gimpselectiontool.c b/app/tools/gimpselectiontool.c index fe08d9a232..6502461aa5 100644 --- a/app/tools/gimpselectiontool.c +++ b/app/tools/gimpselectiontool.c @@ -121,9 +121,7 @@ gimp_selection_tool_modifier_key (GimpTool *tool, if (key == GDK_SHIFT_MASK || key == GDK_CONTROL_MASK) { - SelectOps button_op; - - button_op = options->operation; + SelectOps button_op = options->operation; if (press) { diff --git a/app/tools/gimpsourcetool.c b/app/tools/gimpsourcetool.c index 3f4a2ec2ca..114de58ef9 100644 --- a/app/tools/gimpsourcetool.c +++ b/app/tools/gimpsourcetool.c @@ -189,7 +189,7 @@ gimp_clone_tool_cursor_update (GimpTool *tool, options = (GimpCloneOptions *) tool->tool_info->tool_options; - if (gimp_display_coords_in_active_drawable (gdisp, coords)) + if (gimp_image_coords_in_active_drawable (gdisp->gimage, coords)) { GimpChannel *selection = gimp_image_get_mask (gdisp->gimage); diff --git a/app/tools/gimptransformtool.c b/app/tools/gimptransformtool.c index fb2add6e54..4f80a6de66 100644 --- a/app/tools/gimptransformtool.c +++ b/app/tools/gimptransformtool.c @@ -460,6 +460,9 @@ gimp_transform_tool_button_release (GimpTool *tool, { gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool)); + /* get rid of preview artifacts left outside the drawable's area */ + gimp_transform_tool_expose_preview (tr_tool); + /* Restore the previous transformation info */ for (i = 0; i < TRAN_INFO_SIZE; i++) tr_tool->trans_info[i] = tr_tool->old_trans_info[i]; @@ -658,7 +661,8 @@ gimp_transform_tool_cursor_update (GimpTool *tool, { cursor = GIMP_CURSOR_BAD; } - else if (gimp_display_coords_in_active_drawable (gdisp, coords)) + else if (gimp_image_coords_in_active_drawable (gdisp->gimage, + coords)) { if (gimp_channel_is_empty (selection) || gimp_channel_value (selection, coords->x, coords->y)) diff --git a/app/widgets/gimpselectioneditor.c b/app/widgets/gimpselectioneditor.c index bca8e5cf2b..5553723e32 100644 --- a/app/widgets/gimpselectioneditor.c +++ b/app/widgets/gimpselectioneditor.c @@ -36,7 +36,7 @@ #include "core/gimpchannel-select.h" #include "core/gimpcontainer.h" #include "core/gimpimage.h" -#include "core/gimpimage-projection.h" +#include "core/gimpprojection.h" #include "core/gimpselection.h" #include "core/gimptoolinfo.h" @@ -316,7 +316,8 @@ gimp_selection_preview_button_press (GtkWidget *widget, y >= image_editor->gimage->height) return TRUE; - col = gimp_image_projection_get_color_at (image_editor->gimage, x, y); + col = gimp_projection_get_color_at (image_editor->gimage->projection, + x, y); } else {