To optimize duplicate and/or wrong image updates away, introduced new

2003-09-06  Michael Natterer  <mitch@gimp.org>

	To optimize duplicate and/or wrong image updates away, introduced
	new policy that a child object must never explicitly update or
	invalidate its parent object (just like the GUI is not updated
	explicitly by the core):

	* app/core/gimpdrawable.[ch]: added new signal
	GimpDrawable::update(). Never update or invalidate the image when
	the drawable is updated or invalidated.

	(gimp_drawable_set_visible): don't gimp_drawable_update() the
	drawable since its pixels have not changed.

	* app/core/gimpimage.[ch]: connect to the "add" and "remove"
	signals of the layers and channels containers. Also connect to the
	"update" and "visibility_changed" signals of all drawables in
	these containers (optimizes away updates issued by drawables which
	are not yet added to the image and updates of the selection
	mask). Also, don't propagate updates to the image if the emitting
	drawable is invisible (optimizes away updates issued by invisible
	drawables).

	(gimp_image_add_layer,channel)
	(gimp_image_remove_layer,channel): don't update the image since
	that's done by our "add" and "remove" handlers now.

	(gimp_image_position_layer,channel): update just the image, not
	the drawable since its pixels have not changed.

	(gimp_image_real_colormap_changed)
	(gimp_image_set_component_visible): always call
	gimp_image_update() *and* gimp_viewable_invalidate_preview() to
	get everything updated, since update and invalidate of images are
	not connected.

	* app/core/gimpimage-undo-push.c (undo_pop_layer,channel): don't
	update the drawable since (a) its pixels don't change and (b) the
	image updates itself upon adding/removing now.

	(undo_pop_layer_mod): replaced gimp_image_update() by
	gimp_drawable_update() (just for consistency with other similar
	functions).

	* app/core/gimplayer.c: connect to "update" of the layer mask and
	issue updates on the layer if the mask update has any effect on
	the projection.
	(gimp_layer_create_mask): don't set the mask's offsets here since
	they may be different when we later add the mask to the layer.

	* app/core/gimplayermask.c (gimp_layer_mask_set_layer): set the
	mask offsets here instead.

	* app/core/gimpchannel.c (gimp_channel_translate): update the
	channel even if push_undo == FALSE.

	* app/paint/gimppaintcore.c (gimp_paint_core_finish)
	* app/tools/gimpinktool.c (ink_finish): invalidate both the
	drawable and the image preview since invalidating the drawable
	doesn't invalidate the image any more.

	* app/text/gimptextlayer.c (gimp_text_layer_render_now): also
	update the new extents of the text layer, not only the old one.

	(gimp_text_layer_render_layout): don't update the drawable since
	gimp_drawable_fill() already updated it.
This commit is contained in:
Michael Natterer 2003-09-06 20:06:53 +00:00 committed by Michael Natterer
parent 99dba1ca01
commit 7a5f914866
13 changed files with 410 additions and 180 deletions

View File

@ -1,3 +1,70 @@
2003-09-06 Michael Natterer <mitch@gimp.org>
To optimize duplicate and/or wrong image updates away, introduced
new policy that a child object must never explicitly update or
invalidate its parent object (just like the GUI is not updated
explicitly by the core):
* app/core/gimpdrawable.[ch]: added new signal
GimpDrawable::update(). Never update or invalidate the image when
the drawable is updated or invalidated.
(gimp_drawable_set_visible): don't gimp_drawable_update() the
drawable since its pixels have not changed.
* app/core/gimpimage.[ch]: connect to the "add" and "remove"
signals of the layers and channels containers. Also connect to the
"update" and "visibility_changed" signals of all drawables in
these containers (optimizes away updates issued by drawables which
are not yet added to the image and updates of the selection
mask). Also, don't propagate updates to the image if the emitting
drawable is invisible (optimizes away updates issued by invisible
drawables).
(gimp_image_add_layer,channel)
(gimp_image_remove_layer,channel): don't update the image since
that's done by our "add" and "remove" handlers now.
(gimp_image_position_layer,channel): update just the image, not
the drawable since its pixels have not changed.
(gimp_image_real_colormap_changed)
(gimp_image_set_component_visible): always call
gimp_image_update() *and* gimp_viewable_invalidate_preview() to
get everything updated, since update and invalidate of images are
not connected.
* app/core/gimpimage-undo-push.c (undo_pop_layer,channel): don't
update the drawable since (a) its pixels don't change and (b) the
image updates itself upon adding/removing now.
(undo_pop_layer_mod): replaced gimp_image_update() by
gimp_drawable_update() (just for consistency with other similar
functions).
* app/core/gimplayer.c: connect to "update" of the layer mask and
issue updates on the layer if the mask update has any effect on
the projection.
(gimp_layer_create_mask): don't set the mask's offsets here since
they may be different when we later add the mask to the layer.
* app/core/gimplayermask.c (gimp_layer_mask_set_layer): set the
mask offsets here instead.
* app/core/gimpchannel.c (gimp_channel_translate): update the
channel even if push_undo == FALSE.
* app/paint/gimppaintcore.c (gimp_paint_core_finish)
* app/tools/gimpinktool.c (ink_finish): invalidate both the
drawable and the image preview since invalidating the drawable
doesn't invalidate the image any more.
* app/text/gimptextlayer.c (gimp_text_layer_render_now): also
update the new extents of the text layer, not only the old one.
(gimp_text_layer_render_layout): don't update the drawable since
gimp_drawable_fill() already updated it.
2003-09-06 Sven Neumann <sven@gimp.org>
* app/vectors/gimpbezierstroke.c

