mirror of
https://gitlab.gnome.org/GNOME/gimp
synced 2024-10-21 03:52:33 +00:00
added new virtual functions GimpDrawable::get_active_components(),
2003-10-06 Michael Natterer <mitch@gimp.org> * 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.
This commit is contained in:
parent
f0372cad0f
commit
a20e04bdaf
37
ChangeLog
37
ChangeLog
|
@ -1,3 +1,40 @@
|
|||
2003-10-06 Michael Natterer <mitch@gimp.org>
|
||||
|
||||
* 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 <mitch@gimp.org>
|
||||
|
||||
Treat changes to the selection like changes to any other drawable:
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -18,13 +18,11 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
294
app/core/gimpdrawable-combine.c
Normal file
294
app/core/gimpdrawable-combine.c
Normal file
|
@ -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 <glib-object.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
44
app/core/gimpdrawable-combine.h
Normal file
44
app/core/gimpdrawable-combine.h
Normal file
|
@ -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__ */
|
|
@ -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);
|
||||
|
|
|
@ -18,15 +18,9 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#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)
|
||||
{
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue