diff --git a/ChangeLog b/ChangeLog index bfa9ca95ae..901d40d6aa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,40 @@ +2003-10-06 Michael Natterer + + * app/core/gimpdrawable.[ch]: added new virtual functions + GimpDrawable::get_active_components(), apply_region() and + replace_region(). + + * app/core/Makefile.am + * app/core/gimpdrawable-combine.[ch]: new files containing + apply_region()'s and replace_region()'s default implementation. + They are identical to the ones removed from GimpImage except that + they don't mask the selection with itself (bug #107949). + + * app/core/gimpchannel.c + * app/core/gimplayer.c: implement get_active_components(). + + * app/core/gimpchannel.c: implement apply_region() and + replace_region() and invalidate the channel's boundary + before upchaining (bug #107949). + + * app/core/gimpimage.[ch]: removed gimp_image_apply_image(), + gimp_image_replace_image() and gimp_image_get_active_components(). + + * app/core/gimpimage-undo-push.c (undo_pop_image): invalidate + boundary and bounds if the drawable is a channel (bug #107949). + + (undo_pop_mask) + (undo_pop_channel_mod): finish previous commit :) + + * app/core/gimp-edit.c + * app/core/gimpdrawable-blend.c + * app/core/gimpdrawable-bucket-fill.c + * app/core/gimpdrawable-stroke.c + * app/core/gimpimagemap.c + * app/core/gimplayer-floating-sel.c + * app/paint/gimppaintcore.c + * app/tools/gimpinktool.c: changed accordingly. + 2003-10-06 Michael Natterer Treat changes to the selection like changes to any other drawable: diff --git a/app/core/Makefile.am b/app/core/Makefile.am index 95a5a73f48..541c348437 100644 --- a/app/core/Makefile.am +++ b/app/core/Makefile.am @@ -75,6 +75,8 @@ libappcore_a_sources = \ gimpdrawable-blend.h \ gimpdrawable-bucket-fill.c \ gimpdrawable-bucket-fill.h \ + gimpdrawable-combine.c \ + gimpdrawable-combine.h \ gimpdrawable-desaturate.c \ gimpdrawable-desaturate.h \ gimpdrawable-equalize.c \ diff --git a/app/core/gimp-edit.c b/app/core/gimp-edit.c index e9f1113e29..8ad0699874 100644 --- a/app/core/gimp-edit.c +++ b/app/core/gimp-edit.c @@ -312,15 +312,13 @@ gimp_edit_clear (GimpImage *gimage, color_region (&bufPR, col); pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), FALSE); - gimp_image_apply_image (gimage, drawable, &bufPR, - TRUE, _("Clear"), - GIMP_OPACITY_OPAQUE, GIMP_ERASE_MODE, - NULL, x1, y1); + gimp_drawable_apply_region (drawable, &bufPR, + TRUE, _("Clear"), + GIMP_OPACITY_OPAQUE, GIMP_ERASE_MODE, + NULL, x1, y1); /* update the image */ - gimp_drawable_update (drawable, - x1, y1, - (x2 - x1), (y2 - y1)); + gimp_drawable_update (drawable, x1, y1, x2 - x1, y2 - y1); /* free the temporary tiles */ tile_manager_unref (buf_tiles); @@ -396,15 +394,13 @@ gimp_edit_fill (GimpImage *gimage, color_region (&bufPR, col); pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), FALSE); - gimp_image_apply_image (gimage, drawable, &bufPR, - TRUE, undo_desc, - GIMP_OPACITY_OPAQUE, GIMP_NORMAL_MODE, - NULL, x1, y1); + gimp_drawable_apply_region (drawable, &bufPR, + TRUE, undo_desc, + GIMP_OPACITY_OPAQUE, GIMP_NORMAL_MODE, + NULL, x1, y1); /* update the image */ - gimp_drawable_update (drawable, - x1, y1, - (x2 - x1), (y2 - y1)); + gimp_drawable_update (drawable, x1, y1, x2 - x1, y2 - y1); /* free the temporary tiles */ tile_manager_unref (buf_tiles); diff --git a/app/core/gimpchannel.c b/app/core/gimpchannel.c index bcb348a332..64a436e77a 100644 --- a/app/core/gimpchannel.c +++ b/app/core/gimpchannel.c @@ -18,13 +18,11 @@ #include "config.h" -#include #include #include #include "libgimpcolor/gimpcolor.h" -#include "libgimpmath/gimpmath.h" #include "core-types.h" @@ -49,7 +47,6 @@ #include "gimpdrawable-stroke.h" #include "gimplayer.h" #include "gimppaintinfo.h" -#include "gimpparasitelist.h" #include "gimpstrokeoptions.h" #include "gimp-intl.h" @@ -101,7 +98,27 @@ static gboolean gimp_channel_stroke (GimpItem *item, GimpDrawable *drawable, GimpObject *stroke_desc); -static void gimp_channel_invalidate_boundary (GimpDrawable *drawable); +static void gimp_channel_invalidate_boundary (GimpDrawable *drawable); +static void gimp_channel_get_active_components (const GimpDrawable *drawable, + gboolean *active); + +static void gimp_channel_apply_region (GimpDrawable *drawable, + PixelRegion *src2PR, + gboolean push_undo, + const gchar *undo_desc, + gdouble opacity, + GimpLayerModeEffects mode, + TileManager *src1_tiles, + gint x, + gint y); +static void gimp_channel_replace_region (GimpDrawable *drawable, + PixelRegion *src2PR, + gboolean push_undo, + const gchar *undo_desc, + gdouble opacity, + PixelRegion *maskPR, + gint x, + gint y); static gboolean gimp_channel_real_boundary (GimpChannel *channel, const BoundSeg **segs_in, @@ -200,47 +217,50 @@ gimp_channel_class_init (GimpChannelClass *klass) parent_class = g_type_class_peek_parent (klass); - object_class->finalize = gimp_channel_finalize; + object_class->finalize = gimp_channel_finalize; - gimp_object_class->get_memsize = gimp_channel_get_memsize; + gimp_object_class->get_memsize = gimp_channel_get_memsize; - viewable_class->default_stock_id = "gimp-channel"; + viewable_class->default_stock_id = "gimp-channel"; - item_class->duplicate = gimp_channel_duplicate; - item_class->translate = gimp_channel_translate; - item_class->scale = gimp_channel_scale; - item_class->resize = gimp_channel_resize; - item_class->flip = gimp_channel_flip; - item_class->rotate = gimp_channel_rotate; - item_class->transform = gimp_channel_transform; - item_class->stroke = gimp_channel_stroke; - item_class->default_name = _("Channel"); - item_class->rename_desc = _("Rename Channel"); + item_class->duplicate = gimp_channel_duplicate; + item_class->translate = gimp_channel_translate; + item_class->scale = gimp_channel_scale; + item_class->resize = gimp_channel_resize; + item_class->flip = gimp_channel_flip; + item_class->rotate = gimp_channel_rotate; + item_class->transform = gimp_channel_transform; + item_class->stroke = gimp_channel_stroke; + item_class->default_name = _("Channel"); + item_class->rename_desc = _("Rename Channel"); - drawable_class->invalidate_boundary = gimp_channel_invalidate_boundary; + drawable_class->invalidate_boundary = gimp_channel_invalidate_boundary; + drawable_class->get_active_components = gimp_channel_get_active_components; + drawable_class->apply_region = gimp_channel_apply_region; + drawable_class->replace_region = gimp_channel_replace_region; - klass->boundary = gimp_channel_real_boundary; - klass->bounds = gimp_channel_real_bounds; - klass->is_empty = gimp_channel_real_is_empty; - klass->value = gimp_channel_real_value; - klass->feather = gimp_channel_real_feather; - klass->sharpen = gimp_channel_real_sharpen; - klass->clear = gimp_channel_real_clear; - klass->all = gimp_channel_real_all; - klass->invert = gimp_channel_real_invert; - klass->border = gimp_channel_real_border; - klass->grow = gimp_channel_real_grow; - klass->shrink = gimp_channel_real_shrink; + klass->boundary = gimp_channel_real_boundary; + klass->bounds = gimp_channel_real_bounds; + klass->is_empty = gimp_channel_real_is_empty; + klass->value = gimp_channel_real_value; + klass->feather = gimp_channel_real_feather; + klass->sharpen = gimp_channel_real_sharpen; + klass->clear = gimp_channel_real_clear; + klass->all = gimp_channel_real_all; + klass->invert = gimp_channel_real_invert; + klass->border = gimp_channel_real_border; + klass->grow = gimp_channel_real_grow; + klass->shrink = gimp_channel_real_shrink; - klass->translate_desc = _("Move Channel"); - klass->feather_desc = _("Feather Channel"); - klass->sharpen_desc = _("Sharpen Channel"); - klass->clear_desc = _("Clear Channel"); - klass->all_desc = _("Fill Channel"); - klass->invert_desc = _("Invert Channel"); - klass->border_desc = _("Border Channel"); - klass->grow_desc = _("Grow Channel"); - klass->shrink_desc = _("Shrink Channel"); + klass->translate_desc = _("Move Channel"); + klass->feather_desc = _("Feather Channel"); + klass->sharpen_desc = _("Sharpen Channel"); + klass->clear_desc = _("Clear Channel"); + klass->all_desc = _("Fill Channel"); + klass->invert_desc = _("Invert Channel"); + klass->border_desc = _("Border Channel"); + klass->grow_desc = _("Grow Channel"); + klass->shrink_desc = _("Shrink Channel"); } static void @@ -644,6 +664,58 @@ gimp_channel_invalidate_boundary (GimpDrawable *drawable) channel->boundary_known = FALSE; } +static void +gimp_channel_get_active_components (const GimpDrawable *drawable, + gboolean *active) +{ + /* Make sure that the alpha channel is not valid. */ + active[GRAY_PIX] = TRUE; + active[ALPHA_G_PIX] = FALSE; +} + +static void +gimp_channel_apply_region (GimpDrawable *drawable, + PixelRegion *src2PR, + gboolean push_undo, + const gchar *undo_desc, + gdouble opacity, + GimpLayerModeEffects mode, + TileManager *src1_tiles, + gint x, + gint y) +{ + gimp_drawable_invalidate_boundary (drawable); + + GIMP_DRAWABLE_CLASS (parent_class)->apply_region (drawable, src2PR, + push_undo, undo_desc, + opacity, mode, + src1_tiles, + x, y); + + GIMP_CHANNEL (drawable)->bounds_known = FALSE; +} + +static void +gimp_channel_replace_region (GimpDrawable *drawable, + PixelRegion *src2PR, + gboolean push_undo, + const gchar *undo_desc, + gdouble opacity, + PixelRegion *maskPR, + gint x, + gint y) +{ + gimp_drawable_invalidate_boundary (drawable); + + GIMP_DRAWABLE_CLASS (parent_class)->replace_region (drawable, src2PR, + push_undo, undo_desc, + opacity, + maskPR, + x, y); + + GIMP_CHANNEL (drawable)->bounds_known = FALSE; +} + static gboolean gimp_channel_real_boundary (GimpChannel *channel, const BoundSeg **segs_in, diff --git a/app/core/gimpdrawable-blend.c b/app/core/gimpdrawable-blend.c index 625f6ba21c..a13793ef7c 100644 --- a/app/core/gimpdrawable-blend.c +++ b/app/core/gimpdrawable-blend.c @@ -237,13 +237,13 @@ gimp_drawable_blend (GimpDrawable *drawable, } pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), FALSE); - gimp_image_apply_image (gimage, drawable, &bufPR, - TRUE, _("Blend"), - opacity, paint_mode, - NULL, x1, y1); + gimp_drawable_apply_region (drawable, &bufPR, + TRUE, _("Blend"), + opacity, paint_mode, + NULL, x1, y1); /* update the image */ - gimp_drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1)); + gimp_drawable_update (drawable, x1, y1, x2 - x1, y2 - y1); /* free the temporary buffer */ tile_manager_unref (buf_tiles); diff --git a/app/core/gimpdrawable-bucket-fill.c b/app/core/gimpdrawable-bucket-fill.c index c94e75fe8e..d749a7aba3 100644 --- a/app/core/gimpdrawable-bucket-fill.c +++ b/app/core/gimpdrawable-bucket-fill.c @@ -268,14 +268,14 @@ gimp_drawable_bucket_fill_full (GimpDrawable *drawable, /* Apply it to the image */ pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), FALSE); - gimp_image_apply_image (gimage, drawable, &bufPR, - TRUE, _("Bucket Fill"), - opacity, paint_mode, - NULL, x1, y1); + gimp_drawable_apply_region (drawable, &bufPR, + TRUE, _("Bucket Fill"), + opacity, paint_mode, + NULL, x1, y1); tile_manager_unref (buf_tiles); /* update the image */ - gimp_drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1)); + gimp_drawable_update (drawable, x1, y1, x2 - x1, y2 - y1); /* free the mask */ if (mask) diff --git a/app/core/gimpdrawable-combine.c b/app/core/gimpdrawable-combine.c new file mode 100644 index 0000000000..29d637e3cd --- /dev/null +++ b/app/core/gimpdrawable-combine.c @@ -0,0 +1,294 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include + +#include "core-types.h" + +#include "base/pixel-region.h" + +#include "paint-funcs/paint-funcs.h" + +#include "gimpchannel.h" +#include "gimpdrawable-combine.h" +#include "gimpimage.h" + + +void +gimp_drawable_real_apply_region (GimpDrawable *drawable, + PixelRegion *src2PR, + gboolean push_undo, + const gchar *undo_desc, + gdouble opacity, + GimpLayerModeEffects mode, + TileManager *src1_tiles, + gint x, + gint y) +{ + GimpImage *gimage; + GimpItem *item; + GimpChannel *mask; + gint x1, y1, x2, y2; + gint offset_x, offset_y; + PixelRegion src1PR, destPR, maskPR; + CombinationMode operation; + gboolean active_components[MAX_CHANNELS]; + + item = GIMP_ITEM (drawable); + + gimage = gimp_item_get_image (item); + + mask = gimp_image_get_mask (gimage); + + /* don't apply the mask to itself and don't apply an empty mask */ + if (GIMP_DRAWABLE (mask) == drawable || gimp_channel_is_empty (mask)) + mask = NULL; + + /* configure the active channel array */ + gimp_drawable_get_active_components (drawable, active_components); + + /* determine what sort of operation is being attempted and + * if it's actually legal... + */ + operation = gimp_image_get_combination_mode (gimp_drawable_type (drawable), + src2PR->bytes); + if (operation == -1) + { + g_warning ("%s: illegal parameters.", G_GNUC_PRETTY_FUNCTION); + return; + } + + /* get the layer offsets */ + gimp_item_offsets (item, &offset_x, &offset_y); + + /* make sure the image application coordinates are within gimage bounds */ + x1 = CLAMP (x, 0, gimp_item_width (item)); + y1 = CLAMP (y, 0, gimp_item_height (item)); + x2 = CLAMP (x + src2PR->w, 0, gimp_item_width (item)); + y2 = CLAMP (y + src2PR->h, 0, gimp_item_height (item)); + + if (mask) + { + /* make sure coordinates are in mask bounds ... + * we need to add the layer offset to transform coords + * into the mask coordinate system + */ + x1 = CLAMP (x1, -offset_x, gimp_item_width (GIMP_ITEM (mask))-offset_x); + y1 = CLAMP (y1, -offset_y, gimp_item_height (GIMP_ITEM (mask))-offset_y); + x2 = CLAMP (x2, -offset_x, gimp_item_width (GIMP_ITEM (mask))-offset_x); + y2 = CLAMP (y2, -offset_y, gimp_item_height (GIMP_ITEM (mask))-offset_y); + } + + /* If the calling procedure specified an undo step... */ + if (push_undo) + gimp_drawable_push_undo (drawable, undo_desc, x1, y1, x2, y2, NULL, FALSE); + + /* configure the pixel regions + * If an alternative to using the drawable's data as src1 was provided... + */ + if (src1_tiles) + pixel_region_init (&src1PR, src1_tiles, + x1, y1, (x2 - x1), (y2 - y1), FALSE); + else + pixel_region_init (&src1PR, gimp_drawable_data (drawable), + x1, y1, (x2 - x1), (y2 - y1), FALSE); + pixel_region_init (&destPR, gimp_drawable_data (drawable), + x1, y1, (x2 - x1), (y2 - y1), TRUE); + pixel_region_resize (src2PR, + src2PR->x + (x1 - x), src2PR->y + (y1 - y), + (x2 - x1), (y2 - y1)); + + if (mask) + { + gint mx, my; + + /* configure the mask pixel region + * don't use x1 and y1 because they are in layer + * coordinate system. Need mask coordinate system + */ + mx = x1 + offset_x; + my = y1 + offset_y; + + pixel_region_init (&maskPR, + gimp_drawable_data (GIMP_DRAWABLE (mask)), + mx, my, + (x2 - x1), (y2 - y1), + FALSE); + + combine_regions (&src1PR, src2PR, &destPR, &maskPR, NULL, + opacity * 255.999, + mode, + active_components, + operation); + } + else + { + combine_regions (&src1PR, src2PR, &destPR, NULL, NULL, + opacity * 255.999, + mode, + active_components, + operation); + } +} + +/* Similar to gimp_drawable_apply_region but works in "replace" mode (i.e. + * transparent pixels in src2 make the result transparent rather than + * opaque. + * + * Takes an additional mask pixel region as well. + */ +void +gimp_drawable_real_replace_region (GimpDrawable *drawable, + PixelRegion *src2PR, + gboolean push_undo, + const gchar *undo_desc, + gdouble opacity, + PixelRegion *maskPR, + gint x, + gint y) +{ + GimpImage *gimage; + GimpItem *item; + GimpChannel *mask; + gint x1, y1, x2, y2; + gint offset_x, offset_y; + PixelRegion src1PR, destPR; + CombinationMode operation; + gboolean active_components[MAX_CHANNELS]; + + item = GIMP_ITEM (drawable); + + gimage = gimp_item_get_image (item); + + mask = gimp_image_get_mask (gimage); + + /* don't apply the mask to itself and don't apply an empty mask */ + if (GIMP_DRAWABLE (mask) == drawable || gimp_channel_is_empty (mask)) + mask = NULL; + + /* configure the active channel array */ + gimp_drawable_get_active_components (drawable, active_components); + + /* determine what sort of operation is being attempted and + * if it's actually legal... + */ + operation = gimp_image_get_combination_mode (gimp_drawable_type (drawable), + src2PR->bytes); + if (operation == -1) + { + g_warning ("%s: illegal parameters.", G_GNUC_PRETTY_FUNCTION); + return; + } + + /* get the layer offsets */ + gimp_item_offsets (item, &offset_x, &offset_y); + + /* make sure the image application coordinates are within gimage bounds */ + x1 = CLAMP (x, 0, gimp_item_width (item)); + y1 = CLAMP (y, 0, gimp_item_height (item)); + x2 = CLAMP (x + src2PR->w, 0, gimp_item_width (item)); + y2 = CLAMP (y + src2PR->h, 0, gimp_item_height (item)); + + if (mask) + { + /* make sure coordinates are in mask bounds ... + * we need to add the layer offset to transform coords + * into the mask coordinate system + */ + x1 = CLAMP (x1, -offset_x, gimp_item_width (GIMP_ITEM (mask))-offset_x); + y1 = CLAMP (y1, -offset_y, gimp_item_height(GIMP_ITEM (mask))-offset_y); + x2 = CLAMP (x2, -offset_x, gimp_item_width (GIMP_ITEM (mask))-offset_x); + y2 = CLAMP (y2, -offset_y, gimp_item_height(GIMP_ITEM (mask))-offset_y); + } + + /* If the calling procedure specified an undo step... */ + if (push_undo) + gimp_drawable_push_undo (drawable, undo_desc, x1, y1, x2, y2, NULL, FALSE); + + /* configure the pixel regions + * If an alternative to using the drawable's data as src1 was provided... + */ + pixel_region_init (&src1PR, gimp_drawable_data (drawable), + x1, y1, (x2 - x1), (y2 - y1), FALSE); + pixel_region_init (&destPR, gimp_drawable_data (drawable), + x1, y1, (x2 - x1), (y2 - y1), TRUE); + pixel_region_resize (src2PR, + src2PR->x + (x1 - x), src2PR->y + (y1 - y), + (x2 - x1), (y2 - y1)); + + if (mask) + { + 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 + * coordinate system. Need mask coordinate system + */ + mx = x1 + offset_x; + my = y1 + offset_y; + + pixel_region_init (&mask2PR, + gimp_drawable_data (GIMP_DRAWABLE (mask)), + mx, my, + (x2 - x1), (y2 - y1), + FALSE); + + tempPR.bytes = 1; + tempPR.x = 0; + tempPR.y = 0; + tempPR.w = x2 - x1; + tempPR.h = y2 - y1; + tempPR.rowstride = tempPR.w * tempPR.bytes; + 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.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.data = temp_data; + + combine_regions_replace (&src1PR, src2PR, &destPR, &tempPR, NULL, + opacity * 255.999, + active_components, + operation); + + g_free (temp_data); + } + else + { + combine_regions_replace (&src1PR, src2PR, &destPR, maskPR, NULL, + opacity * 255.999, + active_components, + operation); + } +} diff --git a/app/core/gimpdrawable-combine.h b/app/core/gimpdrawable-combine.h new file mode 100644 index 0000000000..7ba145a9b8 --- /dev/null +++ b/app/core/gimpdrawable-combine.h @@ -0,0 +1,44 @@ +/* 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_DRAWABLE_COMBINE_H__ +#define __GIMP_DRAWABLE_COMBINE_H__ + + +/* virtual functions of GimpDrawable, don't call directly */ + +void gimp_drawable_real_apply_region (GimpDrawable *drawable, + PixelRegion *src2PR, + gboolean push_undo, + const gchar *undo_desc, + gdouble opacity, + GimpLayerModeEffects mode, + TileManager *src1_tiles, + gint x, + gint y); +void gimp_drawable_real_replace_region (GimpDrawable *drawable, + PixelRegion *src2PR, + gboolean push_undo, + const gchar *undo_desc, + gdouble opacity, + PixelRegion *maskPR, + gint x, + gint y); + + +#endif /* __GIMP_DRAWABLE_COMBINE_H__ */ diff --git a/app/core/gimpdrawable-stroke.c b/app/core/gimpdrawable-stroke.c index fb852d8134..a643fb0eb1 100644 --- a/app/core/gimpdrawable-stroke.c +++ b/app/core/gimpdrawable-stroke.c @@ -319,12 +319,11 @@ gimp_drawable_stroke_scan_convert (GimpDrawable *drawable, /* Apply to drawable */ pixel_region_init (&basePR, base, 0, 0, w, h, FALSE); - gimp_image_apply_image (gimp_item_get_image (GIMP_ITEM (drawable)), - drawable, &basePR, - TRUE, _("Render Stroke"), - context->opacity, - context->paint_mode, - NULL, x1, y1); + gimp_drawable_apply_region (drawable, &basePR, + TRUE, _("Render Stroke"), + gimp_context_get_opacity (context), + gimp_context_get_paint_mode (context), + NULL, x1, y1); tile_manager_unref (mask); tile_manager_unref (base); diff --git a/app/core/gimpdrawable.c b/app/core/gimpdrawable.c index bfa7a6cb8c..d1de18e3ec 100644 --- a/app/core/gimpdrawable.c +++ b/app/core/gimpdrawable.c @@ -18,15 +18,9 @@ #include "config.h" -#include -#include -#include - #include #include "libgimpcolor/gimpcolor.h" -#include "libgimpmath/gimpmath.h" -#include "libgimpbase/gimpbase.h" #include "core-types.h" @@ -40,15 +34,12 @@ #include "gimp-utils.h" #include "gimpchannel.h" #include "gimpcontext.h" -#include "gimpdrawable.h" +#include "gimpdrawable-combine.h" #include "gimpdrawable-preview.h" #include "gimpdrawable-transform.h" #include "gimpimage.h" #include "gimpimage-undo-push.h" -#include "gimplayer.h" -#include "gimplist.h" #include "gimpmarshal.h" -#include "gimpparasitelist.h" #include "gimppreviewcache.h" #include "gimp-intl.h" @@ -201,6 +192,9 @@ gimp_drawable_class_init (GimpDrawableClass *klass) klass->update = gimp_drawable_real_update; klass->alpha_changed = NULL; klass->invalidate_boundary = NULL; + klass->get_active_components = NULL; + klass->apply_region = gimp_drawable_real_apply_region; + klass->replace_region = gimp_drawable_real_replace_region; } static void @@ -611,6 +605,80 @@ gimp_drawable_update (GimpDrawable *drawable, x, y, width, height); } +void +gimp_drawable_alpha_changed (GimpDrawable *drawable) +{ + g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); + + g_signal_emit (drawable, gimp_drawable_signals[ALPHA_CHANGED], 0); +} + +void +gimp_drawable_invalidate_boundary (GimpDrawable *drawable) +{ + GimpDrawableClass *drawable_class; + + g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); + + drawable_class = GIMP_DRAWABLE_GET_CLASS (drawable); + + if (drawable_class->invalidate_boundary) + drawable_class->invalidate_boundary (drawable); +} + +void +gimp_drawable_get_active_components (const GimpDrawable *drawable, + gboolean *active) +{ + GimpDrawableClass *drawable_class; + + g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); + g_return_if_fail (active != NULL); + + drawable_class = GIMP_DRAWABLE_GET_CLASS (drawable); + + if (drawable_class->get_active_components) + drawable_class->get_active_components (drawable, active); +} + +void +gimp_drawable_apply_region (GimpDrawable *drawable, + PixelRegion *src2PR, + gboolean push_undo, + const gchar *undo_desc, + gdouble opacity, + GimpLayerModeEffects mode, + TileManager *src1_tiles, + gint x, + gint y) +{ + g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); + + GIMP_DRAWABLE_GET_CLASS (drawable)->apply_region (drawable, src2PR, + push_undo, undo_desc, + opacity, mode, + src1_tiles, + x, y); +} + +void +gimp_drawable_replace_region (GimpDrawable *drawable, + PixelRegion *src2PR, + gboolean push_undo, + const gchar *undo_desc, + gdouble opacity, + PixelRegion *maskPR, + gint x, + gint y) +{ + g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); + + GIMP_DRAWABLE_GET_CLASS (drawable)->replace_region (drawable, src2PR, + push_undo, undo_desc, + opacity, maskPR, + x, y); +} + void gimp_drawable_push_undo (GimpDrawable *drawable, const gchar *undo_desc, @@ -659,10 +727,10 @@ gimp_drawable_merge_shadow (GimpDrawable *drawable, gimp_drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2); pixel_region_init (&shadowPR, gimage->shadow, x1, y1, (x2 - x1), (y2 - y1), FALSE); - gimp_image_apply_image (gimage, drawable, &shadowPR, - push_undo, undo_desc, - GIMP_OPACITY_OPAQUE, GIMP_REPLACE_MODE, - NULL, x1, y1); + gimp_drawable_apply_region (drawable, &shadowPR, + push_undo, undo_desc, + GIMP_OPACITY_OPAQUE, GIMP_REPLACE_MODE, + NULL, x1, y1); } void @@ -909,27 +977,6 @@ gimp_drawable_bytes_with_alpha (const GimpDrawable *drawable) return GIMP_IMAGE_TYPE_BYTES (type); } -void -gimp_drawable_alpha_changed (GimpDrawable *drawable) -{ - g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); - - g_signal_emit (drawable, gimp_drawable_signals[ALPHA_CHANGED], 0); -} - -void -gimp_drawable_invalidate_boundary (GimpDrawable *drawable) -{ - GimpDrawableClass *drawable_class; - - g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); - - drawable_class = GIMP_DRAWABLE_GET_CLASS (drawable); - - if (drawable_class->invalidate_boundary) - drawable_class->invalidate_boundary (drawable); -} - guchar * gimp_drawable_cmap (const GimpDrawable *drawable) { diff --git a/app/core/gimpdrawable.h b/app/core/gimpdrawable.h index 577d97d905..0126002b89 100644 --- a/app/core/gimpdrawable.h +++ b/app/core/gimpdrawable.h @@ -53,15 +53,34 @@ struct _GimpDrawableClass GimpItemClass parent_class; /* signals */ - void (* update) (GimpDrawable *drawable, - gint x, - gint y, - gint width, - gint height); - void (* alpha_changed) (GimpDrawable *drawable); + void (* update) (GimpDrawable *drawable, + gint x, + gint y, + gint width, + gint height); + void (* alpha_changed) (GimpDrawable *drawable); /* virtual functions */ - void (* invalidate_boundary) (GimpDrawable *drawable); + void (* invalidate_boundary) (GimpDrawable *drawable); + void (* get_active_components) (const GimpDrawable *drawable, + gboolean *active); + void (* apply_region) (GimpDrawable *drawable, + PixelRegion *src2PR, + gboolean push_undo, + const gchar *undo_desc, + gdouble opacity, + GimpLayerModeEffects mode, + TileManager *src1_tiles, + gint x, + gint y); + void (* replace_region) (GimpDrawable *drawable, + PixelRegion *src2PR, + gboolean push_undo, + const gchar *undo_desc, + gdouble opacity, + PixelRegion *maskPR, + gint x, + gint y); }; @@ -83,6 +102,29 @@ void gimp_drawable_update (GimpDrawable *drawable, gint y, gint width, gint height); +void gimp_drawable_alpha_changed (GimpDrawable *drawable); + +void gimp_drawable_invalidate_boundary (GimpDrawable *drawable); +void gimp_drawable_get_active_components (const GimpDrawable *drawable, + gboolean *active); + +void gimp_drawable_apply_region (GimpDrawable *drawable, + PixelRegion *src2PR, + gboolean push_undo, + const gchar *undo_desc, + gdouble opacity, + GimpLayerModeEffects mode, + TileManager *src1_tiles, + gint x, + gint y); +void gimp_drawable_replace_region (GimpDrawable *drawable, + PixelRegion *src2PR, + gboolean push_undo, + const gchar *undo_desc, + gdouble opacity, + PixelRegion *maskPR, + gint x, + gint y); void gimp_drawable_push_undo (GimpDrawable *drawable, const gchar *undo_desc, @@ -120,10 +162,6 @@ TileManager * gimp_drawable_shadow (GimpDrawable *drawable); gint gimp_drawable_bytes (const GimpDrawable *drawable); gint gimp_drawable_bytes_with_alpha (const GimpDrawable *drawable); -void gimp_drawable_alpha_changed (GimpDrawable *drawable); - -void gimp_drawable_invalidate_boundary (GimpDrawable *drawable); - guchar * gimp_drawable_cmap (const GimpDrawable *drawable); guchar * gimp_drawable_get_color_at (GimpDrawable *drawable, diff --git a/app/core/gimpimage-undo-push.c b/app/core/gimpimage-undo-push.c index 21344a8f87..667bb76e9c 100644 --- a/app/core/gimpimage-undo-push.c +++ b/app/core/gimpimage-undo-push.c @@ -223,6 +223,9 @@ undo_pop_image (GimpUndo *undo, x = image_undo->x1; y = image_undo->y1; + if (GIMP_IS_CHANNEL (drawable)) + gimp_drawable_invalidate_boundary (drawable); + if (image_undo->sparse == FALSE) { w = tile_manager_width (tiles); @@ -276,6 +279,9 @@ undo_pop_image (GimpUndo *undo, } } + if (GIMP_IS_CHANNEL (drawable)) + GIMP_CHANNEL (drawable)->bounds_known = FALSE; + gimp_drawable_update (drawable, x, y, w, h); return TRUE; @@ -1025,15 +1031,8 @@ undo_pop_mask (GimpUndo *undo, tile_manager_unref (mu->tiles); } - if (channel == gimp_image_get_mask (undo->gimage)) - { - /* invalidate the current bounds and boundary of the mask */ - gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (gimp_image_get_mask (undo->gimage))); - } - else - { - channel->boundary_known = FALSE; - } + /* invalidate the current bounds and boundary of the mask */ + gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (channel)); if (mu->tiles) { @@ -2312,7 +2311,7 @@ undo_pop_channel_mod (GimpUndo *undo, channel = GIMP_CHANNEL (GIMP_ITEM_UNDO (undo)->item); /* invalidate the current bounds and boundary of the mask */ - gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (gimp_image_get_mask (undo->gimage))); + gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (channel)); /* Issue the first update */ gimp_drawable_update (GIMP_DRAWABLE (channel), diff --git a/app/core/gimpimage.c b/app/core/gimpimage.c index d97f25f166..4d325ef9b6 100644 --- a/app/core/gimpimage.c +++ b/app/core/gimpimage.c @@ -28,12 +28,9 @@ #include "core-types.h" -#include "base/pixel-region.h" #include "base/temp-buf.h" #include "base/tile-manager.h" -#include "paint-funcs/paint-funcs.h" - #include "config/gimpcoreconfig.h" #include "gimp.h" @@ -139,10 +136,6 @@ static void gimp_image_drawable_remove (GimpContainer *container, GimpItem *item, GimpImage *gimage); -static void gimp_image_get_active_components (const GimpImage *gimage, - const GimpDrawable *drawable, - gboolean *active); - static gint valid_combinations[][MAX_CHANNELS + 1] = { @@ -922,36 +915,6 @@ gimp_image_drawable_remove (GimpContainer *container, gimp_image_drawable_visibility (item, gimage); } -static void -gimp_image_get_active_components (const GimpImage *gimage, - const GimpDrawable *drawable, - gboolean *active) -{ - /* If the drawable is a channel make sure that the alpha channel is - * not valid. - */ - if (GIMP_IS_CHANNEL (drawable)) - { - active[GRAY_PIX] = TRUE; - active[ALPHA_G_PIX] = FALSE; - } - /* otherwise, check whether preserve transparency is - * enabled in the layer and if the layer has alpha - */ - else if (GIMP_IS_LAYER (drawable)) - { - GimpLayer *layer = GIMP_LAYER (drawable); - gint i; - - /* first copy the gimage active channels */ - for (i = 0; i < MAX_CHANNELS; i++) - active[i] = gimage->active[i]; - - if (gimp_drawable_has_alpha (drawable) && layer->preserve_trans) - active[gimp_drawable_bytes (drawable) - 1] = FALSE; - } -} - /* public functions */ @@ -1908,272 +1871,6 @@ gimp_image_free_shadow (GimpImage *gimage) } -/* combine functions */ - -void -gimp_image_apply_image (GimpImage *gimage, - GimpDrawable *drawable, - PixelRegion *src2PR, - gboolean push_undo, - const gchar *undo_desc, - gdouble opacity, - GimpLayerModeEffects mode, - /* alternative to using drawable tiles as src1: */ - TileManager *src1_tiles, - gint x, - gint y) -{ - GimpItem *item; - GimpChannel *mask; - gint x1, y1, x2, y2; - gint offset_x, offset_y; - PixelRegion src1PR, destPR, maskPR; - CombinationMode operation; - gboolean active_components[MAX_CHANNELS]; - - g_return_if_fail (GIMP_IS_IMAGE (gimage)); - g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); - - item = GIMP_ITEM (drawable); - - /* get the selection mask if one exists */ - mask = gimp_image_get_mask (gimage); - if (gimp_channel_is_empty (mask)) - mask = NULL; - - /* configure the active channel array */ - gimp_image_get_active_components (gimage, drawable, active_components); - - /* determine what sort of operation is being attempted and - * if it's actually legal... - */ - operation = gimp_image_get_combination_mode (gimp_drawable_type (drawable), - src2PR->bytes); - if (operation == -1) - { - g_warning ("%s: illegal parameters.", G_GNUC_PRETTY_FUNCTION); - return; - } - - /* get the layer offsets */ - gimp_item_offsets (item, &offset_x, &offset_y); - - /* make sure the image application coordinates are within gimage bounds */ - x1 = CLAMP (x, 0, gimp_item_width (item)); - y1 = CLAMP (y, 0, gimp_item_height (item)); - x2 = CLAMP (x + src2PR->w, 0, gimp_item_width (item)); - y2 = CLAMP (y + src2PR->h, 0, gimp_item_height (item)); - - if (mask) - { - /* make sure coordinates are in mask bounds ... - * we need to add the layer offset to transform coords - * into the mask coordinate system - */ - x1 = CLAMP (x1, -offset_x, gimp_item_width (GIMP_ITEM (mask))-offset_x); - y1 = CLAMP (y1, -offset_y, gimp_item_height (GIMP_ITEM (mask))-offset_y); - x2 = CLAMP (x2, -offset_x, gimp_item_width (GIMP_ITEM (mask))-offset_x); - y2 = CLAMP (y2, -offset_y, gimp_item_height (GIMP_ITEM (mask))-offset_y); - } - - /* If the calling procedure specified an undo step... */ - if (push_undo) - gimp_drawable_push_undo (drawable, undo_desc, x1, y1, x2, y2, NULL, FALSE); - - /* configure the pixel regions - * If an alternative to using the drawable's data as src1 was provided... - */ - if (src1_tiles) - pixel_region_init (&src1PR, src1_tiles, - x1, y1, (x2 - x1), (y2 - y1), FALSE); - else - pixel_region_init (&src1PR, gimp_drawable_data (drawable), - x1, y1, (x2 - x1), (y2 - y1), FALSE); - pixel_region_init (&destPR, gimp_drawable_data (drawable), - x1, y1, (x2 - x1), (y2 - y1), TRUE); - pixel_region_resize (src2PR, - src2PR->x + (x1 - x), src2PR->y + (y1 - y), - (x2 - x1), (y2 - y1)); - - if (mask) - { - gint mx, my; - - /* configure the mask pixel region - * don't use x1 and y1 because they are in layer - * coordinate system. Need mask coordinate system - */ - mx = x1 + offset_x; - my = y1 + offset_y; - - pixel_region_init (&maskPR, - gimp_drawable_data (GIMP_DRAWABLE (mask)), - mx, my, - (x2 - x1), (y2 - y1), - FALSE); - - combine_regions (&src1PR, src2PR, &destPR, &maskPR, NULL, - opacity * 255.999, - mode, - active_components, - operation); - } - else - { - combine_regions (&src1PR, src2PR, &destPR, NULL, NULL, - opacity * 255.999, - mode, - active_components, - operation); - } -} - -/* Similar to gimp_image_apply_image but works in "replace" mode (i.e. - transparent pixels in src2 make the result transparent rather - than opaque. - - Takes an additional mask pixel region as well. -*/ -void -gimp_image_replace_image (GimpImage *gimage, - GimpDrawable *drawable, - PixelRegion *src2PR, - gboolean push_undo, - const gchar *undo_desc, - gdouble opacity, - PixelRegion *maskPR, - gint x, - gint y) -{ - GimpItem *item; - GimpChannel *mask; - gint x1, y1, x2, y2; - gint offset_x, offset_y; - PixelRegion src1PR, destPR; - CombinationMode operation; - gboolean active_components[MAX_CHANNELS]; - - g_return_if_fail (GIMP_IS_IMAGE (gimage)); - g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); - - item = GIMP_ITEM (drawable); - - /* get the selection mask if one exists */ - mask = gimp_image_get_mask (gimage); - if (gimp_channel_is_empty (mask)) - mask = NULL; - - /* configure the active channel array */ - gimp_image_get_active_components (gimage, drawable, active_components); - - /* determine what sort of operation is being attempted and - * if it's actually legal... - */ - operation = gimp_image_get_combination_mode (gimp_drawable_type (drawable), - src2PR->bytes); - if (operation == -1) - { - g_warning ("%s: illegal parameters.", G_GNUC_PRETTY_FUNCTION); - return; - } - - /* get the layer offsets */ - gimp_item_offsets (item, &offset_x, &offset_y); - - /* make sure the image application coordinates are within gimage bounds */ - x1 = CLAMP (x, 0, gimp_item_width (item)); - y1 = CLAMP (y, 0, gimp_item_height (item)); - x2 = CLAMP (x + src2PR->w, 0, gimp_item_width (item)); - y2 = CLAMP (y + src2PR->h, 0, gimp_item_height (item)); - - if (mask) - { - /* make sure coordinates are in mask bounds ... - * we need to add the layer offset to transform coords - * into the mask coordinate system - */ - x1 = CLAMP (x1, -offset_x, gimp_item_width (GIMP_ITEM (mask))-offset_x); - y1 = CLAMP (y1, -offset_y, gimp_item_height(GIMP_ITEM (mask))-offset_y); - x2 = CLAMP (x2, -offset_x, gimp_item_width (GIMP_ITEM (mask))-offset_x); - y2 = CLAMP (y2, -offset_y, gimp_item_height(GIMP_ITEM (mask))-offset_y); - } - - /* If the calling procedure specified an undo step... */ - if (push_undo) - gimp_drawable_push_undo (drawable, undo_desc, x1, y1, x2, y2, NULL, FALSE); - - /* configure the pixel regions - * If an alternative to using the drawable's data as src1 was provided... - */ - pixel_region_init (&src1PR, gimp_drawable_data (drawable), - x1, y1, (x2 - x1), (y2 - y1), FALSE); - pixel_region_init (&destPR, gimp_drawable_data (drawable), - x1, y1, (x2 - x1), (y2 - y1), TRUE); - pixel_region_resize (src2PR, - src2PR->x + (x1 - x), src2PR->y + (y1 - y), - (x2 - x1), (y2 - y1)); - - if (mask) - { - 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 - * coordinate system. Need mask coordinate system - */ - mx = x1 + offset_x; - my = y1 + offset_y; - - pixel_region_init (&mask2PR, - gimp_drawable_data (GIMP_DRAWABLE (mask)), - mx, my, - (x2 - x1), (y2 - y1), - FALSE); - - tempPR.bytes = 1; - tempPR.x = 0; - tempPR.y = 0; - tempPR.w = x2 - x1; - tempPR.h = y2 - y1; - tempPR.rowstride = tempPR.w * tempPR.bytes; - 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.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.data = temp_data; - - combine_regions_replace (&src1PR, src2PR, &destPR, &tempPR, NULL, - opacity * 255.999, - active_components, - operation); - - g_free (temp_data); - } - else - { - combine_regions_replace (&src1PR, src2PR, &destPR, maskPR, NULL, - opacity * 255.999, - active_components, - operation); - } -} - - /* parasites */ GimpParasite * diff --git a/app/core/gimpimage.h b/app/core/gimpimage.h index 3d2d140c82..07cc10984f 100644 --- a/app/core/gimpimage.h +++ b/app/core/gimpimage.h @@ -347,29 +347,6 @@ TileManager * gimp_image_shadow (GimpImage *gimage, void gimp_image_free_shadow (GimpImage *gimage); -/* combine functions */ - -void gimp_image_apply_image (GimpImage *gimage, - GimpDrawable *drawable, - PixelRegion *src2PR, - gboolean push_undo, - const gchar *undo_desc, - gdouble opacity, - GimpLayerModeEffects mode, - TileManager *src1_tiles, - gint x, - gint y); -void gimp_image_replace_image (GimpImage *gimage, - GimpDrawable *drawable, - PixelRegion *src2PR, - gboolean push_undo, - const gchar *undo_desc, - gdouble opacity, - PixelRegion *maskPR, - gint x, - gint y); - - /* parasites */ GimpParasite * gimp_image_parasite_find (const GimpImage *gimage, diff --git a/app/core/gimpimagemap.c b/app/core/gimpimagemap.c index 26f19d43bf..1d316dbaa7 100644 --- a/app/core/gimpimagemap.c +++ b/app/core/gimpimagemap.c @@ -512,11 +512,11 @@ gimp_image_map_do (GimpImageMap *image_map) /* apply the results */ pixel_region_init (&shadowPR, gimage->shadow, x, y, w, h, FALSE); - gimp_image_apply_image (gimage, image_map->drawable, &shadowPR, - FALSE, NULL, - GIMP_OPACITY_OPAQUE, GIMP_REPLACE_MODE, - NULL, - x, y); + gimp_drawable_apply_region (image_map->drawable, &shadowPR, + FALSE, NULL, + GIMP_OPACITY_OPAQUE, GIMP_REPLACE_MODE, + NULL, + x, y); /* display the results */ gimp_drawable_update (image_map->drawable, x, y, w, h); diff --git a/app/core/gimplayer-floating-sel.c b/app/core/gimplayer-floating-sel.c index 41a4f48f3a..a49d7bdfae 100644 --- a/app/core/gimplayer-floating-sel.c +++ b/app/core/gimplayer-floating-sel.c @@ -477,12 +477,12 @@ floating_sel_composite (GimpLayer *layer, /* apply the fs with the undo specified by the value * passed to this function */ - gimp_image_apply_image (gimage, layer->fs.drawable, &fsPR, - push_undo, NULL, - layer->opacity, - layer->mode, - NULL, - (x1 - offx), (y1 - offy)); + gimp_drawable_apply_region (layer->fs.drawable, &fsPR, + push_undo, NULL, + layer->opacity, + layer->mode, + NULL, + (x1 - offx), (y1 - offy)); /* restore preserve transparency */ if (preserve_trans) diff --git a/app/core/gimplayer.c b/app/core/gimplayer.c index 722401abfa..b18d81f55b 100644 --- a/app/core/gimplayer.c +++ b/app/core/gimplayer.c @@ -112,7 +112,9 @@ static void gimp_layer_transform (GimpItem *item, GimpProgressFunc progress_callback, gpointer progress_data); -static void gimp_layer_invalidate_boundary (GimpDrawable *drawable); +static void gimp_layer_invalidate_boundary (GimpDrawable *drawable); +static void gimp_layer_get_active_components (const GimpDrawable *drawable, + gboolean *active); static void gimp_layer_transform_color (GimpImage *gimage, PixelRegion *layerPR, @@ -234,7 +236,8 @@ gimp_layer_class_init (GimpLayerClass *klass) item_class->default_name = _("Layer"); item_class->rename_desc = _("Rename Layer"); - drawable_class->invalidate_boundary = gimp_layer_invalidate_boundary; + drawable_class->invalidate_boundary = gimp_layer_invalidate_boundary; + drawable_class->get_active_components = gimp_layer_get_active_components; klass->opacity_changed = NULL; klass->mode_changed = NULL; @@ -334,6 +337,22 @@ gimp_layer_invalidate_preview (GimpViewable *viewable) floating_sel_invalidate (layer); } +static void +gimp_layer_get_active_components (const GimpDrawable *drawable, + gboolean *active) +{ + GimpImage *gimage = gimp_item_get_image (GIMP_ITEM (drawable)); + GimpLayer *layer = GIMP_LAYER (drawable); + gint i; + + /* first copy the gimage active channels */ + for (i = 0; i < MAX_CHANNELS; i++) + active[i] = gimage->active[i]; + + if (gimp_drawable_has_alpha (drawable) && layer->preserve_trans) + active[gimp_drawable_bytes (drawable) - 1] = FALSE; +} + static GimpItem * gimp_layer_duplicate (GimpItem *item, GType new_type, diff --git a/app/paint/gimpink.c b/app/paint/gimpink.c index 04a597d176..33d1c360ba 100644 --- a/app/paint/gimpink.c +++ b/app/paint/gimpink.c @@ -1021,12 +1021,12 @@ ink_paste (GimpInkTool *ink_tool, srcPR.data = temp_buf_data (canvas_buf); /* apply the paint area to the gimage */ - gimp_image_apply_image (gimage, drawable, &srcPR, - FALSE, NULL, - gimp_context_get_opacity (context), - gimp_context_get_paint_mode (context), - undo_tiles, /* specify an alternative src1 */ - canvas_buf->x, canvas_buf->y); + gimp_drawable_apply_region (drawable, &srcPR, + FALSE, NULL, + gimp_context_get_opacity (context), + gimp_context_get_paint_mode (context), + undo_tiles, /* specify an alternative src1 */ + canvas_buf->x, canvas_buf->y); /* Update the undo extents */ ink_tool->x1 = MIN (ink_tool->x1, canvas_buf->x); diff --git a/app/paint/gimppaintcore.c b/app/paint/gimppaintcore.c index 2fd1c8d630..25c6b55dde 100644 --- a/app/paint/gimppaintcore.c +++ b/app/paint/gimppaintcore.c @@ -1673,12 +1673,12 @@ gimp_paint_core_paste (GimpPaintCore *core, srcPR.data = temp_buf_data (core->canvas_buf); /* apply the paint area to the gimage */ - gimp_image_apply_image (gimage, drawable, &srcPR, - FALSE, NULL, - image_opacity, paint_mode, - alt, /* specify an alternative src1 */ - core->canvas_buf->x, - core->canvas_buf->y); + gimp_drawable_apply_region (drawable, &srcPR, + FALSE, NULL, + image_opacity, paint_mode, + alt, /* specify an alternative src1 */ + core->canvas_buf->x, + core->canvas_buf->y); /* Update the undo extents */ core->x1 = MIN (core->x1, core->canvas_buf->x); @@ -1785,12 +1785,12 @@ gimp_paint_core_replace (GimpPaintCore *core, srcPR.data = temp_buf_data (core->canvas_buf); /* apply the paint area to the gimage */ - gimp_image_replace_image (gimage, drawable, &srcPR, - FALSE, NULL, - image_opacity, - &maskPR, - core->canvas_buf->x, - core->canvas_buf->y); + gimp_drawable_replace_region (drawable, &srcPR, + FALSE, NULL, + image_opacity, + &maskPR, + core->canvas_buf->x, + core->canvas_buf->y); /* Update the undo extents */ core->x1 = MIN (core->x1, core->canvas_buf->x); diff --git a/app/tools/gimpinktool.c b/app/tools/gimpinktool.c index 04a597d176..33d1c360ba 100644 --- a/app/tools/gimpinktool.c +++ b/app/tools/gimpinktool.c @@ -1021,12 +1021,12 @@ ink_paste (GimpInkTool *ink_tool, srcPR.data = temp_buf_data (canvas_buf); /* apply the paint area to the gimage */ - gimp_image_apply_image (gimage, drawable, &srcPR, - FALSE, NULL, - gimp_context_get_opacity (context), - gimp_context_get_paint_mode (context), - undo_tiles, /* specify an alternative src1 */ - canvas_buf->x, canvas_buf->y); + gimp_drawable_apply_region (drawable, &srcPR, + FALSE, NULL, + gimp_context_get_opacity (context), + gimp_context_get_paint_mode (context), + undo_tiles, /* specify an alternative src1 */ + canvas_buf->x, canvas_buf->y); /* Update the undo extents */ ink_tool->x1 = MIN (ink_tool->x1, canvas_buf->x);