View File

@ -362,19 +362,15 @@ gimp_channel_translate (GimpItem *item,
height = y2 - y1;
if (push_undo)
{
gimp_channel_push_undo (channel,
GIMP_CHANNEL_GET_CLASS (channel)->translate_desc);
/* update the old area */
gimp_drawable_update (GIMP_DRAWABLE (item),
x1, y1,
x2 - x1, y2 - y1);
}
gimp_channel_push_undo (channel,
GIMP_CHANNEL_GET_CLASS (channel)->translate_desc);
else
{
gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (channel));
}
gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (channel));
/* update the old area */
gimp_drawable_update (GIMP_DRAWABLE (item),
x1, y1,
x2 - x1, y2 - y1);
/* make sure width and height are non-zero */
if (width != 0 && height != 0)
@ -429,16 +425,11 @@ gimp_channel_translate (GimpItem *item,
channel->y2 = y2;
}
if (push_undo)
{
/* update the new area */
gimp_drawable_update (GIMP_DRAWABLE (item),
channel->x1, channel->y1,
channel->x2 - channel->x1,
channel->y2 - channel->y1);
gimp_viewable_size_changed (GIMP_VIEWABLE (item));
}
/* update the new area */
gimp_drawable_update (GIMP_DRAWABLE (item),
channel->x1, channel->y1,
channel->x2 - channel->x1,
channel->y2 - channel->y1);
}
static void

View File

@ -56,6 +56,7 @@
enum
{
UPDATE,
VISIBILITY_CHANGED,
ALPHA_CHANGED,
LAST_SIGNAL
@ -105,6 +106,12 @@ static void gimp_drawable_transform (GimpItem *item,
GimpProgressFunc progress_callback,
gpointer progress_data);
static void gimp_drawable_real_update (GimpDrawable *drawable,
gint x,
gint y,
gint width,
gint height);
/* private variables */
@ -156,6 +163,19 @@ gimp_drawable_class_init (GimpDrawableClass *klass)
parent_class = g_type_class_peek_parent (klass);
gimp_drawable_signals[UPDATE] =
g_signal_new ("update",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GimpDrawableClass, update),
NULL, NULL,
gimp_marshal_VOID__INT_INT_INT_INT,
G_TYPE_NONE, 4,
G_TYPE_INT,
G_TYPE_INT,
G_TYPE_INT,
G_TYPE_INT);
gimp_drawable_signals[VISIBILITY_CHANGED] =
g_signal_new ("visibility_changed",
G_TYPE_FROM_CLASS (klass),
@ -190,6 +210,7 @@ gimp_drawable_class_init (GimpDrawableClass *klass)
item_class->rotate = gimp_drawable_rotate;
item_class->transform = gimp_drawable_transform;
klass->update = gimp_drawable_real_update;
klass->visibility_changed = NULL;
klass->alpha_changed = NULL;
klass->invalidate_boundary = NULL;
@ -247,7 +268,6 @@ static void
gimp_drawable_invalidate_preview (GimpViewable *viewable)
{
GimpDrawable *drawable;
GimpImage *gimage;
if (GIMP_VIEWABLE_CLASS (parent_class)->invalidate_preview)
GIMP_VIEWABLE_CLASS (parent_class)->invalidate_preview (viewable);
@ -258,11 +278,6 @@ gimp_drawable_invalidate_preview (GimpViewable *viewable)
if (drawable->preview_cache)
gimp_preview_cache_invalidate (&drawable->preview_cache);
gimage = gimp_item_get_image (GIMP_ITEM (drawable));
if (gimage)
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (gimage));
}
static GimpItem *
@ -559,6 +574,16 @@ gimp_drawable_transform (GimpItem *item,
}
}
static void
gimp_drawable_real_update (GimpDrawable *drawable,
gint x,
gint y,
gint width,
gint height)
{
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (drawable));
}
void
gimp_drawable_configure (GimpDrawable *drawable,
GimpImage *gimage,
@ -595,28 +620,13 @@ void
gimp_drawable_update (GimpDrawable *drawable,
gint x,
gint y,
gint w,
gint h)
gint width,
gint height)
{
GimpItem *item;
GimpImage *gimage;
gint offset_x;
gint offset_y;
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
item = GIMP_ITEM (drawable);
gimage = gimp_item_get_image (item);
g_return_if_fail (gimage != NULL);
gimp_item_offsets (item, &offset_x, &offset_y);
x += offset_x;
y += offset_y;
gimp_image_update (gimage, x, y, w, h);
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (drawable));
g_signal_emit (drawable, gimp_drawable_signals[UPDATE], 0,
x, y, width, height);
}
void
@ -947,8 +957,6 @@ gimp_drawable_set_visible (GimpDrawable *drawable,
drawable->visible = visible ? TRUE : FALSE;
g_signal_emit (drawable, gimp_drawable_signals[VISIBILITY_CHANGED], 0);
gimp_drawable_update (drawable, 0, 0, item->width, item->height);
}
}

