*** empty log message ***

This commit is contained in:
Michael Natterer 2004-07-13 16:36:29 +00:00
parent f1706f09e1
commit c5ec0d4f70
48 changed files with 1134 additions and 2700 deletions

View File

@ -1,3 +1,62 @@
2004-07-13 Michael Natterer <mitch@gimp.org>
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 <sven@gimp.org>
* 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 <shlomif@iglu.org.il>
* plug-ins/gimpressionist/presets.c: fixed bug #147483 (gimpressionist

View File

@ -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 \

View File

@ -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;

View File

@ -18,11 +18,11 @@
#include "config.h"
#include <gtk/gtk.h>
#include <glib-object.h>
#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)
{

View File

@ -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__ */

View File

@ -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);

View File

@ -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)

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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
{

View File

@ -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 <glib-object.h>
#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);
}
}

View File

@ -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__ */

View File

@ -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);

View File

@ -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)
{

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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__ */

File diff suppressed because it is too large Load Diff

View File

@ -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__ */

View File

@ -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],

View File

@ -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 \

View File

@ -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 <gtk/gtk.h>
#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;
}

View File

@ -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__ */

View File

@ -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,

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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__ */

View File

@ -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);
}
}

View File

@ -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

View File

@ -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],

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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);
}
/********************************************************************/
/********************************************************************/

View File

@ -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);

View File

@ -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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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)
{

View File

@ -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);

View File

@ -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))

View File

@ -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
{