View File

@ -54,6 +54,11 @@ struct _GimpDrawableClass
GimpItemClass parent_class;
/* signals */
void (* update) (GimpDrawable *drawable,
gint x,
gint y,
gint width,
gint height);
void (* visibility_changed) (GimpDrawable *drawable);
void (* alpha_changed) (GimpDrawable *drawable);
@ -78,8 +83,8 @@ void gimp_drawable_configure (GimpDrawable *drawable,
void gimp_drawable_update (GimpDrawable *drawable,
gint x,
gint y,
gint w,
gint h);
gint width,
gint height);
void gimp_drawable_push_undo (GimpDrawable *drawable,
const gchar *undo_desc,

View File

@ -1563,11 +1563,6 @@ undo_pop_layer (GimpUndo *undo,
gimp_image_floating_selection_changed (undo->gimage);
}
gimp_drawable_update (GIMP_DRAWABLE (layer),
0, 0,
GIMP_ITEM (layer)->width,
GIMP_ITEM (layer)->height);
if (gimp_container_num_children (undo->gimage->layers) == 1 &&
! gimp_drawable_has_alpha (GIMP_LIST (undo->gimage->layers)->list->data))
{
@ -1607,11 +1602,6 @@ undo_pop_layer (GimpUndo *undo,
if (gimp_layer_is_floating_sel (layer))
gimp_image_floating_selection_changed (undo->gimage);
gimp_drawable_update (GIMP_DRAWABLE (layer),
0, 0,
GIMP_ITEM (layer)->width,
GIMP_ITEM (layer)->height);
}
return TRUE;
@ -1699,11 +1689,10 @@ undo_pop_layer_mod (GimpUndo *undo,
layer = GIMP_LAYER (GIMP_ITEM_UNDO (undo)->item);
/* Issue the first update */
gimp_image_update (undo->gimage,
GIMP_ITEM (layer)->offset_x,
GIMP_ITEM (layer)->offset_y,
GIMP_ITEM (layer)->width,
GIMP_ITEM (layer)->height);
gimp_drawable_update (GIMP_DRAWABLE (layer),
0, 0,
GIMP_ITEM (layer)->width,
GIMP_ITEM (layer)->height);
tiles = lmu->tiles;
layer_type = lmu->type;
@ -2237,12 +2226,6 @@ undo_pop_channel (GimpUndo *undo,
else
gimp_image_unset_active_channel (undo->gimage);
}
/* update the area */
gimp_drawable_update (GIMP_DRAWABLE (channel),
0, 0,
GIMP_ITEM (channel)->width,
GIMP_ITEM (channel)->height);
}
else
{
@ -2257,12 +2240,6 @@ undo_pop_channel (GimpUndo *undo,
gimp_container_insert (undo->gimage->channels,
GIMP_OBJECT (channel), cu->prev_position);
gimp_image_set_active_channel (undo->gimage, channel);
/* update the area */
gimp_drawable_update (GIMP_DRAWABLE (channel),
0, 0,
GIMP_ITEM (channel)->width,
GIMP_ITEM (channel)->height);
}
return TRUE;

View File

@ -118,6 +118,21 @@ static gchar * gimp_image_get_description (GimpViewable *viewable,
static void gimp_image_real_colormap_changed (GimpImage *gimage,
gint ncol);
static void gimp_image_drawable_update (GimpDrawable *drawable,
gint x,
gint y,
gint width,
gint height,
GimpImage *gimage);
static void gimp_image_drawable_visibility (GimpDrawable *drawable,
GimpImage *gimage);
static void gimp_image_drawable_add (GimpContainer *container,
GimpDrawable *drawable,
GimpImage *gimage);
static void gimp_image_drawable_remove (GimpContainer *container,
GimpDrawable *drawable,
GimpImage *gimage);
static void gimp_image_get_active_components (const GimpImage *gimage,
const GimpDrawable *drawable,
gboolean *active);
@ -478,6 +493,38 @@ gimp_image_init (GimpImage *gimage)
GIMP_CONTAINER_POLICY_STRONG);
gimage->layer_stack = NULL;
gimage->layer_update_handler =
gimp_container_add_handler (gimage->layers, "update",
G_CALLBACK (gimp_image_drawable_update),
gimage);
gimage->channel_update_handler =
gimp_container_add_handler (gimage->channels, "update",
G_CALLBACK (gimp_image_drawable_update),
gimage);
gimage->layer_visible_handler =
gimp_container_add_handler (gimage->layers, "visibility_changed",
G_CALLBACK (gimp_image_drawable_visibility),
gimage);
gimage->channel_visible_handler =
gimp_container_add_handler (gimage->channels, "visibility_changed",
G_CALLBACK (gimp_image_drawable_visibility),
gimage);
g_signal_connect (gimage->layers, "add",
G_CALLBACK (gimp_image_drawable_add),
gimage);
g_signal_connect (gimage->channels, "add",
G_CALLBACK (gimp_image_drawable_add),
gimage);
g_signal_connect (gimage->layers, "remove",
G_CALLBACK (gimp_image_drawable_remove),
gimage);
g_signal_connect (gimage->channels, "remove",
G_CALLBACK (gimp_image_drawable_remove),
gimage);
gimage->active_layer = NULL;
gimage->active_channel = NULL;
gimage->active_vectors = NULL;
@ -507,21 +554,41 @@ gimp_image_init (GimpImage *gimage)
static void
gimp_image_dispose (GObject *object)
{
GimpImage *gimage;
gimage = GIMP_IMAGE (object);
GimpImage *gimage = GIMP_IMAGE (object);
gimp_image_undo_free (gimage);
gimp_container_remove_handler (gimage->layers,
gimage->layer_update_handler);
gimp_container_remove_handler (gimage->channels,
gimage->channel_update_handler);
gimp_container_remove_handler (gimage->layers,
gimage->layer_visible_handler);
gimp_container_remove_handler (gimage->channels,
gimage->channel_visible_handler);
g_signal_handlers_disconnect_by_func (gimage->layers,
gimp_image_drawable_add,
gimage);
g_signal_handlers_disconnect_by_func (gimage->channels,
gimp_image_drawable_add,
gimage);
g_signal_handlers_disconnect_by_func (gimage->layers,
gimp_image_drawable_remove,
gimage);
g_signal_handlers_disconnect_by_func (gimage->channels,
gimp_image_drawable_remove,
gimage);
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
gimp_image_finalize (GObject *object)
{
GimpImage *gimage;
gimage = GIMP_IMAGE (object);
GimpImage *gimage = GIMP_IMAGE (object);
if (gimage->gimp && gimage->gimp->image_table)
{
@ -763,11 +830,71 @@ gimp_image_real_colormap_changed (GimpImage *gimage,
{
/* A colormap alteration affects the whole image */
gimp_image_update (gimage, 0, 0, gimage->width, gimage->height);
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (gimage));
gimp_image_color_hash_invalidate (gimage, ncol);
}
}
static void
gimp_image_drawable_update (GimpDrawable *drawable,
gint x,
gint y,
gint width,
gint height,
GimpImage *gimage)
{
if (gimp_drawable_get_visible (drawable))
{
gint offset_x;
gint offset_y;
gimp_item_offsets (GIMP_ITEM (drawable), &offset_x, &offset_y);
x += offset_x;
y += offset_y;
gimp_image_update (gimage, x, y, width, height);
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (gimage));
}
}
static void
gimp_image_drawable_visibility (GimpDrawable *drawable,
GimpImage *gimage)
{
GimpItem *item;
gint offset_x;
gint offset_y;
item = GIMP_ITEM (drawable);
gimp_item_offsets (item, &offset_x, &offset_y);
gimp_image_update (gimage,
offset_x, offset_y,
gimp_item_width (item),
gimp_item_height (item));
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (gimage));
}
static void
gimp_image_drawable_add (GimpContainer *container,
GimpDrawable *drawable,
GimpImage *gimage)
{
if (gimp_drawable_get_visible (drawable))
gimp_image_drawable_visibility (drawable, gimage);
}
static void
gimp_image_drawable_remove (GimpContainer *container,
GimpDrawable *drawable,
GimpImage *gimage)
{
if (gimp_drawable_get_visible (drawable))
gimp_image_drawable_visibility (drawable, gimage);
}
static void
gimp_image_get_active_components (const GimpImage *gimage,
const GimpDrawable *drawable,
@ -1236,6 +1363,7 @@ gimp_image_set_component_visible (GimpImage *gimage,
channel);
gimp_image_update (gimage, 0, 0, gimage->width, gimage->height);
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (gimage));
}
}
@ -1820,8 +1948,6 @@ gimp_image_replace_image (GimpImage *gimage,
gint x1, y1, x2, y2;
gint offset_x, offset_y;
PixelRegion src1PR, destPR;
PixelRegion mask2PR, tempPR;
guchar *temp_data;
CombinationMode operation;
gboolean active_components[MAX_CHANNELS];
@ -1887,7 +2013,9 @@ gimp_image_replace_image (GimpImage *gimage,
if (mask)
{
int mx, my;
PixelRegion mask2PR, tempPR;
guchar *temp_data;
gint mx, my;
/* configure the mask pixel region
* don't use x1 and y1 because they are in layer
@ -1902,30 +2030,29 @@ gimp_image_replace_image (GimpImage *gimage,
(x2 - x1), (y2 - y1),
FALSE);
tempPR.bytes = 1;
tempPR.x = 0;
tempPR.y = 0;
tempPR.w = x2 - x1;
tempPR.h = y2 - y1;
tempPR.bytes = 1;
tempPR.x = 0;
tempPR.y = 0;
tempPR.w = x2 - x1;
tempPR.h = y2 - y1;
tempPR.rowstride = tempPR.w * tempPR.bytes;
temp_data = g_malloc (tempPR.h * tempPR.rowstride);
tempPR.data = temp_data;
tempPR.data = temp_data = g_malloc (tempPR.h * tempPR.rowstride);
copy_region (&mask2PR, &tempPR);
/* apparently, region operations can mutate some PR data. */
tempPR.x = 0;
tempPR.y = 0;
tempPR.w = x2 - x1;
tempPR.h = y2 - y1;
tempPR.x = 0;
tempPR.y = 0;
tempPR.w = x2 - x1;
tempPR.h = y2 - y1;
tempPR.data = temp_data;
apply_mask_to_region (&tempPR, maskPR, OPAQUE_OPACITY);
tempPR.x = 0;
tempPR.y = 0;
tempPR.w = x2 - x1;
tempPR.h = y2 - y1;
tempPR.x = 0;
tempPR.y = 0;
tempPR.w = x2 - x1;
tempPR.h = y2 - y1;
tempPR.data = temp_data;
combine_regions_replace (&src1PR, src2PR, &destPR, &tempPR, NULL,
@ -2569,12 +2696,6 @@ gimp_image_add_layer (GimpImage *gimage,
/* notify the layers dialog of the currently active layer */
gimp_image_set_active_layer (gimage, layer);
/* update the new layer's area */
gimp_drawable_update (GIMP_DRAWABLE (layer),
0, 0,
gimp_item_width (GIMP_ITEM (layer)),
gimp_item_height (GIMP_ITEM (layer)));
if (alpha_changed)
gimp_image_alpha_changed (gimage);
@ -2585,8 +2706,6 @@ void
gimp_image_remove_layer (GimpImage *gimage,
GimpLayer *layer)
{
gint x, y, w, h;
g_return_if_fail (GIMP_IS_IMAGE (gimage));
g_return_if_fail (GIMP_IS_LAYER (layer));
@ -2630,16 +2749,8 @@ gimp_image_remove_layer (GimpImage *gimage,
/* Send out REMOVED signal from layer */
gimp_item_removed (GIMP_ITEM (layer));
gimp_item_offsets (GIMP_ITEM (layer), &x, &y);
w = gimp_item_width (GIMP_ITEM (layer));
h = gimp_item_height (GIMP_ITEM (layer));
g_object_unref (layer);
gimp_image_update (gimage, x, y, w, h);
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (gimage));
if (gimp_container_num_children (gimage->layers) == 1 &&
! gimp_drawable_has_alpha (GIMP_LIST (gimage->layers)->list->data))
{
@ -2755,7 +2866,6 @@ gimp_image_position_layer (GimpImage *gimage,
gboolean push_undo,
const gchar *undo_desc)
{
gint off_x, off_y;
gint index;
gint num_layers;
@ -2800,14 +2910,18 @@ gimp_image_position_layer (GimpImage *gimage,
gimp_container_reorder (gimage->layers, GIMP_OBJECT (layer), new_index);
gimp_item_offsets (GIMP_ITEM (layer), &off_x, &off_y);
if (gimp_drawable_get_visible (GIMP_DRAWABLE (layer)))
{
gint off_x, off_y;
gimp_image_update (gimage,
off_x, off_y,
gimp_item_width (GIMP_ITEM (layer)),
gimp_item_height (GIMP_ITEM (layer)));
gimp_item_offsets (GIMP_ITEM (layer), &off_x, &off_y);
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (gimage));
gimp_image_update (gimage,
off_x, off_y,
gimp_item_width (GIMP_ITEM (layer)),
gimp_item_height (GIMP_ITEM (layer)));
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (gimage));
}
return TRUE;
}
@ -2867,13 +2981,6 @@ gimp_image_add_channel (GimpImage *gimage,
/* notify this gimage of the currently active channel */
gimp_image_set_active_channel (gimage, channel);
/* if channel is visible, update the image */
if (gimp_drawable_get_visible (GIMP_DRAWABLE (channel)))
gimp_drawable_update (GIMP_DRAWABLE (channel),
0, 0,
gimp_item_width (GIMP_ITEM (channel)),
gimp_item_height (GIMP_ITEM (channel)));
return TRUE;
}
@ -2916,10 +3023,6 @@ gimp_image_remove_channel (GimpImage *gimage,
}
g_object_unref (channel);
gimp_image_update (gimage, 0, 0, gimage->width, gimage->height);
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (gimage));
}
gboolean
@ -2971,7 +3074,7 @@ gimp_image_position_channel (GimpImage *gimage,
gboolean push_undo,
const gchar *undo_desc)
{
gint index;
gint index;
gint num_channels;
g_return_val_if_fail (GIMP_IS_IMAGE (gimage), FALSE);
@ -2995,10 +3098,18 @@ gimp_image_position_channel (GimpImage *gimage,
gimp_container_reorder (gimage->channels,
GIMP_OBJECT (channel), new_index);
gimp_drawable_update (GIMP_DRAWABLE (channel),
0, 0,
gimp_item_width (GIMP_ITEM (channel)),
gimp_item_height (GIMP_ITEM (channel)));
if (gimp_drawable_get_visible (GIMP_DRAWABLE (channel)))
{
gint off_x, off_y;
gimp_item_offsets (GIMP_ITEM (channel), &off_x, &off_y);
gimp_image_update (gimage,
off_x, off_y,
gimp_item_width (GIMP_ITEM (channel)),
gimp_item_height (GIMP_ITEM (channel)));
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (gimage));
}
return TRUE;
}

View File

@ -132,6 +132,11 @@ struct _GimpImage
GimpContainer *vectors; /* the list of vectors */
GSList *layer_stack; /* the layers in MRU order */
GQuark layer_update_handler;
GQuark channel_update_handler;
GQuark layer_visible_handler;
GQuark channel_visible_handler;
GimpLayer *active_layer; /* the active layer */
GimpChannel *active_channel; /* the active channel */
GimpVectors *active_vectors; /* the active vectors */

View File

@ -63,6 +63,7 @@ enum
static void gimp_layer_class_init (GimpLayerClass *klass);
static void gimp_layer_init (GimpLayer *layer);
static void gimp_layer_dispose (GObject *object);
static void gimp_layer_finalize (GObject *object);
static gsize gimp_layer_get_memsize (GimpObject *object,
@ -120,6 +121,13 @@ static void gimp_layer_transform_color (GimpImage *gimage,
GimpDrawable *drawable,
GimpImageBaseType type);
static void gimp_layer_layer_mask_update (GimpDrawable *layer_mask,
gint x,
gint y,
gint width,
gint height,
GimpLayer *layer);
static guint layer_signals[LAST_SIGNAL] = { 0 };
@ -207,6 +215,7 @@ gimp_layer_class_init (GimpLayerClass *klass)
gimp_marshal_VOID__VOID,
G_TYPE_NONE, 0);
object_class->dispose = gimp_layer_dispose;
object_class->finalize = gimp_layer_finalize;
gimp_object_class->get_memsize = gimp_layer_get_memsize;
@ -252,6 +261,19 @@ gimp_layer_init (GimpLayer *layer)
layer->fs.num_segs = 0;
}
static void
gimp_layer_dispose (GObject *object)
{
GimpLayer *layer = GIMP_LAYER (object);
if (layer->mask)
g_signal_handlers_disconnect_by_func (layer->mask,
gimp_layer_layer_mask_update,
layer);
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
gimp_layer_finalize (GObject *object)
{
@ -266,7 +288,8 @@ gimp_layer_finalize (GObject *object)
if (layer->fs.segs)
{
g_free (layer->fs.segs);
layer->fs.segs = NULL;
layer->fs.segs = NULL;
layer->fs.num_segs = 0;
}
/* free the floating selection if it exists */
@ -303,9 +326,7 @@ gimp_layer_get_memsize (GimpObject *object,
static void
gimp_layer_invalidate_preview (GimpViewable *viewable)
{
GimpLayer *layer;
layer = GIMP_LAYER (viewable);
GimpLayer *layer = GIMP_LAYER (viewable);
if (GIMP_VIEWABLE_CLASS (parent_class)->invalidate_preview)
GIMP_VIEWABLE_CLASS (parent_class)->invalidate_preview (viewable);
@ -749,9 +770,25 @@ gimp_layer_transform_color (GimpImage *gimage,
}
}
/**************************/
/* Function definitions */
/**************************/
static void
gimp_layer_layer_mask_update (GimpDrawable *drawable,
gint x,
gint y,
gint width,
gint height,
GimpLayer *layer)
{
GimpLayerMask *layer_mask = GIMP_LAYER_MASK (drawable);
if (layer_mask->apply_mask || layer_mask->show_mask)
{
gimp_drawable_update (GIMP_DRAWABLE (layer),
x, y, width, height);
}
}
/* public functions */
GimpLayer *
gimp_layer_new (GimpImage *gimage,
@ -906,15 +943,20 @@ gimp_layer_add_mask (GimpLayer *layer,
return NULL;
}
layer->mask = mask;
g_object_ref (layer->mask);
layer->mask = g_object_ref (mask);
gimp_layer_mask_set_layer (mask, layer);
gimp_drawable_update (GIMP_DRAWABLE (layer),
0, 0,
GIMP_ITEM (layer)->width,
GIMP_ITEM (layer)->height);
if (mask->apply_mask || mask->show_mask)
{
gimp_drawable_update (GIMP_DRAWABLE (layer),
0, 0,
GIMP_ITEM (layer)->width,
GIMP_ITEM (layer)->height);
}
g_signal_connect (mask, "update",
G_CALLBACK (gimp_layer_layer_mask_update),
layer);
if (push_undo)
gimp_image_undo_push_layer_mask_add (gimage, _("Add Layer Mask"),
@ -954,9 +996,6 @@ gimp_layer_create_mask (const GimpLayer *layer,
g_free (mask_name);
GIMP_ITEM (mask)->offset_x = item->offset_x;
GIMP_ITEM (mask)->offset_y = item->offset_y;
switch (add_mask_type)
{
case GIMP_ADD_WHITE_MASK:
@ -1126,10 +1165,9 @@ gimp_layer_apply_mask (GimpLayer *layer,
}
/* check if applying the mask changes the projection */
if ((mode == GIMP_MASK_APPLY && (! layer->mask->apply_mask ||
layer->mask->show_mask)) ||
(mode == GIMP_MASK_DISCARD && (layer->mask->apply_mask ||
layer->mask->show_mask)))
if (layer->mask->show_mask ||
(mode == GIMP_MASK_APPLY && ! layer->mask->apply_mask) ||
(mode == GIMP_MASK_DISCARD && layer->mask->apply_mask))
{
view_changed = TRUE;
}
@ -1158,6 +1196,10 @@ gimp_layer_apply_mask (GimpLayer *layer,
apply_mask_to_region (&srcPR, &maskPR, OPAQUE_OPACITY);
}
g_signal_handlers_disconnect_by_func (layer->mask,
gimp_layer_layer_mask_update,
layer);
g_object_unref (layer->mask);
layer->mask = NULL;

View File

@ -170,7 +170,7 @@ gimp_layer_mask_new (GimpImage *gimage,
layer_mask = g_object_new (GIMP_TYPE_LAYER_MASK, NULL);
gimp_drawable_configure (GIMP_DRAWABLE (layer_mask),
gimp_drawable_configure (GIMP_DRAWABLE (layer_mask),
gimage,
0, 0, width, height,
GIMP_GRAY_IMAGE, name);
@ -192,9 +192,15 @@ gimp_layer_mask_set_layer (GimpLayerMask *layer_mask,
GimpLayer *layer)
{
g_return_if_fail (GIMP_IS_LAYER_MASK (layer_mask));
g_return_if_fail (! layer || GIMP_IS_LAYER (layer));
g_return_if_fail (layer == NULL || GIMP_IS_LAYER (layer));
layer_mask->layer = layer;
if (layer)
{
GIMP_ITEM (layer_mask)->offset_x = GIMP_ITEM (layer)->offset_x;
GIMP_ITEM (layer_mask)->offset_y = GIMP_ITEM (layer)->offset_y;
}
}
GimpLayer *

View File

@ -704,6 +704,8 @@ static void
ink_finish (GimpInkTool *ink_tool,
GimpDrawable *drawable)
{
GimpImage *gimage;
gimp_drawable_push_undo (drawable, _("Ink"),
ink_tool->x1, ink_tool->y1,
ink_tool->x2, ink_tool->y2,
@ -712,10 +714,13 @@ ink_finish (GimpInkTool *ink_tool,
tile_manager_unref (undo_tiles);
undo_tiles = NULL;
/* invalidate the drawable--have to do it here, because
gimage = gimp_item_get_image (GIMP_ITEM (drawable));
/* invalidate the previews -- have to do it here, because
* it is not done during the actual painting.
*/
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (drawable));
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (gimage));
}
static void
@ -1029,9 +1034,9 @@ ink_paste (GimpInkTool *ink_tool,
ink_tool->x2 = MAX (ink_tool->x2, (canvas_buf->x + canvas_buf->width));
ink_tool->y2 = MAX (ink_tool->y2, (canvas_buf->y + canvas_buf->height));
/* Update the gimage--it is important to call gimp_image_update
* instead of drawable_update because we don't want the drawable
* preview to be constantly invalidated
/* Update the gimage -- it is important to call gimp_image_update()
* instead of gimp_drawable_update() because we don't want the
* drawable and image previews to be constantly invalidated
*/
gimp_item_offsets (GIMP_ITEM (drawable), &offx, &offy);
gimp_image_update (gimage,

View File

@ -489,10 +489,11 @@ gimp_paint_core_finish (GimpPaintCore *core,
gimp_image_undo_group_end (gimage);
/* invalidate the drawable--have to do it here, because
/* invalidate the previews -- have to do it here, because
* it is not done during the actual painting.
*/
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (drawable));
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (gimage));
}
void
@ -1622,9 +1623,9 @@ gimp_paint_core_paste (GimpPaintCore *core,
core->x2 = MAX (core->x2, core->canvas_buf->x + core->canvas_buf->width);
core->y2 = MAX (core->y2, core->canvas_buf->y + core->canvas_buf->height);
/* Update the gimage -- It is important to call gimp_image_update
* instead of drawable_update because we don't want the drawable
* preview to be constantly invalidated
/* Update the gimage -- It is important to call gimp_image_update()
* instead of gimp_drawable_update() because we don't want the
* drawable and image previews to be constantly invalidated
*/
gimp_item_offsets (GIMP_ITEM (drawable), &offx, &offy);
gimp_image_update (gimage,
@ -1734,9 +1735,9 @@ gimp_paint_core_replace (GimpPaintCore *core,
core->x2 = MAX (core->x2, core->canvas_buf->x + core->canvas_buf->width) ;
core->y2 = MAX (core->y2, core->canvas_buf->y + core->canvas_buf->height) ;
/* Update the gimage -- It is important to call gimp_image_update
* instead of drawable_update because we don't want the drawable
* preview to be constantly invalidated
/* Update the gimage -- It is important to call gimp_image_update()
* instead of gimp_drawable_update() because we don't want the
* drawable and image previews to be constantly invalidated
*/
gimp_item_offsets (GIMP_ITEM (drawable), &offx, &offy);
gimp_image_update (gimage,

View File

@ -443,6 +443,11 @@ gimp_text_layer_render_now (GimpTextLayer *layer)
drawable->tiles = tile_manager_new (width, height, drawable->bytes);
gimp_drawable_update (drawable,
0, 0,
gimp_item_width (item),
gimp_item_height (item));
gimp_viewable_size_changed (GIMP_VIEWABLE (layer));
}
}
@ -508,5 +513,7 @@ gimp_text_layer_render_layout (GimpTextLayer *layer,
tile_manager_unref (mask);
gimp_drawable_update (drawable, 0, 0, bitmap.width, bitmap.rows);
/* no need to gimp_drawable_update() since gimp_drawable_fill()
* did that for us.
*/
}

View File

@ -704,6 +704,8 @@ static void
ink_finish (GimpInkTool *ink_tool,
GimpDrawable *drawable)
{
GimpImage *gimage;
gimp_drawable_push_undo (drawable, _("Ink"),
ink_tool->x1, ink_tool->y1,
ink_tool->x2, ink_tool->y2,
@ -712,10 +714,13 @@ ink_finish (GimpInkTool *ink_tool,
tile_manager_unref (undo_tiles);
undo_tiles = NULL;
/* invalidate the drawable--have to do it here, because
gimage = gimp_item_get_image (GIMP_ITEM (drawable));
/* invalidate the previews -- have to do it here, because
* it is not done during the actual painting.
*/
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (drawable));
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (gimage));
}
static void
@ -1029,9 +1034,9 @@ ink_paste (GimpInkTool *ink_tool,
ink_tool->x2 = MAX (ink_tool->x2, (canvas_buf->x + canvas_buf->width));
ink_tool->y2 = MAX (ink_tool->y2, (canvas_buf->y + canvas_buf->height));
/* Update the gimage--it is important to call gimp_image_update
* instead of drawable_update because we don't want the drawable
* preview to be constantly invalidated
/* Update the gimage -- it is important to call gimp_image_update()
* instead of gimp_drawable_update() because we don't want the
* drawable and image previews to be constantly invalidated
*/
gimp_item_offsets (GIMP_ITEM (drawable), &offx, &offy);
gimp_image_update (gimage,