2006-12-10 05:33:38 +08:00
|
|
|
/* GIMP - The GNU Image Manipulation Program
|
1997-11-25 06:05:25 +08:00
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
2009-01-18 06:28:01 +08:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
1997-11-25 06:05:25 +08:00
|
|
|
* it under the terms of the GNU General Public License as published by
|
2009-01-18 06:28:01 +08:00
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
1997-11-25 06:05:25 +08:00
|
|
|
* (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
|
2009-01-18 06:28:01 +08:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
1997-11-25 06:05:25 +08:00
|
|
|
*/
|
2000-12-14 21:52:16 +08:00
|
|
|
|
2000-04-28 01:27:28 +08:00
|
|
|
#include "config.h"
|
|
|
|
|
1998-09-24 09:19:57 +08:00
|
|
|
#include <stdlib.h>
|
2000-12-14 21:52:16 +08:00
|
|
|
#include <string.h>
|
2000-04-28 01:27:28 +08:00
|
|
|
|
2008-10-10 04:24:04 +08:00
|
|
|
#include <gegl.h>
|
2001-08-14 22:53:55 +08:00
|
|
|
|
2006-08-29 22:46:32 +08:00
|
|
|
#include "libgimpbase/gimpbase.h"
|
2001-01-24 07:56:18 +08:00
|
|
|
#include "libgimpmath/gimpmath.h"
|
|
|
|
|
2001-05-10 06:34:59 +08:00
|
|
|
#include "core-types.h"
|
2000-12-29 23:22:01 +08:00
|
|
|
|
2001-05-15 19:25:25 +08:00
|
|
|
#include "base/boundary.h"
|
|
|
|
#include "base/pixel-region.h"
|
|
|
|
#include "base/tile-manager.h"
|
|
|
|
#include "base/tile.h"
|
|
|
|
|
2001-04-07 23:58:26 +08:00
|
|
|
#include "paint-funcs/paint-funcs.h"
|
|
|
|
|
2008-10-10 04:44:23 +08:00
|
|
|
#include "gegl/gimp-gegl-utils.h"
|
|
|
|
|
2010-07-21 05:09:19 +08:00
|
|
|
#include "gimpchannel-select.h"
|
2004-04-15 07:37:34 +08:00
|
|
|
#include "gimpcontext.h"
|
2001-11-01 05:18:57 +08:00
|
|
|
#include "gimpcontainer.h"
|
2005-02-19 00:16:24 +08:00
|
|
|
#include "gimpdrawable-convert.h"
|
2004-04-15 07:37:34 +08:00
|
|
|
#include "gimpdrawable-invert.h"
|
2008-11-12 18:56:06 +08:00
|
|
|
#include "gimperror.h"
|
2003-02-14 22:14:29 +08:00
|
|
|
#include "gimpimage-undo-push.h"
|
2004-04-15 07:37:34 +08:00
|
|
|
#include "gimpimage-undo.h"
|
|
|
|
#include "gimpimage.h"
|
2002-02-22 06:19:45 +08:00
|
|
|
#include "gimplayer-floating-sel.h"
|
2004-04-15 07:37:34 +08:00
|
|
|
#include "gimplayer.h"
|
2008-11-08 08:16:40 +08:00
|
|
|
#include "gimplayer-project.h"
|
2001-01-29 00:44:22 +08:00
|
|
|
#include "gimplayermask.h"
|
2001-11-23 07:46:13 +08:00
|
|
|
#include "gimpmarshal.h"
|
2005-07-12 03:21:52 +08:00
|
|
|
#include "gimppickable.h"
|
2001-07-10 03:48:30 +08:00
|
|
|
|
2003-03-26 00:38:19 +08:00
|
|
|
#include "gimp-intl.h"
|
2000-04-28 01:27:28 +08:00
|
|
|
|
|
|
|
|
2001-03-05 04:06:48 +08:00
|
|
|
enum
|
|
|
|
{
|
2001-03-12 01:24:47 +08:00
|
|
|
OPACITY_CHANGED,
|
|
|
|
MODE_CHANGED,
|
2005-07-11 05:17:22 +08:00
|
|
|
LOCK_ALPHA_CHANGED,
|
2001-03-05 04:06:48 +08:00
|
|
|
MASK_CHANGED,
|
|
|
|
LAST_SIGNAL
|
|
|
|
};
|
|
|
|
|
2005-07-12 00:46:28 +08:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
PROP_0,
|
|
|
|
PROP_OPACITY,
|
|
|
|
PROP_MODE,
|
2008-11-17 08:02:15 +08:00
|
|
|
PROP_LOCK_ALPHA,
|
2008-11-20 07:37:15 +08:00
|
|
|
PROP_MASK,
|
2008-11-17 08:02:15 +08:00
|
|
|
PROP_FLOATING_SELECTION
|
2005-07-12 00:46:28 +08:00
|
|
|
};
|
|
|
|
|
2001-03-05 04:06:48 +08:00
|
|
|
|
2005-12-11 03:24:36 +08:00
|
|
|
static void gimp_layer_pickable_iface_init (GimpPickableInterface *iface);
|
2001-08-11 22:39:19 +08:00
|
|
|
|
2005-07-12 00:46:28 +08:00
|
|
|
static void gimp_layer_set_property (GObject *object,
|
|
|
|
guint property_id,
|
|
|
|
const GValue *value,
|
|
|
|
GParamSpec *pspec);
|
|
|
|
static void gimp_layer_get_property (GObject *object,
|
|
|
|
guint property_id,
|
|
|
|
GValue *value,
|
|
|
|
GParamSpec *pspec);
|
To optimize duplicate and/or wrong image updates away, introduced new
2003-09-06 Michael Natterer <mitch@gimp.org>
To optimize duplicate and/or wrong image updates away, introduced
new policy that a child object must never explicitly update or
invalidate its parent object (just like the GUI is not updated
explicitly by the core):
* app/core/gimpdrawable.[ch]: added new signal
GimpDrawable::update(). Never update or invalidate the image when
the drawable is updated or invalidated.
(gimp_drawable_set_visible): don't gimp_drawable_update() the
drawable since its pixels have not changed.
* app/core/gimpimage.[ch]: connect to the "add" and "remove"
signals of the layers and channels containers. Also connect to the
"update" and "visibility_changed" signals of all drawables in
these containers (optimizes away updates issued by drawables which
are not yet added to the image and updates of the selection
mask). Also, don't propagate updates to the image if the emitting
drawable is invisible (optimizes away updates issued by invisible
drawables).
(gimp_image_add_layer,channel)
(gimp_image_remove_layer,channel): don't update the image since
that's done by our "add" and "remove" handlers now.
(gimp_image_position_layer,channel): update just the image, not
the drawable since its pixels have not changed.
(gimp_image_real_colormap_changed)
(gimp_image_set_component_visible): always call
gimp_image_update() *and* gimp_viewable_invalidate_preview() to
get everything updated, since update and invalidate of images are
not connected.
* app/core/gimpimage-undo-push.c (undo_pop_layer,channel): don't
update the drawable since (a) its pixels don't change and (b) the
image updates itself upon adding/removing now.
(undo_pop_layer_mod): replaced gimp_image_update() by
gimp_drawable_update() (just for consistency with other similar
functions).
* app/core/gimplayer.c: connect to "update" of the layer mask and
issue updates on the layer if the mask update has any effect on
the projection.
(gimp_layer_create_mask): don't set the mask's offsets here since
they may be different when we later add the mask to the layer.
* app/core/gimplayermask.c (gimp_layer_mask_set_layer): set the
mask offsets here instead.
* app/core/gimpchannel.c (gimp_channel_translate): update the
channel even if push_undo == FALSE.
* app/paint/gimppaintcore.c (gimp_paint_core_finish)
* app/tools/gimpinktool.c (ink_finish): invalidate both the
drawable and the image preview since invalidating the drawable
doesn't invalidate the image any more.
* app/text/gimptextlayer.c (gimp_text_layer_render_now): also
update the new extents of the text layer, not only the old one.
(gimp_text_layer_render_layout): don't update the drawable since
gimp_drawable_fill() already updated it.
2003-09-07 04:06:53 +08:00
|
|
|
static void gimp_layer_dispose (GObject *object);
|
2003-02-11 21:52:47 +08:00
|
|
|
static void gimp_layer_finalize (GObject *object);
|
2001-08-11 22:39:19 +08:00
|
|
|
|
2004-02-02 04:38:26 +08:00
|
|
|
static void gimp_layer_name_changed (GimpObject *object);
|
2003-11-17 01:51:36 +08:00
|
|
|
static gint64 gimp_layer_get_memsize (GimpObject *object,
|
|
|
|
gint64 *gui_size);
|
1998-01-22 15:02:57 +08:00
|
|
|
|
2003-02-11 21:52:47 +08:00
|
|
|
static void gimp_layer_invalidate_preview (GimpViewable *viewable);
|
2004-09-22 20:46:35 +08:00
|
|
|
static gchar * gimp_layer_get_description (GimpViewable *viewable,
|
|
|
|
gchar **tooltip);
|
2002-01-31 00:14:26 +08:00
|
|
|
|
2004-02-17 19:45:46 +08:00
|
|
|
static void gimp_layer_removed (GimpItem *item);
|
2009-08-30 01:47:52 +08:00
|
|
|
static gboolean gimp_layer_is_attached (const GimpItem *item);
|
2010-02-06 23:17:23 +08:00
|
|
|
static GimpItemTree * gimp_layer_get_tree (GimpItem *item);
|
2003-02-11 21:52:47 +08:00
|
|
|
static GimpItem * gimp_layer_duplicate (GimpItem *item,
|
2008-01-08 19:46:15 +08:00
|
|
|
GType new_type);
|
2005-01-14 02:17:24 +08:00
|
|
|
static void gimp_layer_convert (GimpItem *item,
|
|
|
|
GimpImage *dest_image);
|
2004-02-02 04:38:26 +08:00
|
|
|
static gboolean gimp_layer_rename (GimpItem *item,
|
2003-03-17 08:14:59 +08:00
|
|
|
const gchar *new_name,
|
2007-12-12 21:57:11 +08:00
|
|
|
const gchar *undo_desc,
|
|
|
|
GError **error);
|
2003-05-09 03:11:17 +08:00
|
|
|
static void gimp_layer_translate (GimpItem *item,
|
|
|
|
gint offset_x,
|
2003-05-09 21:05:37 +08:00
|
|
|
gint offset_y,
|
|
|
|
gboolean push_undo);
|
2003-05-07 19:09:00 +08:00
|
|
|
static void gimp_layer_scale (GimpItem *item,
|
|
|
|
gint new_width,
|
|
|
|
gint new_height,
|
|
|
|
gint new_offset_x,
|
|
|
|
gint new_offset_y,
|
2004-02-09 08:09:20 +08:00
|
|
|
GimpInterpolationType interp_type,
|
2004-08-11 02:47:21 +08:00
|
|
|
GimpProgress *progress);
|
2003-05-07 21:01:17 +08:00
|
|
|
static void gimp_layer_resize (GimpItem *item,
|
2004-04-15 07:37:34 +08:00
|
|
|
GimpContext *context,
|
2003-05-07 21:01:17 +08:00
|
|
|
gint new_width,
|
|
|
|
gint new_height,
|
|
|
|
gint offset_x,
|
|
|
|
gint offset_y);
|
2003-05-12 23:56:36 +08:00
|
|
|
static void gimp_layer_flip (GimpItem *item,
|
2004-04-15 07:37:34 +08:00
|
|
|
GimpContext *context,
|
2003-05-12 23:56:36 +08:00
|
|
|
GimpOrientationType flip_type,
|
2003-05-13 21:57:11 +08:00
|
|
|
gdouble axis,
|
|
|
|
gboolean clip_result);
|
2003-05-20 18:36:29 +08:00
|
|
|
static void gimp_layer_rotate (GimpItem *item,
|
2004-04-15 07:37:34 +08:00
|
|
|
GimpContext *context,
|
2003-05-20 18:36:29 +08:00
|
|
|
GimpRotationType rotate_type,
|
|
|
|
gdouble center_x,
|
|
|
|
gdouble center_y,
|
|
|
|
gboolean clip_result);
|
2003-05-12 23:56:36 +08:00
|
|
|
static void gimp_layer_transform (GimpItem *item,
|
2004-04-15 07:37:34 +08:00
|
|
|
GimpContext *context,
|
2003-07-07 21:50:48 +08:00
|
|
|
const GimpMatrix3 *matrix,
|
2003-05-12 23:56:36 +08:00
|
|
|
GimpTransformDirection direction,
|
|
|
|
GimpInterpolationType interpolation_type,
|
2004-03-14 01:45:58 +08:00
|
|
|
gint recursion_level,
|
2010-07-21 05:09:19 +08:00
|
|
|
GimpTransformResize clip_result,
|
2004-08-11 02:47:21 +08:00
|
|
|
GimpProgress *progress);
|
2010-07-21 05:09:19 +08:00
|
|
|
static void gimp_layer_to_selection (GimpItem *item,
|
|
|
|
GimpChannelOps op,
|
|
|
|
gboolean antialias,
|
|
|
|
gboolean feather,
|
|
|
|
gdouble feather_radius_x,
|
|
|
|
gdouble feather_radius_y);
|
2009-09-04 17:31:19 +08:00
|
|
|
static GeglNode * gimp_layer_get_node (GimpItem *item);
|
2007-12-04 19:30:31 +08:00
|
|
|
|
|
|
|
static gint64 gimp_layer_estimate_memsize (const GimpDrawable *drawable,
|
|
|
|
gint width,
|
|
|
|
gint height);
|
2003-10-06 22:40:12 +08:00
|
|
|
static void gimp_layer_invalidate_boundary (GimpDrawable *drawable);
|
|
|
|
static void gimp_layer_get_active_components (const GimpDrawable *drawable,
|
|
|
|
gboolean *active);
|
2009-09-12 03:28:52 +08:00
|
|
|
static void gimp_layer_convert_type (GimpDrawable *drawable,
|
|
|
|
GimpImage *dest_image,
|
2009-09-14 01:24:19 +08:00
|
|
|
GimpImageBaseType new_base_type,
|
|
|
|
gboolean push_undo);
|
2008-10-11 03:36:17 +08:00
|
|
|
|
2005-07-12 03:21:52 +08:00
|
|
|
static gint gimp_layer_get_opacity_at (GimpPickable *pickable,
|
|
|
|
gint x,
|
|
|
|
gint y);
|
2003-09-04 19:33:06 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
static void gimp_layer_transform_color (GimpImage *image,
|
2008-01-08 02:53:55 +08:00
|
|
|
PixelRegion *srcPR,
|
|
|
|
GimpImageType src_type,
|
|
|
|
PixelRegion *destPR,
|
|
|
|
GimpImageType dest_type);
|
2000-12-17 06:02:10 +08:00
|
|
|
|
To optimize duplicate and/or wrong image updates away, introduced new
2003-09-06 Michael Natterer <mitch@gimp.org>
To optimize duplicate and/or wrong image updates away, introduced
new policy that a child object must never explicitly update or
invalidate its parent object (just like the GUI is not updated
explicitly by the core):
* app/core/gimpdrawable.[ch]: added new signal
GimpDrawable::update(). Never update or invalidate the image when
the drawable is updated or invalidated.
(gimp_drawable_set_visible): don't gimp_drawable_update() the
drawable since its pixels have not changed.
* app/core/gimpimage.[ch]: connect to the "add" and "remove"
signals of the layers and channels containers. Also connect to the
"update" and "visibility_changed" signals of all drawables in
these containers (optimizes away updates issued by drawables which
are not yet added to the image and updates of the selection
mask). Also, don't propagate updates to the image if the emitting
drawable is invisible (optimizes away updates issued by invisible
drawables).
(gimp_image_add_layer,channel)
(gimp_image_remove_layer,channel): don't update the image since
that's done by our "add" and "remove" handlers now.
(gimp_image_position_layer,channel): update just the image, not
the drawable since its pixels have not changed.
(gimp_image_real_colormap_changed)
(gimp_image_set_component_visible): always call
gimp_image_update() *and* gimp_viewable_invalidate_preview() to
get everything updated, since update and invalidate of images are
not connected.
* app/core/gimpimage-undo-push.c (undo_pop_layer,channel): don't
update the drawable since (a) its pixels don't change and (b) the
image updates itself upon adding/removing now.
(undo_pop_layer_mod): replaced gimp_image_update() by
gimp_drawable_update() (just for consistency with other similar
functions).
* app/core/gimplayer.c: connect to "update" of the layer mask and
issue updates on the layer if the mask update has any effect on
the projection.
(gimp_layer_create_mask): don't set the mask's offsets here since
they may be different when we later add the mask to the layer.
* app/core/gimplayermask.c (gimp_layer_mask_set_layer): set the
mask offsets here instead.
* app/core/gimpchannel.c (gimp_channel_translate): update the
channel even if push_undo == FALSE.
* app/paint/gimppaintcore.c (gimp_paint_core_finish)
* app/tools/gimpinktool.c (ink_finish): invalidate both the
drawable and the image preview since invalidating the drawable
doesn't invalidate the image any more.
* app/text/gimptextlayer.c (gimp_text_layer_render_now): also
update the new extents of the text layer, not only the old one.
(gimp_text_layer_render_layout): don't update the drawable since
gimp_drawable_fill() already updated it.
2003-09-07 04:06:53 +08:00
|
|
|
static void gimp_layer_layer_mask_update (GimpDrawable *layer_mask,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint width,
|
|
|
|
gint height,
|
|
|
|
GimpLayer *layer);
|
|
|
|
|
2009-11-29 20:35:27 +08:00
|
|
|
static void gimp_layer_sync_mode_node (GimpLayer *layer);
|
|
|
|
|
2000-12-17 06:02:10 +08:00
|
|
|
|
2005-12-11 03:24:36 +08:00
|
|
|
G_DEFINE_TYPE_WITH_CODE (GimpLayer, gimp_layer, GIMP_TYPE_DRAWABLE,
|
|
|
|
G_IMPLEMENT_INTERFACE (GIMP_TYPE_PICKABLE,
|
2006-05-15 17:46:31 +08:00
|
|
|
gimp_layer_pickable_iface_init))
|
2001-03-05 04:06:48 +08:00
|
|
|
|
2005-12-11 03:24:36 +08:00
|
|
|
#define parent_class gimp_layer_parent_class
|
1998-01-22 15:02:57 +08:00
|
|
|
|
2005-12-11 03:24:36 +08:00
|
|
|
static guint layer_signals[LAST_SIGNAL] = { 0 };
|
2001-01-10 08:36:54 +08:00
|
|
|
|
1998-01-22 15:02:57 +08:00
|
|
|
|
|
|
|
static void
|
2000-12-29 00:19:55 +08:00
|
|
|
gimp_layer_class_init (GimpLayerClass *klass)
|
1998-01-22 15:02:57 +08:00
|
|
|
{
|
2004-03-17 00:23:06 +08:00
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);
|
|
|
|
GimpViewableClass *viewable_class = GIMP_VIEWABLE_CLASS (klass);
|
|
|
|
GimpItemClass *item_class = GIMP_ITEM_CLASS (klass);
|
|
|
|
GimpDrawableClass *drawable_class = GIMP_DRAWABLE_CLASS (klass);
|
1998-01-22 15:02:57 +08:00
|
|
|
|
2001-03-12 01:24:47 +08:00
|
|
|
layer_signals[OPACITY_CHANGED] =
|
2005-05-27 21:05:26 +08:00
|
|
|
g_signal_new ("opacity-changed",
|
2006-04-12 20:49:29 +08:00
|
|
|
G_TYPE_FROM_CLASS (klass),
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
G_STRUCT_OFFSET (GimpLayerClass, opacity_changed),
|
|
|
|
NULL, NULL,
|
|
|
|
gimp_marshal_VOID__VOID,
|
|
|
|
G_TYPE_NONE, 0);
|
2001-03-12 01:24:47 +08:00
|
|
|
|
|
|
|
layer_signals[MODE_CHANGED] =
|
2005-05-27 21:05:26 +08:00
|
|
|
g_signal_new ("mode-changed",
|
2006-04-12 20:49:29 +08:00
|
|
|
G_TYPE_FROM_CLASS (klass),
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
G_STRUCT_OFFSET (GimpLayerClass, mode_changed),
|
|
|
|
NULL, NULL,
|
|
|
|
gimp_marshal_VOID__VOID,
|
|
|
|
G_TYPE_NONE, 0);
|
2001-03-12 01:24:47 +08:00
|
|
|
|
2005-07-11 05:17:22 +08:00
|
|
|
layer_signals[LOCK_ALPHA_CHANGED] =
|
|
|
|
g_signal_new ("lock-alpha-changed",
|
2006-04-12 20:49:29 +08:00
|
|
|
G_TYPE_FROM_CLASS (klass),
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
G_STRUCT_OFFSET (GimpLayerClass, lock_alpha_changed),
|
|
|
|
NULL, NULL,
|
|
|
|
gimp_marshal_VOID__VOID,
|
|
|
|
G_TYPE_NONE, 0);
|
2001-03-12 01:24:47 +08:00
|
|
|
|
2001-03-05 04:06:48 +08:00
|
|
|
layer_signals[MASK_CHANGED] =
|
2005-05-27 21:05:26 +08:00
|
|
|
g_signal_new ("mask-changed",
|
2006-04-12 20:49:29 +08:00
|
|
|
G_TYPE_FROM_CLASS (klass),
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
G_STRUCT_OFFSET (GimpLayerClass, mask_changed),
|
|
|
|
NULL, NULL,
|
|
|
|
gimp_marshal_VOID__VOID,
|
|
|
|
G_TYPE_NONE, 0);
|
2001-03-05 04:06:48 +08:00
|
|
|
|
2005-07-12 00:46:28 +08:00
|
|
|
object_class->set_property = gimp_layer_set_property;
|
|
|
|
object_class->get_property = gimp_layer_get_property;
|
To optimize duplicate and/or wrong image updates away, introduced new
2003-09-06 Michael Natterer <mitch@gimp.org>
To optimize duplicate and/or wrong image updates away, introduced
new policy that a child object must never explicitly update or
invalidate its parent object (just like the GUI is not updated
explicitly by the core):
* app/core/gimpdrawable.[ch]: added new signal
GimpDrawable::update(). Never update or invalidate the image when
the drawable is updated or invalidated.
(gimp_drawable_set_visible): don't gimp_drawable_update() the
drawable since its pixels have not changed.
* app/core/gimpimage.[ch]: connect to the "add" and "remove"
signals of the layers and channels containers. Also connect to the
"update" and "visibility_changed" signals of all drawables in
these containers (optimizes away updates issued by drawables which
are not yet added to the image and updates of the selection
mask). Also, don't propagate updates to the image if the emitting
drawable is invisible (optimizes away updates issued by invisible
drawables).
(gimp_image_add_layer,channel)
(gimp_image_remove_layer,channel): don't update the image since
that's done by our "add" and "remove" handlers now.
(gimp_image_position_layer,channel): update just the image, not
the drawable since its pixels have not changed.
(gimp_image_real_colormap_changed)
(gimp_image_set_component_visible): always call
gimp_image_update() *and* gimp_viewable_invalidate_preview() to
get everything updated, since update and invalidate of images are
not connected.
* app/core/gimpimage-undo-push.c (undo_pop_layer,channel): don't
update the drawable since (a) its pixels don't change and (b) the
image updates itself upon adding/removing now.
(undo_pop_layer_mod): replaced gimp_image_update() by
gimp_drawable_update() (just for consistency with other similar
functions).
* app/core/gimplayer.c: connect to "update" of the layer mask and
issue updates on the layer if the mask update has any effect on
the projection.
(gimp_layer_create_mask): don't set the mask's offsets here since
they may be different when we later add the mask to the layer.
* app/core/gimplayermask.c (gimp_layer_mask_set_layer): set the
mask offsets here instead.
* app/core/gimpchannel.c (gimp_channel_translate): update the
channel even if push_undo == FALSE.
* app/paint/gimppaintcore.c (gimp_paint_core_finish)
* app/tools/gimpinktool.c (ink_finish): invalidate both the
drawable and the image preview since invalidating the drawable
doesn't invalidate the image any more.
* app/text/gimptextlayer.c (gimp_text_layer_render_now): also
update the new extents of the text layer, not only the old one.
(gimp_text_layer_render_layout): don't update the drawable since
gimp_drawable_fill() already updated it.
2003-09-07 04:06:53 +08:00
|
|
|
object_class->dispose = gimp_layer_dispose;
|
2003-09-04 19:33:06 +08:00
|
|
|
object_class->finalize = gimp_layer_finalize;
|
|
|
|
|
2004-02-02 04:38:26 +08:00
|
|
|
gimp_object_class->name_changed = gimp_layer_name_changed;
|
2003-09-04 19:33:06 +08:00
|
|
|
gimp_object_class->get_memsize = gimp_layer_get_memsize;
|
|
|
|
|
|
|
|
viewable_class->default_stock_id = "gimp-layer";
|
|
|
|
viewable_class->invalidate_preview = gimp_layer_invalidate_preview;
|
2004-09-22 20:46:35 +08:00
|
|
|
viewable_class->get_description = gimp_layer_get_description;
|
2003-09-04 19:33:06 +08:00
|
|
|
|
2004-02-17 19:45:46 +08:00
|
|
|
item_class->removed = gimp_layer_removed;
|
2004-01-27 00:18:16 +08:00
|
|
|
item_class->is_attached = gimp_layer_is_attached;
|
2010-02-06 23:17:23 +08:00
|
|
|
item_class->get_tree = gimp_layer_get_tree;
|
2003-09-04 19:33:06 +08:00
|
|
|
item_class->duplicate = gimp_layer_duplicate;
|
2005-01-14 02:17:24 +08:00
|
|
|
item_class->convert = gimp_layer_convert;
|
2003-09-04 19:33:06 +08:00
|
|
|
item_class->rename = gimp_layer_rename;
|
|
|
|
item_class->translate = gimp_layer_translate;
|
|
|
|
item_class->scale = gimp_layer_scale;
|
|
|
|
item_class->resize = gimp_layer_resize;
|
|
|
|
item_class->flip = gimp_layer_flip;
|
|
|
|
item_class->rotate = gimp_layer_rotate;
|
|
|
|
item_class->transform = gimp_layer_transform;
|
2010-07-21 05:09:19 +08:00
|
|
|
item_class->to_selection = gimp_layer_to_selection;
|
2008-11-03 00:39:38 +08:00
|
|
|
item_class->get_node = gimp_layer_get_node;
|
2003-09-04 19:33:06 +08:00
|
|
|
item_class->default_name = _("Layer");
|
2010-06-08 19:24:11 +08:00
|
|
|
item_class->rename_desc = C_("undo-type", "Rename Layer");
|
|
|
|
item_class->translate_desc = C_("undo-type", "Move Layer");
|
|
|
|
item_class->scale_desc = C_("undo-type", "Scale Layer");
|
|
|
|
item_class->resize_desc = C_("undo-type", "Resize Layer");
|
|
|
|
item_class->flip_desc = C_("undo-type", "Flip Layer");
|
|
|
|
item_class->rotate_desc = C_("undo-type", "Rotate Layer");
|
|
|
|
item_class->transform_desc = C_("undo-type", "Transform Layer");
|
2010-07-21 05:09:19 +08:00
|
|
|
item_class->to_selection_desc = C_("undo-type", "Alpha to Selection");
|
2010-07-09 00:08:13 +08:00
|
|
|
item_class->reorder_desc = C_("undo-type", "Reorder Layer");
|
|
|
|
item_class->raise_desc = C_("undo-type", "Raise Layer");
|
|
|
|
item_class->raise_to_top_desc = C_("undo-type", "Raise Layer to Top");
|
|
|
|
item_class->lower_desc = C_("undo-type", "Lower Layer");
|
|
|
|
item_class->lower_to_bottom_desc = C_("undo-type", "Lower Layer to Bottom");
|
|
|
|
item_class->raise_failed = _("Layer cannot be raised higher.");
|
|
|
|
item_class->lower_failed = _("Layer cannot be lowered more.");
|
2003-09-04 19:33:06 +08:00
|
|
|
|
2007-12-04 19:30:31 +08:00
|
|
|
drawable_class->estimate_memsize = gimp_layer_estimate_memsize;
|
2003-10-06 22:40:12 +08:00
|
|
|
drawable_class->invalidate_boundary = gimp_layer_invalidate_boundary;
|
|
|
|
drawable_class->get_active_components = gimp_layer_get_active_components;
|
2009-09-12 03:28:52 +08:00
|
|
|
drawable_class->convert_type = gimp_layer_convert_type;
|
2008-11-08 08:16:40 +08:00
|
|
|
drawable_class->project_region = gimp_layer_project_region;
|
2003-09-04 19:33:06 +08:00
|
|
|
|
|
|
|
klass->opacity_changed = NULL;
|
|
|
|
klass->mode_changed = NULL;
|
2005-07-11 05:17:22 +08:00
|
|
|
klass->lock_alpha_changed = NULL;
|
2003-09-04 19:33:06 +08:00
|
|
|
klass->mask_changed = NULL;
|
2005-07-12 00:46:28 +08:00
|
|
|
|
|
|
|
g_object_class_install_property (object_class, PROP_OPACITY,
|
|
|
|
g_param_spec_double ("opacity", NULL, NULL,
|
|
|
|
GIMP_OPACITY_TRANSPARENT,
|
|
|
|
GIMP_OPACITY_OPAQUE,
|
|
|
|
GIMP_OPACITY_OPAQUE,
|
2006-01-19 04:29:40 +08:00
|
|
|
GIMP_PARAM_READABLE));
|
2005-07-12 00:46:28 +08:00
|
|
|
|
|
|
|
g_object_class_install_property (object_class, PROP_MODE,
|
|
|
|
g_param_spec_enum ("mode", NULL, NULL,
|
|
|
|
GIMP_TYPE_LAYER_MODE_EFFECTS,
|
|
|
|
GIMP_NORMAL_MODE,
|
2006-01-19 04:29:40 +08:00
|
|
|
GIMP_PARAM_READABLE));
|
2005-07-12 00:46:28 +08:00
|
|
|
|
|
|
|
g_object_class_install_property (object_class, PROP_LOCK_ALPHA,
|
|
|
|
g_param_spec_boolean ("lock-alpha",
|
|
|
|
NULL, NULL,
|
|
|
|
FALSE,
|
2006-01-19 04:29:40 +08:00
|
|
|
GIMP_PARAM_READABLE));
|
2008-11-17 08:02:15 +08:00
|
|
|
|
2008-11-20 07:37:15 +08:00
|
|
|
g_object_class_install_property (object_class, PROP_MASK,
|
|
|
|
g_param_spec_object ("mask",
|
|
|
|
NULL, NULL,
|
|
|
|
GIMP_TYPE_LAYER_MASK,
|
|
|
|
GIMP_PARAM_READABLE));
|
|
|
|
|
2008-11-17 08:02:15 +08:00
|
|
|
g_object_class_install_property (object_class, PROP_FLOATING_SELECTION,
|
|
|
|
g_param_spec_boolean ("floating-selection",
|
|
|
|
NULL, NULL,
|
|
|
|
FALSE,
|
|
|
|
GIMP_PARAM_READABLE));
|
1998-01-22 15:02:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_layer_init (GimpLayer *layer)
|
|
|
|
{
|
2005-07-11 05:17:22 +08:00
|
|
|
layer->opacity = GIMP_OPACITY_OPAQUE;
|
|
|
|
layer->mode = GIMP_NORMAL_MODE;
|
|
|
|
layer->lock_alpha = FALSE;
|
1998-01-22 15:02:57 +08:00
|
|
|
|
2005-07-11 05:17:22 +08:00
|
|
|
layer->mask = NULL;
|
1998-01-22 15:02:57 +08:00
|
|
|
|
2001-01-29 00:44:22 +08:00
|
|
|
/* floating selection */
|
|
|
|
layer->fs.drawable = NULL;
|
|
|
|
layer->fs.boundary_known = FALSE;
|
|
|
|
layer->fs.segs = NULL;
|
|
|
|
layer->fs.num_segs = 0;
|
1998-01-22 15:02:57 +08:00
|
|
|
}
|
|
|
|
|
2005-07-12 03:21:52 +08:00
|
|
|
static void
|
2005-12-11 03:24:36 +08:00
|
|
|
gimp_layer_pickable_iface_init (GimpPickableInterface *iface)
|
2005-07-12 03:21:52 +08:00
|
|
|
{
|
2005-12-11 03:24:36 +08:00
|
|
|
iface->get_opacity_at = gimp_layer_get_opacity_at;
|
2005-07-12 03:21:52 +08:00
|
|
|
}
|
|
|
|
|
2005-07-12 00:46:28 +08:00
|
|
|
static void
|
|
|
|
gimp_layer_set_property (GObject *object,
|
|
|
|
guint property_id,
|
|
|
|
const GValue *value,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
|
|
|
switch (property_id)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_layer_get_property (GObject *object,
|
|
|
|
guint property_id,
|
|
|
|
GValue *value,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
|
|
|
GimpLayer *layer = GIMP_LAYER (object);
|
|
|
|
|
|
|
|
switch (property_id)
|
|
|
|
{
|
|
|
|
case PROP_OPACITY:
|
2008-11-17 08:02:15 +08:00
|
|
|
g_value_set_double (value, gimp_layer_get_opacity (layer));
|
2005-07-12 00:46:28 +08:00
|
|
|
break;
|
|
|
|
case PROP_MODE:
|
2008-11-17 08:02:15 +08:00
|
|
|
g_value_set_enum (value, gimp_layer_get_mode (layer));
|
2005-07-12 00:46:28 +08:00
|
|
|
break;
|
|
|
|
case PROP_LOCK_ALPHA:
|
2008-11-17 08:02:15 +08:00
|
|
|
g_value_set_boolean (value, gimp_layer_get_lock_alpha (layer));
|
|
|
|
break;
|
2008-11-20 07:37:15 +08:00
|
|
|
case PROP_MASK:
|
|
|
|
g_value_set_object (value, gimp_layer_get_mask (layer));
|
|
|
|
break;
|
2008-11-17 08:02:15 +08:00
|
|
|
case PROP_FLOATING_SELECTION:
|
|
|
|
g_value_set_boolean (value, gimp_layer_is_floating_sel (layer));
|
2005-07-12 00:46:28 +08:00
|
|
|
break;
|
2008-11-17 08:02:15 +08:00
|
|
|
|
2005-07-12 00:46:28 +08:00
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
To optimize duplicate and/or wrong image updates away, introduced new
2003-09-06 Michael Natterer <mitch@gimp.org>
To optimize duplicate and/or wrong image updates away, introduced
new policy that a child object must never explicitly update or
invalidate its parent object (just like the GUI is not updated
explicitly by the core):
* app/core/gimpdrawable.[ch]: added new signal
GimpDrawable::update(). Never update or invalidate the image when
the drawable is updated or invalidated.
(gimp_drawable_set_visible): don't gimp_drawable_update() the
drawable since its pixels have not changed.
* app/core/gimpimage.[ch]: connect to the "add" and "remove"
signals of the layers and channels containers. Also connect to the
"update" and "visibility_changed" signals of all drawables in
these containers (optimizes away updates issued by drawables which
are not yet added to the image and updates of the selection
mask). Also, don't propagate updates to the image if the emitting
drawable is invisible (optimizes away updates issued by invisible
drawables).
(gimp_image_add_layer,channel)
(gimp_image_remove_layer,channel): don't update the image since
that's done by our "add" and "remove" handlers now.
(gimp_image_position_layer,channel): update just the image, not
the drawable since its pixels have not changed.
(gimp_image_real_colormap_changed)
(gimp_image_set_component_visible): always call
gimp_image_update() *and* gimp_viewable_invalidate_preview() to
get everything updated, since update and invalidate of images are
not connected.
* app/core/gimpimage-undo-push.c (undo_pop_layer,channel): don't
update the drawable since (a) its pixels don't change and (b) the
image updates itself upon adding/removing now.
(undo_pop_layer_mod): replaced gimp_image_update() by
gimp_drawable_update() (just for consistency with other similar
functions).
* app/core/gimplayer.c: connect to "update" of the layer mask and
issue updates on the layer if the mask update has any effect on
the projection.
(gimp_layer_create_mask): don't set the mask's offsets here since
they may be different when we later add the mask to the layer.
* app/core/gimplayermask.c (gimp_layer_mask_set_layer): set the
mask offsets here instead.
* app/core/gimpchannel.c (gimp_channel_translate): update the
channel even if push_undo == FALSE.
* app/paint/gimppaintcore.c (gimp_paint_core_finish)
* app/tools/gimpinktool.c (ink_finish): invalidate both the
drawable and the image preview since invalidating the drawable
doesn't invalidate the image any more.
* app/text/gimptextlayer.c (gimp_text_layer_render_now): also
update the new extents of the text layer, not only the old one.
(gimp_text_layer_render_layout): don't update the drawable since
gimp_drawable_fill() already updated it.
2003-09-07 04:06:53 +08:00
|
|
|
static void
|
|
|
|
gimp_layer_dispose (GObject *object)
|
|
|
|
{
|
|
|
|
GimpLayer *layer = GIMP_LAYER (object);
|
|
|
|
|
|
|
|
if (layer->mask)
|
|
|
|
g_signal_handlers_disconnect_by_func (layer->mask,
|
|
|
|
gimp_layer_layer_mask_update,
|
|
|
|
layer);
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
|
|
|
}
|
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
static void
|
|
|
|
gimp_layer_finalize (GObject *object)
|
|
|
|
{
|
2003-09-02 21:43:26 +08:00
|
|
|
GimpLayer *layer = GIMP_LAYER (object);
|
2001-08-11 22:39:19 +08:00
|
|
|
|
|
|
|
if (layer->mask)
|
|
|
|
{
|
2003-01-06 06:07:10 +08:00
|
|
|
g_object_unref (layer->mask);
|
2001-08-11 22:39:19 +08:00
|
|
|
layer->mask = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (layer->fs.segs)
|
|
|
|
{
|
|
|
|
g_free (layer->fs.segs);
|
To optimize duplicate and/or wrong image updates away, introduced new
2003-09-06 Michael Natterer <mitch@gimp.org>
To optimize duplicate and/or wrong image updates away, introduced
new policy that a child object must never explicitly update or
invalidate its parent object (just like the GUI is not updated
explicitly by the core):
* app/core/gimpdrawable.[ch]: added new signal
GimpDrawable::update(). Never update or invalidate the image when
the drawable is updated or invalidated.
(gimp_drawable_set_visible): don't gimp_drawable_update() the
drawable since its pixels have not changed.
* app/core/gimpimage.[ch]: connect to the "add" and "remove"
signals of the layers and channels containers. Also connect to the
"update" and "visibility_changed" signals of all drawables in
these containers (optimizes away updates issued by drawables which
are not yet added to the image and updates of the selection
mask). Also, don't propagate updates to the image if the emitting
drawable is invisible (optimizes away updates issued by invisible
drawables).
(gimp_image_add_layer,channel)
(gimp_image_remove_layer,channel): don't update the image since
that's done by our "add" and "remove" handlers now.
(gimp_image_position_layer,channel): update just the image, not
the drawable since its pixels have not changed.
(gimp_image_real_colormap_changed)
(gimp_image_set_component_visible): always call
gimp_image_update() *and* gimp_viewable_invalidate_preview() to
get everything updated, since update and invalidate of images are
not connected.
* app/core/gimpimage-undo-push.c (undo_pop_layer,channel): don't
update the drawable since (a) its pixels don't change and (b) the
image updates itself upon adding/removing now.
(undo_pop_layer_mod): replaced gimp_image_update() by
gimp_drawable_update() (just for consistency with other similar
functions).
* app/core/gimplayer.c: connect to "update" of the layer mask and
issue updates on the layer if the mask update has any effect on
the projection.
(gimp_layer_create_mask): don't set the mask's offsets here since
they may be different when we later add the mask to the layer.
* app/core/gimplayermask.c (gimp_layer_mask_set_layer): set the
mask offsets here instead.
* app/core/gimpchannel.c (gimp_channel_translate): update the
channel even if push_undo == FALSE.
* app/paint/gimppaintcore.c (gimp_paint_core_finish)
* app/tools/gimpinktool.c (ink_finish): invalidate both the
drawable and the image preview since invalidating the drawable
doesn't invalidate the image any more.
* app/text/gimptextlayer.c (gimp_text_layer_render_now): also
update the new extents of the text layer, not only the old one.
(gimp_text_layer_render_layout): don't update the drawable since
gimp_drawable_fill() already updated it.
2003-09-07 04:06:53 +08:00
|
|
|
layer->fs.segs = NULL;
|
|
|
|
layer->fs.num_segs = 0;
|
2001-08-11 22:39:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
|
|
|
}
|
|
|
|
|
2004-02-02 04:38:26 +08:00
|
|
|
static void
|
|
|
|
gimp_layer_name_changed (GimpObject *object)
|
|
|
|
{
|
|
|
|
GimpLayer *layer = GIMP_LAYER (object);
|
|
|
|
|
2004-05-24 18:49:34 +08:00
|
|
|
if (GIMP_OBJECT_CLASS (parent_class)->name_changed)
|
|
|
|
GIMP_OBJECT_CLASS (parent_class)->name_changed (object);
|
2004-02-02 04:38:26 +08:00
|
|
|
|
|
|
|
if (layer->mask)
|
|
|
|
{
|
2006-04-07 18:51:22 +08:00
|
|
|
gchar *mask_name = g_strdup_printf (_("%s mask"),
|
|
|
|
gimp_object_get_name (object));
|
2004-02-02 04:38:26 +08:00
|
|
|
|
2006-04-07 18:51:22 +08:00
|
|
|
gimp_object_take_name (GIMP_OBJECT (layer->mask), mask_name);
|
2004-02-02 04:38:26 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-11-17 01:51:36 +08:00
|
|
|
static gint64
|
2003-08-25 18:49:33 +08:00
|
|
|
gimp_layer_get_memsize (GimpObject *object,
|
2003-11-17 01:51:36 +08:00
|
|
|
gint64 *gui_size)
|
2002-01-31 00:14:26 +08:00
|
|
|
{
|
2004-02-02 04:38:26 +08:00
|
|
|
GimpLayer *layer = GIMP_LAYER (object);
|
2003-11-17 01:51:36 +08:00
|
|
|
gint64 memsize = 0;
|
2002-01-31 00:14:26 +08:00
|
|
|
|
2007-11-17 02:19:30 +08:00
|
|
|
memsize += gimp_object_get_memsize (GIMP_OBJECT (layer->mask), gui_size);
|
2002-01-31 00:14:26 +08:00
|
|
|
|
2003-08-25 18:49:33 +08:00
|
|
|
*gui_size += layer->fs.num_segs * sizeof (BoundSeg);
|
2002-01-31 00:14:26 +08:00
|
|
|
|
2003-08-25 18:49:33 +08:00
|
|
|
return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
|
|
|
|
gui_size);
|
2002-01-31 00:14:26 +08:00
|
|
|
}
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
static void
|
2001-02-05 06:10:54 +08:00
|
|
|
gimp_layer_invalidate_preview (GimpViewable *viewable)
|
1998-01-22 15:02:57 +08:00
|
|
|
{
|
To optimize duplicate and/or wrong image updates away, introduced new
2003-09-06 Michael Natterer <mitch@gimp.org>
To optimize duplicate and/or wrong image updates away, introduced
new policy that a child object must never explicitly update or
invalidate its parent object (just like the GUI is not updated
explicitly by the core):
* app/core/gimpdrawable.[ch]: added new signal
GimpDrawable::update(). Never update or invalidate the image when
the drawable is updated or invalidated.
(gimp_drawable_set_visible): don't gimp_drawable_update() the
drawable since its pixels have not changed.
* app/core/gimpimage.[ch]: connect to the "add" and "remove"
signals of the layers and channels containers. Also connect to the
"update" and "visibility_changed" signals of all drawables in
these containers (optimizes away updates issued by drawables which
are not yet added to the image and updates of the selection
mask). Also, don't propagate updates to the image if the emitting
drawable is invisible (optimizes away updates issued by invisible
drawables).
(gimp_image_add_layer,channel)
(gimp_image_remove_layer,channel): don't update the image since
that's done by our "add" and "remove" handlers now.
(gimp_image_position_layer,channel): update just the image, not
the drawable since its pixels have not changed.
(gimp_image_real_colormap_changed)
(gimp_image_set_component_visible): always call
gimp_image_update() *and* gimp_viewable_invalidate_preview() to
get everything updated, since update and invalidate of images are
not connected.
* app/core/gimpimage-undo-push.c (undo_pop_layer,channel): don't
update the drawable since (a) its pixels don't change and (b) the
image updates itself upon adding/removing now.
(undo_pop_layer_mod): replaced gimp_image_update() by
gimp_drawable_update() (just for consistency with other similar
functions).
* app/core/gimplayer.c: connect to "update" of the layer mask and
issue updates on the layer if the mask update has any effect on
the projection.
(gimp_layer_create_mask): don't set the mask's offsets here since
they may be different when we later add the mask to the layer.
* app/core/gimplayermask.c (gimp_layer_mask_set_layer): set the
mask offsets here instead.
* app/core/gimpchannel.c (gimp_channel_translate): update the
channel even if push_undo == FALSE.
* app/paint/gimppaintcore.c (gimp_paint_core_finish)
* app/tools/gimpinktool.c (ink_finish): invalidate both the
drawable and the image preview since invalidating the drawable
doesn't invalidate the image any more.
* app/text/gimptextlayer.c (gimp_text_layer_render_now): also
update the new extents of the text layer, not only the old one.
(gimp_text_layer_render_layout): don't update the drawable since
gimp_drawable_fill() already updated it.
2003-09-07 04:06:53 +08:00
|
|
|
GimpLayer *layer = GIMP_LAYER (viewable);
|
2002-06-07 03:07:59 +08:00
|
|
|
|
2009-09-02 05:35:26 +08:00
|
|
|
GIMP_VIEWABLE_CLASS (parent_class)->invalidate_preview (viewable);
|
2001-06-18 21:10:03 +08:00
|
|
|
|
2001-01-29 07:25:25 +08:00
|
|
|
if (gimp_layer_is_floating_sel (layer))
|
2001-06-18 21:10:03 +08:00
|
|
|
floating_sel_invalidate (layer);
|
1998-01-22 15:02:57 +08:00
|
|
|
}
|
|
|
|
|
2004-09-22 20:46:35 +08:00
|
|
|
static gchar *
|
|
|
|
gimp_layer_get_description (GimpViewable *viewable,
|
|
|
|
gchar **tooltip)
|
|
|
|
{
|
|
|
|
if (gimp_layer_is_floating_sel (GIMP_LAYER (viewable)))
|
|
|
|
{
|
|
|
|
return g_strdup_printf (_("Floating Selection\n(%s)"),
|
2009-09-01 04:47:18 +08:00
|
|
|
gimp_object_get_name (viewable));
|
2004-09-22 20:46:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return GIMP_VIEWABLE_CLASS (parent_class)->get_description (viewable,
|
|
|
|
tooltip);
|
|
|
|
}
|
|
|
|
|
2004-02-17 19:45:46 +08:00
|
|
|
static void
|
|
|
|
gimp_layer_removed (GimpItem *item)
|
|
|
|
{
|
|
|
|
GimpLayer *layer = GIMP_LAYER (item);
|
|
|
|
|
|
|
|
if (layer->mask)
|
|
|
|
gimp_item_removed (GIMP_ITEM (layer->mask));
|
|
|
|
|
|
|
|
if (GIMP_ITEM_CLASS (parent_class)->removed)
|
|
|
|
GIMP_ITEM_CLASS (parent_class)->removed (item);
|
|
|
|
}
|
|
|
|
|
2004-01-27 00:18:16 +08:00
|
|
|
static gboolean
|
2009-08-30 01:47:52 +08:00
|
|
|
gimp_layer_is_attached (const GimpItem *item)
|
2004-01-27 00:18:16 +08:00
|
|
|
{
|
2010-02-04 06:00:31 +08:00
|
|
|
GimpImage *image = gimp_item_get_image (item);
|
|
|
|
|
|
|
|
return (GIMP_IS_IMAGE (image) &&
|
|
|
|
gimp_container_have (gimp_image_get_layers (image),
|
2009-08-30 01:47:52 +08:00
|
|
|
GIMP_OBJECT (item)));
|
2004-01-27 00:18:16 +08:00
|
|
|
}
|
|
|
|
|
2010-02-06 23:17:23 +08:00
|
|
|
static GimpItemTree *
|
|
|
|
gimp_layer_get_tree (GimpItem *item)
|
2009-08-02 02:22:07 +08:00
|
|
|
{
|
|
|
|
if (gimp_item_is_attached (item))
|
|
|
|
{
|
|
|
|
GimpImage *image = gimp_item_get_image (item);
|
|
|
|
|
2010-02-06 23:17:23 +08:00
|
|
|
return gimp_image_get_layer_tree (image);
|
2009-08-02 02:22:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2003-02-11 21:52:47 +08:00
|
|
|
static GimpItem *
|
|
|
|
gimp_layer_duplicate (GimpItem *item,
|
2008-01-08 19:46:15 +08:00
|
|
|
GType new_type)
|
2003-02-11 21:52:47 +08:00
|
|
|
{
|
2005-12-23 09:15:19 +08:00
|
|
|
GimpItem *new_item;
|
2003-02-11 21:52:47 +08:00
|
|
|
|
|
|
|
g_return_val_if_fail (g_type_is_a (new_type, GIMP_TYPE_DRAWABLE), NULL);
|
|
|
|
|
2008-01-08 19:46:15 +08:00
|
|
|
new_item = GIMP_ITEM_CLASS (parent_class)->duplicate (item, new_type);
|
2003-02-11 21:52:47 +08:00
|
|
|
|
2005-12-23 09:15:19 +08:00
|
|
|
if (GIMP_IS_LAYER (new_item))
|
2003-02-11 21:52:47 +08:00
|
|
|
{
|
2006-02-13 00:07:39 +08:00
|
|
|
GimpLayer *layer = GIMP_LAYER (item);
|
2005-12-23 09:15:19 +08:00
|
|
|
GimpLayer *new_layer = GIMP_LAYER (new_item);
|
|
|
|
|
2009-09-09 04:09:03 +08:00
|
|
|
gimp_layer_set_mode (new_layer, gimp_layer_get_mode (layer), FALSE);
|
|
|
|
gimp_layer_set_opacity (new_layer, gimp_layer_get_opacity (layer), FALSE);
|
|
|
|
|
|
|
|
if (gimp_layer_can_lock_alpha (new_layer))
|
|
|
|
gimp_layer_set_lock_alpha (new_layer,
|
|
|
|
gimp_layer_get_lock_alpha (layer), FALSE);
|
2005-12-23 09:15:19 +08:00
|
|
|
|
|
|
|
/* duplicate the layer mask if necessary */
|
|
|
|
if (layer->mask)
|
|
|
|
{
|
2008-01-08 19:46:15 +08:00
|
|
|
GimpItem *mask;
|
|
|
|
|
|
|
|
mask = gimp_item_duplicate (GIMP_ITEM (layer->mask),
|
|
|
|
G_TYPE_FROM_INSTANCE (layer->mask));
|
2008-09-16 05:05:01 +08:00
|
|
|
gimp_layer_add_mask (new_layer, GIMP_LAYER_MASK (mask), FALSE, NULL);
|
2005-12-23 09:15:19 +08:00
|
|
|
}
|
2003-02-11 21:52:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return new_item;
|
|
|
|
}
|
|
|
|
|
2004-12-23 19:53:14 +08:00
|
|
|
static void
|
2005-01-14 02:17:24 +08:00
|
|
|
gimp_layer_convert (GimpItem *item,
|
|
|
|
GimpImage *dest_image)
|
2003-08-28 01:21:49 +08:00
|
|
|
{
|
2004-12-23 19:53:14 +08:00
|
|
|
GimpLayer *layer = GIMP_LAYER (item);
|
|
|
|
GimpDrawable *drawable = GIMP_DRAWABLE (item);
|
|
|
|
GimpImageBaseType old_base_type;
|
2003-08-28 01:21:49 +08:00
|
|
|
GimpImageBaseType new_base_type;
|
|
|
|
|
2004-12-23 19:53:14 +08:00
|
|
|
old_base_type = GIMP_IMAGE_TYPE_BASE_TYPE (gimp_drawable_type (drawable));
|
2005-01-14 02:17:24 +08:00
|
|
|
new_base_type = gimp_image_base_type (dest_image);
|
2003-08-28 01:21:49 +08:00
|
|
|
|
2004-12-23 19:53:14 +08:00
|
|
|
if (old_base_type != new_base_type)
|
2009-09-14 01:24:19 +08:00
|
|
|
gimp_drawable_convert_type (drawable, dest_image, new_base_type, FALSE);
|
2003-08-28 01:21:49 +08:00
|
|
|
|
2005-01-14 02:17:24 +08:00
|
|
|
if (layer->mask)
|
|
|
|
gimp_item_set_image (GIMP_ITEM (layer->mask), dest_image);
|
|
|
|
|
|
|
|
GIMP_ITEM_CLASS (parent_class)->convert (item, dest_image);
|
2003-08-28 01:21:49 +08:00
|
|
|
}
|
|
|
|
|
2004-02-02 04:38:26 +08:00
|
|
|
static gboolean
|
2007-12-12 21:57:11 +08:00
|
|
|
gimp_layer_rename (GimpItem *item,
|
|
|
|
const gchar *new_name,
|
|
|
|
const gchar *undo_desc,
|
|
|
|
GError **error)
|
2003-03-17 08:14:59 +08:00
|
|
|
{
|
2004-02-02 04:38:26 +08:00
|
|
|
GimpLayer *layer = GIMP_LAYER (item);
|
2006-03-29 01:08:36 +08:00
|
|
|
GimpImage *image = gimp_item_get_image (item);
|
2004-02-02 04:38:26 +08:00
|
|
|
gboolean attached;
|
|
|
|
gboolean floating_sel;
|
2003-03-17 08:14:59 +08:00
|
|
|
|
2004-02-02 04:38:26 +08:00
|
|
|
attached = gimp_item_is_attached (item);
|
|
|
|
floating_sel = gimp_layer_is_floating_sel (layer);
|
|
|
|
|
|
|
|
if (floating_sel)
|
2003-03-17 08:14:59 +08:00
|
|
|
{
|
2009-01-27 06:47:16 +08:00
|
|
|
if (GIMP_IS_CHANNEL (gimp_layer_get_floating_sel_drawable (layer)))
|
2007-12-12 21:57:11 +08:00
|
|
|
{
|
2008-11-12 18:56:06 +08:00
|
|
|
g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
|
2008-11-04 20:33:09 +08:00
|
|
|
_("Cannot create a new layer from the floating "
|
|
|
|
"selection because it belongs to a layer mask "
|
|
|
|
"or channel."));
|
2007-12-12 21:57:11 +08:00
|
|
|
return FALSE;
|
|
|
|
}
|
2004-02-02 04:38:26 +08:00
|
|
|
|
|
|
|
if (attached)
|
|
|
|
{
|
2006-03-29 01:08:36 +08:00
|
|
|
gimp_image_undo_group_start (image,
|
2004-02-02 04:38:26 +08:00
|
|
|
GIMP_UNDO_GROUP_ITEM_PROPERTIES,
|
|
|
|
undo_desc);
|
2003-03-17 08:14:59 +08:00
|
|
|
|
2007-12-07 02:00:10 +08:00
|
|
|
floating_sel_to_layer (layer, NULL);
|
2004-02-02 04:38:26 +08:00
|
|
|
}
|
2003-03-17 08:14:59 +08:00
|
|
|
}
|
|
|
|
|
2007-12-12 21:57:11 +08:00
|
|
|
GIMP_ITEM_CLASS (parent_class)->rename (item, new_name, undo_desc, error);
|
2003-03-17 08:14:59 +08:00
|
|
|
|
2004-02-02 04:38:26 +08:00
|
|
|
if (attached && floating_sel)
|
2006-03-29 01:08:36 +08:00
|
|
|
gimp_image_undo_group_end (image);
|
2004-02-02 04:38:26 +08:00
|
|
|
|
|
|
|
return TRUE;
|
2003-03-17 08:14:59 +08:00
|
|
|
}
|
|
|
|
|
2003-05-09 03:11:17 +08:00
|
|
|
static void
|
|
|
|
gimp_layer_translate (GimpItem *item,
|
2006-04-12 20:49:29 +08:00
|
|
|
gint offset_x,
|
|
|
|
gint offset_y,
|
2003-05-09 21:05:37 +08:00
|
|
|
gboolean push_undo)
|
2003-05-09 03:11:17 +08:00
|
|
|
{
|
2004-02-02 04:38:26 +08:00
|
|
|
GimpLayer *layer = GIMP_LAYER (item);
|
2003-05-09 03:11:17 +08:00
|
|
|
|
2003-05-09 21:05:37 +08:00
|
|
|
if (push_undo)
|
2004-04-13 19:43:27 +08:00
|
|
|
gimp_image_undo_push_item_displace (gimp_item_get_image (item), NULL, item);
|
2003-05-09 21:05:37 +08:00
|
|
|
|
2003-05-09 03:11:17 +08:00
|
|
|
/* update the old region */
|
2007-12-24 00:58:41 +08:00
|
|
|
gimp_drawable_update (GIMP_DRAWABLE (layer),
|
|
|
|
0, 0,
|
2008-11-03 08:09:01 +08:00
|
|
|
gimp_item_get_width (item),
|
|
|
|
gimp_item_get_height (item));
|
2003-05-09 03:11:17 +08:00
|
|
|
|
|
|
|
/* invalidate the selection boundary because of a layer modification */
|
2003-09-04 19:33:06 +08:00
|
|
|
gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (layer));
|
2003-05-09 03:11:17 +08:00
|
|
|
|
2003-05-09 21:05:37 +08:00
|
|
|
GIMP_ITEM_CLASS (parent_class)->translate (item, offset_x, offset_y,
|
|
|
|
push_undo);
|
2003-05-09 03:11:17 +08:00
|
|
|
|
|
|
|
/* update the new region */
|
2007-12-24 00:58:41 +08:00
|
|
|
gimp_drawable_update (GIMP_DRAWABLE (layer),
|
|
|
|
0, 0,
|
2008-11-03 08:09:01 +08:00
|
|
|
gimp_item_get_width (item),
|
|
|
|
gimp_item_get_height (item));
|
2003-05-09 03:11:17 +08:00
|
|
|
|
2003-08-28 01:21:49 +08:00
|
|
|
if (layer->mask)
|
2003-05-09 03:11:17 +08:00
|
|
|
{
|
2008-11-04 05:17:50 +08:00
|
|
|
gint off_x, off_y;
|
|
|
|
|
|
|
|
gimp_item_get_offset (item, &off_x, &off_y);
|
|
|
|
gimp_item_set_offset (GIMP_ITEM (layer->mask), off_x, off_y);
|
2003-05-09 03:11:17 +08:00
|
|
|
|
|
|
|
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (layer->mask));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-05-07 19:09:00 +08:00
|
|
|
static void
|
|
|
|
gimp_layer_scale (GimpItem *item,
|
|
|
|
gint new_width,
|
|
|
|
gint new_height,
|
|
|
|
gint new_offset_x,
|
|
|
|
gint new_offset_y,
|
2004-02-09 08:09:20 +08:00
|
|
|
GimpInterpolationType interpolation_type,
|
2004-08-11 02:47:21 +08:00
|
|
|
GimpProgress *progress)
|
2003-05-07 19:09:00 +08:00
|
|
|
{
|
2004-04-13 19:43:27 +08:00
|
|
|
GimpLayer *layer = GIMP_LAYER (item);
|
2003-05-07 19:09:00 +08:00
|
|
|
|
|
|
|
GIMP_ITEM_CLASS (parent_class)->scale (item, new_width, new_height,
|
|
|
|
new_offset_x, new_offset_y,
|
2004-08-11 02:47:21 +08:00
|
|
|
interpolation_type, progress);
|
2003-05-07 19:09:00 +08:00
|
|
|
|
|
|
|
if (layer->mask)
|
2004-04-13 19:43:27 +08:00
|
|
|
gimp_item_scale (GIMP_ITEM (layer->mask),
|
|
|
|
new_width, new_height,
|
|
|
|
new_offset_x, new_offset_y,
|
2004-08-11 02:47:21 +08:00
|
|
|
interpolation_type, progress);
|
2003-05-07 19:09:00 +08:00
|
|
|
}
|
|
|
|
|
2003-05-07 21:01:17 +08:00
|
|
|
static void
|
2004-04-15 07:37:34 +08:00
|
|
|
gimp_layer_resize (GimpItem *item,
|
|
|
|
GimpContext *context,
|
2006-04-12 20:49:29 +08:00
|
|
|
gint new_width,
|
|
|
|
gint new_height,
|
|
|
|
gint offset_x,
|
|
|
|
gint offset_y)
|
2003-05-07 21:01:17 +08:00
|
|
|
{
|
2004-03-17 00:23:06 +08:00
|
|
|
GimpLayer *layer = GIMP_LAYER (item);
|
2003-05-07 21:01:17 +08:00
|
|
|
|
2004-04-15 07:37:34 +08:00
|
|
|
GIMP_ITEM_CLASS (parent_class)->resize (item, context, new_width, new_height,
|
2003-05-07 21:01:17 +08:00
|
|
|
offset_x, offset_y);
|
|
|
|
|
|
|
|
if (layer->mask)
|
2004-04-15 07:37:34 +08:00
|
|
|
gimp_item_resize (GIMP_ITEM (layer->mask), context,
|
2004-04-13 19:43:27 +08:00
|
|
|
new_width, new_height, offset_x, offset_y);
|
2003-05-07 21:01:17 +08:00
|
|
|
}
|
|
|
|
|
2003-05-12 23:56:36 +08:00
|
|
|
static void
|
|
|
|
gimp_layer_flip (GimpItem *item,
|
2004-04-15 07:37:34 +08:00
|
|
|
GimpContext *context,
|
2003-05-12 23:56:36 +08:00
|
|
|
GimpOrientationType flip_type,
|
2003-05-13 21:57:11 +08:00
|
|
|
gdouble axis,
|
|
|
|
gboolean clip_result)
|
2003-05-12 23:56:36 +08:00
|
|
|
{
|
2004-04-13 19:43:27 +08:00
|
|
|
GimpLayer *layer = GIMP_LAYER (item);
|
2003-05-12 23:56:36 +08:00
|
|
|
|
2004-04-15 07:37:34 +08:00
|
|
|
GIMP_ITEM_CLASS (parent_class)->flip (item, context, flip_type, axis,
|
|
|
|
clip_result);
|
2003-05-12 23:56:36 +08:00
|
|
|
|
|
|
|
if (layer->mask)
|
2004-04-15 07:37:34 +08:00
|
|
|
gimp_item_flip (GIMP_ITEM (layer->mask), context,
|
2003-05-13 21:57:11 +08:00
|
|
|
flip_type, axis, clip_result);
|
2003-05-12 23:56:36 +08:00
|
|
|
}
|
|
|
|
|
2003-05-20 18:36:29 +08:00
|
|
|
static void
|
|
|
|
gimp_layer_rotate (GimpItem *item,
|
2004-04-15 07:37:34 +08:00
|
|
|
GimpContext *context,
|
2003-05-20 18:36:29 +08:00
|
|
|
GimpRotationType rotate_type,
|
|
|
|
gdouble center_x,
|
|
|
|
gdouble center_y,
|
|
|
|
gboolean clip_result)
|
|
|
|
{
|
2004-04-13 19:43:27 +08:00
|
|
|
GimpLayer *layer = GIMP_LAYER (item);
|
2003-05-20 18:36:29 +08:00
|
|
|
|
2004-04-15 07:37:34 +08:00
|
|
|
GIMP_ITEM_CLASS (parent_class)->rotate (item, context,
|
2003-05-20 18:36:29 +08:00
|
|
|
rotate_type, center_x, center_y,
|
|
|
|
clip_result);
|
|
|
|
|
|
|
|
if (layer->mask)
|
2004-04-15 07:37:34 +08:00
|
|
|
gimp_item_rotate (GIMP_ITEM (layer->mask), context,
|
2003-05-20 18:36:29 +08:00
|
|
|
rotate_type, center_x, center_y, clip_result);
|
|
|
|
}
|
|
|
|
|
2003-05-12 23:56:36 +08:00
|
|
|
static void
|
|
|
|
gimp_layer_transform (GimpItem *item,
|
2004-04-15 07:37:34 +08:00
|
|
|
GimpContext *context,
|
2003-07-07 21:50:48 +08:00
|
|
|
const GimpMatrix3 *matrix,
|
2003-05-12 23:56:36 +08:00
|
|
|
GimpTransformDirection direction,
|
|
|
|
GimpInterpolationType interpolation_type,
|
2004-03-14 01:45:58 +08:00
|
|
|
gint recursion_level,
|
2006-12-25 00:48:08 +08:00
|
|
|
GimpTransformResize clip_result,
|
2004-08-11 02:47:21 +08:00
|
|
|
GimpProgress *progress)
|
2003-05-12 23:56:36 +08:00
|
|
|
{
|
2004-04-13 19:43:27 +08:00
|
|
|
GimpLayer *layer = GIMP_LAYER (item);
|
2003-05-12 23:56:36 +08:00
|
|
|
|
2009-07-20 17:53:02 +08:00
|
|
|
/* FIXME: make interpolated transformations work on layers without alpha */
|
2006-05-14 05:49:29 +08:00
|
|
|
if (interpolation_type != GIMP_INTERPOLATION_NONE &&
|
|
|
|
! gimp_drawable_has_alpha (GIMP_DRAWABLE (item)))
|
|
|
|
gimp_layer_add_alpha (layer);
|
|
|
|
|
2004-04-15 07:37:34 +08:00
|
|
|
GIMP_ITEM_CLASS (parent_class)->transform (item, context, matrix, direction,
|
2004-03-14 01:45:58 +08:00
|
|
|
interpolation_type,
|
2007-09-10 23:29:48 +08:00
|
|
|
recursion_level,
|
|
|
|
clip_result,
|
|
|
|
progress);
|
2003-05-12 23:56:36 +08:00
|
|
|
|
|
|
|
if (layer->mask)
|
2004-04-15 07:37:34 +08:00
|
|
|
gimp_item_transform (GIMP_ITEM (layer->mask), context,
|
2003-05-13 21:57:11 +08:00
|
|
|
matrix, direction,
|
2007-09-10 23:29:48 +08:00
|
|
|
interpolation_type, recursion_level,
|
2004-08-11 02:47:21 +08:00
|
|
|
clip_result, progress);
|
2003-09-04 19:33:06 +08:00
|
|
|
}
|
|
|
|
|
2010-07-21 05:09:19 +08:00
|
|
|
static void
|
|
|
|
gimp_layer_to_selection (GimpItem *item,
|
|
|
|
GimpChannelOps op,
|
|
|
|
gboolean antialias,
|
|
|
|
gboolean feather,
|
|
|
|
gdouble feather_radius_x,
|
|
|
|
gdouble feather_radius_y)
|
|
|
|
{
|
|
|
|
GimpLayer *layer = GIMP_LAYER (item);
|
|
|
|
GimpImage *image = gimp_item_get_image (item);
|
|
|
|
|
|
|
|
gimp_channel_select_alpha (gimp_image_get_mask (image),
|
|
|
|
GIMP_DRAWABLE (layer),
|
|
|
|
op,
|
|
|
|
feather, feather_radius_x, feather_radius_y);
|
|
|
|
}
|
|
|
|
|
2009-09-04 17:31:19 +08:00
|
|
|
static GeglNode *
|
|
|
|
gimp_layer_get_node (GimpItem *item)
|
|
|
|
{
|
|
|
|
GimpDrawable *drawable = GIMP_DRAWABLE (item);
|
|
|
|
GimpLayer *layer = GIMP_LAYER (item);
|
|
|
|
GeglNode *node;
|
|
|
|
GeglNode *offset_node;
|
|
|
|
GeglNode *source;
|
|
|
|
GeglNode *mode_node;
|
|
|
|
|
|
|
|
node = GIMP_ITEM_CLASS (parent_class)->get_node (item);
|
|
|
|
|
|
|
|
source = gimp_drawable_get_source_node (drawable);
|
|
|
|
gegl_node_add_child (node, source);
|
|
|
|
|
2010-02-15 03:26:16 +08:00
|
|
|
g_warn_if_fail (layer->opacity_node == NULL);
|
|
|
|
|
2009-09-04 17:31:19 +08:00
|
|
|
layer->opacity_node = gegl_node_new_child (node,
|
|
|
|
"operation", "gegl:opacity",
|
|
|
|
"value", layer->opacity,
|
|
|
|
NULL);
|
|
|
|
gegl_node_connect_to (source, "output",
|
|
|
|
layer->opacity_node, "input");
|
|
|
|
|
|
|
|
if (layer->mask)
|
|
|
|
{
|
|
|
|
GeglNode *mask;
|
|
|
|
|
|
|
|
mask = gimp_drawable_get_source_node (GIMP_DRAWABLE (layer->mask));
|
|
|
|
|
|
|
|
gegl_node_connect_to (mask, "output",
|
|
|
|
layer->opacity_node, "aux");
|
|
|
|
}
|
|
|
|
|
|
|
|
offset_node = gimp_item_get_offset_node (GIMP_ITEM (layer));
|
|
|
|
|
|
|
|
gegl_node_connect_to (layer->opacity_node, "output",
|
|
|
|
offset_node, "input");
|
|
|
|
|
2009-11-29 20:35:27 +08:00
|
|
|
gimp_layer_sync_mode_node (layer);
|
2009-09-04 17:31:19 +08:00
|
|
|
|
2009-11-29 20:35:27 +08:00
|
|
|
mode_node = gimp_drawable_get_mode_node (drawable);
|
2009-09-04 17:31:19 +08:00
|
|
|
|
|
|
|
gegl_node_connect_to (offset_node, "output",
|
|
|
|
mode_node, "aux");
|
|
|
|
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
2007-12-04 19:30:31 +08:00
|
|
|
static gint64
|
|
|
|
gimp_layer_estimate_memsize (const GimpDrawable *drawable,
|
|
|
|
gint width,
|
|
|
|
gint height)
|
|
|
|
{
|
|
|
|
GimpLayer *layer = GIMP_LAYER (drawable);
|
|
|
|
gint64 memsize = 0;
|
|
|
|
|
|
|
|
if (layer->mask)
|
|
|
|
memsize += gimp_drawable_estimate_memsize (GIMP_DRAWABLE (layer->mask),
|
|
|
|
width, height);
|
|
|
|
|
|
|
|
return memsize + GIMP_DRAWABLE_CLASS (parent_class)->estimate_memsize (drawable,
|
|
|
|
width,
|
|
|
|
height);
|
|
|
|
}
|
|
|
|
|
2003-09-04 19:33:06 +08:00
|
|
|
static void
|
|
|
|
gimp_layer_invalidate_boundary (GimpDrawable *drawable)
|
|
|
|
{
|
2004-02-02 04:38:26 +08:00
|
|
|
GimpLayer *layer = GIMP_LAYER (drawable);
|
2006-03-29 01:08:36 +08:00
|
|
|
GimpImage *image;
|
2003-09-04 19:33:06 +08:00
|
|
|
GimpChannel *mask;
|
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
if (! (image = gimp_item_get_image (GIMP_ITEM (layer))))
|
2003-09-04 19:33:06 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
/* Turn the current selection off */
|
2006-03-29 01:08:36 +08:00
|
|
|
gimp_image_selection_control (image, GIMP_SELECTION_OFF);
|
2003-09-04 19:33:06 +08:00
|
|
|
|
|
|
|
/* get the selection mask channel */
|
2006-03-29 01:08:36 +08:00
|
|
|
mask = gimp_image_get_mask (image);
|
2003-09-04 19:33:06 +08:00
|
|
|
|
|
|
|
/* Only bother with the bounds if there is a selection */
|
|
|
|
if (! gimp_channel_is_empty (mask))
|
|
|
|
{
|
|
|
|
mask->bounds_known = FALSE;
|
|
|
|
mask->boundary_known = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gimp_layer_is_floating_sel (layer))
|
|
|
|
floating_sel_invalidate (layer);
|
2003-05-12 23:56:36 +08:00
|
|
|
}
|
|
|
|
|
2009-09-04 17:31:19 +08:00
|
|
|
static void
|
|
|
|
gimp_layer_get_active_components (const GimpDrawable *drawable,
|
|
|
|
gboolean *active)
|
|
|
|
{
|
|
|
|
GimpLayer *layer = GIMP_LAYER (drawable);
|
|
|
|
GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable));
|
|
|
|
|
|
|
|
/* first copy the image active channels */
|
2010-02-04 16:08:50 +08:00
|
|
|
gimp_image_get_active_array (image, active);
|
2009-09-04 17:31:19 +08:00
|
|
|
|
|
|
|
if (gimp_drawable_has_alpha (drawable) && layer->lock_alpha)
|
|
|
|
active[gimp_drawable_bytes (drawable) - 1] = FALSE;
|
|
|
|
}
|
|
|
|
|
2009-09-12 03:28:52 +08:00
|
|
|
static void
|
|
|
|
gimp_layer_convert_type (GimpDrawable *drawable,
|
|
|
|
GimpImage *dest_image,
|
2009-09-14 01:24:19 +08:00
|
|
|
GimpImageBaseType new_base_type,
|
|
|
|
gboolean push_undo)
|
2009-09-12 03:28:52 +08:00
|
|
|
{
|
|
|
|
switch (new_base_type)
|
|
|
|
{
|
|
|
|
case GIMP_RGB:
|
|
|
|
case GIMP_GRAY:
|
|
|
|
GIMP_DRAWABLE_CLASS (parent_class)->convert_type (drawable, dest_image,
|
2009-09-14 01:24:19 +08:00
|
|
|
new_base_type,
|
|
|
|
push_undo);
|
2009-09-12 03:28:52 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_INDEXED:
|
|
|
|
{
|
|
|
|
GimpItem *item = GIMP_ITEM (drawable);
|
|
|
|
TileManager *new_tiles;
|
|
|
|
GimpImageType new_type;
|
|
|
|
PixelRegion layerPR;
|
|
|
|
PixelRegion newPR;
|
|
|
|
|
|
|
|
new_type = GIMP_IMAGE_TYPE_FROM_BASE_TYPE (new_base_type);
|
|
|
|
|
|
|
|
if (gimp_drawable_has_alpha (drawable))
|
|
|
|
new_type = GIMP_IMAGE_TYPE_WITH_ALPHA (new_type);
|
|
|
|
|
|
|
|
new_tiles = tile_manager_new (gimp_item_get_width (item),
|
|
|
|
gimp_item_get_height (item),
|
|
|
|
GIMP_IMAGE_TYPE_BYTES (new_type));
|
|
|
|
|
|
|
|
pixel_region_init (&layerPR, gimp_drawable_get_tiles (drawable),
|
|
|
|
0, 0,
|
|
|
|
gimp_item_get_width (item),
|
|
|
|
gimp_item_get_height (item),
|
|
|
|
FALSE);
|
|
|
|
pixel_region_init (&newPR, new_tiles,
|
|
|
|
0, 0,
|
|
|
|
gimp_item_get_width (item),
|
|
|
|
gimp_item_get_height (item),
|
|
|
|
TRUE);
|
|
|
|
|
|
|
|
gimp_layer_transform_color (dest_image,
|
|
|
|
&layerPR, gimp_drawable_type (drawable),
|
|
|
|
&newPR, new_type);
|
|
|
|
|
2009-09-14 01:24:19 +08:00
|
|
|
gimp_drawable_set_tiles (drawable, push_undo, NULL,
|
2009-09-12 03:28:52 +08:00
|
|
|
new_tiles, new_type);
|
|
|
|
tile_manager_unref (new_tiles);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-07-12 03:21:52 +08:00
|
|
|
static gint
|
|
|
|
gimp_layer_get_opacity_at (GimpPickable *pickable,
|
2006-04-12 20:49:29 +08:00
|
|
|
gint x,
|
|
|
|
gint y)
|
2005-07-12 03:21:52 +08:00
|
|
|
{
|
|
|
|
GimpLayer *layer = GIMP_LAYER (pickable);
|
|
|
|
Tile *tile;
|
|
|
|
gint val = 0;
|
|
|
|
|
2008-11-03 08:09:01 +08:00
|
|
|
if (x >= 0 && x < gimp_item_get_width (GIMP_ITEM (layer)) &&
|
|
|
|
y >= 0 && y < gimp_item_get_height (GIMP_ITEM (layer)) &&
|
2005-07-12 03:21:52 +08:00
|
|
|
gimp_item_get_visible (GIMP_ITEM (layer)))
|
|
|
|
{
|
|
|
|
/* If the point is inside, and the layer has no
|
|
|
|
* alpha channel, success!
|
|
|
|
*/
|
|
|
|
if (! gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)))
|
2006-04-12 20:49:29 +08:00
|
|
|
return OPAQUE_OPACITY;
|
2005-07-12 03:21:52 +08:00
|
|
|
|
|
|
|
/* Otherwise, determine if the alpha value at
|
|
|
|
* the given point is non-zero
|
|
|
|
*/
|
2007-12-24 00:58:41 +08:00
|
|
|
tile = tile_manager_get_tile (gimp_drawable_get_tiles (GIMP_DRAWABLE (layer)),
|
2006-04-12 20:49:29 +08:00
|
|
|
x, y, TRUE, FALSE);
|
2005-07-12 03:21:52 +08:00
|
|
|
|
2007-09-13 02:29:11 +08:00
|
|
|
val = * ((const guchar *) tile_data_pointer (tile, x, y) +
|
2006-04-12 20:49:29 +08:00
|
|
|
tile_bpp (tile) - 1);
|
2005-07-12 03:21:52 +08:00
|
|
|
|
|
|
|
if (layer->mask)
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
|
|
|
gint mask_val;
|
2005-07-12 03:21:52 +08:00
|
|
|
|
|
|
|
mask_val = gimp_pickable_get_opacity_at (GIMP_PICKABLE (layer->mask),
|
|
|
|
x, y);
|
|
|
|
|
2006-04-12 20:49:29 +08:00
|
|
|
val = val * mask_val / 255;
|
|
|
|
}
|
2005-07-12 03:21:52 +08:00
|
|
|
|
|
|
|
tile_release (tile, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
1998-01-22 15:02:57 +08:00
|
|
|
static void
|
2006-03-29 01:08:36 +08:00
|
|
|
gimp_layer_transform_color (GimpImage *image,
|
2008-01-08 02:53:55 +08:00
|
|
|
PixelRegion *srcPR,
|
|
|
|
GimpImageType src_type,
|
|
|
|
PixelRegion *destPR,
|
|
|
|
GimpImageType dest_type)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2009-09-09 02:54:51 +08:00
|
|
|
GimpImageBaseType base_type = GIMP_IMAGE_TYPE_BASE_TYPE (src_type);
|
|
|
|
gboolean src_alpha = GIMP_IMAGE_TYPE_HAS_ALPHA (src_type);
|
|
|
|
gboolean dest_alpha = GIMP_IMAGE_TYPE_HAS_ALPHA (dest_type);
|
2005-08-09 08:07:21 +08:00
|
|
|
gpointer pr;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2008-01-08 02:53:55 +08:00
|
|
|
for (pr = pixel_regions_register (2, srcPR, destPR);
|
2001-12-13 07:48:18 +08:00
|
|
|
pr != NULL;
|
2000-05-13 01:07:54 +08:00
|
|
|
pr = pixel_regions_process (pr))
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2008-01-08 02:53:55 +08:00
|
|
|
const guchar *src = srcPR->data;
|
|
|
|
guchar *dest = destPR->data;
|
|
|
|
gint h = destPR->h;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
while (h--)
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
2005-02-16 07:38:59 +08:00
|
|
|
const guchar *s = src;
|
|
|
|
guchar *d = dest;
|
2008-01-08 02:53:55 +08:00
|
|
|
gint i;
|
2005-02-16 07:38:59 +08:00
|
|
|
|
2008-01-08 02:53:55 +08:00
|
|
|
for (i = 0; i < destPR->w; i++)
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
2006-10-26 06:14:36 +08:00
|
|
|
gimp_image_transform_color (image, dest_type, d, base_type, s);
|
2005-02-16 07:38:59 +08:00
|
|
|
|
2009-09-09 02:54:51 +08:00
|
|
|
if (dest_alpha)
|
|
|
|
d[destPR->bytes - 1] = (src_alpha ?
|
|
|
|
s[srcPR->bytes - 1] : OPAQUE_OPACITY);
|
2005-02-16 07:38:59 +08:00
|
|
|
|
2008-01-08 02:53:55 +08:00
|
|
|
s += srcPR->bytes;
|
|
|
|
d += destPR->bytes;
|
2006-04-12 20:49:29 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2008-01-08 02:53:55 +08:00
|
|
|
src += srcPR->rowstride;
|
|
|
|
dest += destPR->rowstride;
|
2006-04-12 20:49:29 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
To optimize duplicate and/or wrong image updates away, introduced new
2003-09-06 Michael Natterer <mitch@gimp.org>
To optimize duplicate and/or wrong image updates away, introduced
new policy that a child object must never explicitly update or
invalidate its parent object (just like the GUI is not updated
explicitly by the core):
* app/core/gimpdrawable.[ch]: added new signal
GimpDrawable::update(). Never update or invalidate the image when
the drawable is updated or invalidated.
(gimp_drawable_set_visible): don't gimp_drawable_update() the
drawable since its pixels have not changed.
* app/core/gimpimage.[ch]: connect to the "add" and "remove"
signals of the layers and channels containers. Also connect to the
"update" and "visibility_changed" signals of all drawables in
these containers (optimizes away updates issued by drawables which
are not yet added to the image and updates of the selection
mask). Also, don't propagate updates to the image if the emitting
drawable is invisible (optimizes away updates issued by invisible
drawables).
(gimp_image_add_layer,channel)
(gimp_image_remove_layer,channel): don't update the image since
that's done by our "add" and "remove" handlers now.
(gimp_image_position_layer,channel): update just the image, not
the drawable since its pixels have not changed.
(gimp_image_real_colormap_changed)
(gimp_image_set_component_visible): always call
gimp_image_update() *and* gimp_viewable_invalidate_preview() to
get everything updated, since update and invalidate of images are
not connected.
* app/core/gimpimage-undo-push.c (undo_pop_layer,channel): don't
update the drawable since (a) its pixels don't change and (b) the
image updates itself upon adding/removing now.
(undo_pop_layer_mod): replaced gimp_image_update() by
gimp_drawable_update() (just for consistency with other similar
functions).
* app/core/gimplayer.c: connect to "update" of the layer mask and
issue updates on the layer if the mask update has any effect on
the projection.
(gimp_layer_create_mask): don't set the mask's offsets here since
they may be different when we later add the mask to the layer.
* app/core/gimplayermask.c (gimp_layer_mask_set_layer): set the
mask offsets here instead.
* app/core/gimpchannel.c (gimp_channel_translate): update the
channel even if push_undo == FALSE.
* app/paint/gimppaintcore.c (gimp_paint_core_finish)
* app/tools/gimpinktool.c (ink_finish): invalidate both the
drawable and the image preview since invalidating the drawable
doesn't invalidate the image any more.
* app/text/gimptextlayer.c (gimp_text_layer_render_now): also
update the new extents of the text layer, not only the old one.
(gimp_text_layer_render_layout): don't update the drawable since
gimp_drawable_fill() already updated it.
2003-09-07 04:06:53 +08:00
|
|
|
static void
|
|
|
|
gimp_layer_layer_mask_update (GimpDrawable *drawable,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint width,
|
|
|
|
gint height,
|
|
|
|
GimpLayer *layer)
|
|
|
|
{
|
|
|
|
GimpLayerMask *layer_mask = GIMP_LAYER_MASK (drawable);
|
|
|
|
|
2007-12-24 00:58:41 +08:00
|
|
|
if (gimp_layer_mask_get_apply (layer_mask) ||
|
|
|
|
gimp_layer_mask_get_show (layer_mask))
|
To optimize duplicate and/or wrong image updates away, introduced new
2003-09-06 Michael Natterer <mitch@gimp.org>
To optimize duplicate and/or wrong image updates away, introduced
new policy that a child object must never explicitly update or
invalidate its parent object (just like the GUI is not updated
explicitly by the core):
* app/core/gimpdrawable.[ch]: added new signal
GimpDrawable::update(). Never update or invalidate the image when
the drawable is updated or invalidated.
(gimp_drawable_set_visible): don't gimp_drawable_update() the
drawable since its pixels have not changed.
* app/core/gimpimage.[ch]: connect to the "add" and "remove"
signals of the layers and channels containers. Also connect to the
"update" and "visibility_changed" signals of all drawables in
these containers (optimizes away updates issued by drawables which
are not yet added to the image and updates of the selection
mask). Also, don't propagate updates to the image if the emitting
drawable is invisible (optimizes away updates issued by invisible
drawables).
(gimp_image_add_layer,channel)
(gimp_image_remove_layer,channel): don't update the image since
that's done by our "add" and "remove" handlers now.
(gimp_image_position_layer,channel): update just the image, not
the drawable since its pixels have not changed.
(gimp_image_real_colormap_changed)
(gimp_image_set_component_visible): always call
gimp_image_update() *and* gimp_viewable_invalidate_preview() to
get everything updated, since update and invalidate of images are
not connected.
* app/core/gimpimage-undo-push.c (undo_pop_layer,channel): don't
update the drawable since (a) its pixels don't change and (b) the
image updates itself upon adding/removing now.
(undo_pop_layer_mod): replaced gimp_image_update() by
gimp_drawable_update() (just for consistency with other similar
functions).
* app/core/gimplayer.c: connect to "update" of the layer mask and
issue updates on the layer if the mask update has any effect on
the projection.
(gimp_layer_create_mask): don't set the mask's offsets here since
they may be different when we later add the mask to the layer.
* app/core/gimplayermask.c (gimp_layer_mask_set_layer): set the
mask offsets here instead.
* app/core/gimpchannel.c (gimp_channel_translate): update the
channel even if push_undo == FALSE.
* app/paint/gimppaintcore.c (gimp_paint_core_finish)
* app/tools/gimpinktool.c (ink_finish): invalidate both the
drawable and the image preview since invalidating the drawable
doesn't invalidate the image any more.
* app/text/gimptextlayer.c (gimp_text_layer_render_now): also
update the new extents of the text layer, not only the old one.
(gimp_text_layer_render_layout): don't update the drawable since
gimp_drawable_fill() already updated it.
2003-09-07 04:06:53 +08:00
|
|
|
{
|
|
|
|
gimp_drawable_update (GIMP_DRAWABLE (layer),
|
|
|
|
x, y, width, height);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-29 20:35:27 +08:00
|
|
|
static void
|
|
|
|
gimp_layer_sync_mode_node (GimpLayer *layer)
|
|
|
|
{
|
|
|
|
if (layer->opacity_node)
|
|
|
|
{
|
|
|
|
GeglNode *mode_node;
|
|
|
|
|
|
|
|
mode_node = gimp_drawable_get_mode_node (GIMP_DRAWABLE (layer));
|
|
|
|
|
2009-11-29 20:51:22 +08:00
|
|
|
switch (layer->mode)
|
|
|
|
{
|
2009-12-31 01:01:09 +08:00
|
|
|
case GIMP_DISSOLVE_MODE:
|
|
|
|
case GIMP_BEHIND_MODE:
|
|
|
|
case GIMP_MULTIPLY_MODE:
|
|
|
|
case GIMP_SCREEN_MODE:
|
|
|
|
case GIMP_OVERLAY_MODE:
|
|
|
|
case GIMP_DIFFERENCE_MODE:
|
|
|
|
case GIMP_ADDITION_MODE:
|
|
|
|
case GIMP_SUBTRACT_MODE:
|
|
|
|
case GIMP_DARKEN_ONLY_MODE:
|
|
|
|
case GIMP_LIGHTEN_ONLY_MODE:
|
|
|
|
case GIMP_HUE_MODE:
|
|
|
|
case GIMP_SATURATION_MODE:
|
|
|
|
case GIMP_COLOR_MODE:
|
|
|
|
case GIMP_VALUE_MODE:
|
|
|
|
case GIMP_DIVIDE_MODE:
|
|
|
|
case GIMP_DODGE_MODE:
|
|
|
|
case GIMP_BURN_MODE:
|
|
|
|
case GIMP_HARDLIGHT_MODE:
|
|
|
|
case GIMP_SOFTLIGHT_MODE:
|
|
|
|
case GIMP_GRAIN_EXTRACT_MODE:
|
|
|
|
case GIMP_GRAIN_MERGE_MODE:
|
|
|
|
case GIMP_COLOR_ERASE_MODE:
|
|
|
|
case GIMP_ERASE_MODE:
|
|
|
|
case GIMP_REPLACE_MODE:
|
|
|
|
case GIMP_ANTI_ERASE_MODE:
|
2009-11-29 20:51:22 +08:00
|
|
|
gegl_node_set (mode_node,
|
2009-12-31 01:01:09 +08:00
|
|
|
"operation", "gimp:point-layer-mode",
|
|
|
|
"blend-mode", layer->mode,
|
2009-11-29 20:51:22 +08:00
|
|
|
NULL);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
gegl_node_set (mode_node,
|
2009-12-31 01:01:09 +08:00
|
|
|
"operation",
|
|
|
|
gimp_layer_mode_to_gegl_operation (layer->mode),
|
2009-11-29 20:51:22 +08:00
|
|
|
NULL);
|
|
|
|
break;
|
|
|
|
}
|
2009-11-29 20:35:27 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
To optimize duplicate and/or wrong image updates away, introduced new
2003-09-06 Michael Natterer <mitch@gimp.org>
To optimize duplicate and/or wrong image updates away, introduced
new policy that a child object must never explicitly update or
invalidate its parent object (just like the GUI is not updated
explicitly by the core):
* app/core/gimpdrawable.[ch]: added new signal
GimpDrawable::update(). Never update or invalidate the image when
the drawable is updated or invalidated.
(gimp_drawable_set_visible): don't gimp_drawable_update() the
drawable since its pixels have not changed.
* app/core/gimpimage.[ch]: connect to the "add" and "remove"
signals of the layers and channels containers. Also connect to the
"update" and "visibility_changed" signals of all drawables in
these containers (optimizes away updates issued by drawables which
are not yet added to the image and updates of the selection
mask). Also, don't propagate updates to the image if the emitting
drawable is invisible (optimizes away updates issued by invisible
drawables).
(gimp_image_add_layer,channel)
(gimp_image_remove_layer,channel): don't update the image since
that's done by our "add" and "remove" handlers now.
(gimp_image_position_layer,channel): update just the image, not
the drawable since its pixels have not changed.
(gimp_image_real_colormap_changed)
(gimp_image_set_component_visible): always call
gimp_image_update() *and* gimp_viewable_invalidate_preview() to
get everything updated, since update and invalidate of images are
not connected.
* app/core/gimpimage-undo-push.c (undo_pop_layer,channel): don't
update the drawable since (a) its pixels don't change and (b) the
image updates itself upon adding/removing now.
(undo_pop_layer_mod): replaced gimp_image_update() by
gimp_drawable_update() (just for consistency with other similar
functions).
* app/core/gimplayer.c: connect to "update" of the layer mask and
issue updates on the layer if the mask update has any effect on
the projection.
(gimp_layer_create_mask): don't set the mask's offsets here since
they may be different when we later add the mask to the layer.
* app/core/gimplayermask.c (gimp_layer_mask_set_layer): set the
mask offsets here instead.
* app/core/gimpchannel.c (gimp_channel_translate): update the
channel even if push_undo == FALSE.
* app/paint/gimppaintcore.c (gimp_paint_core_finish)
* app/tools/gimpinktool.c (ink_finish): invalidate both the
drawable and the image preview since invalidating the drawable
doesn't invalidate the image any more.
* app/text/gimptextlayer.c (gimp_text_layer_render_now): also
update the new extents of the text layer, not only the old one.
(gimp_text_layer_render_layout): don't update the drawable since
gimp_drawable_fill() already updated it.
2003-09-07 04:06:53 +08:00
|
|
|
|
|
|
|
/* public functions */
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-01-29 00:44:22 +08:00
|
|
|
GimpLayer *
|
2006-03-29 01:08:36 +08:00
|
|
|
gimp_layer_new (GimpImage *image,
|
2006-04-12 20:49:29 +08:00
|
|
|
gint width,
|
|
|
|
gint height,
|
|
|
|
GimpImageType type,
|
|
|
|
const gchar *name,
|
|
|
|
gdouble opacity,
|
|
|
|
GimpLayerModeEffects mode)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2001-01-29 00:44:22 +08:00
|
|
|
GimpLayer *layer;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
|
2002-03-04 22:52:54 +08:00
|
|
|
g_return_val_if_fail (width > 0, NULL);
|
|
|
|
g_return_val_if_fail (height > 0, NULL);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-08-10 22:41:39 +08:00
|
|
|
layer = g_object_new (GIMP_TYPE_LAYER, NULL);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
gimp_drawable_configure (GIMP_DRAWABLE (layer),
|
2006-04-12 20:49:29 +08:00
|
|
|
image,
|
2003-02-01 00:37:03 +08:00
|
|
|
0, 0, width, height,
|
2001-12-13 07:48:18 +08:00
|
|
|
type,
|
|
|
|
name);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2002-03-04 22:52:54 +08:00
|
|
|
opacity = CLAMP (opacity, GIMP_OPACITY_TRANSPARENT, GIMP_OPACITY_OPAQUE);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
layer->opacity = opacity;
|
2002-03-04 22:52:54 +08:00
|
|
|
layer->mode = mode;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
return layer;
|
|
|
|
}
|
|
|
|
|
2002-03-04 22:52:54 +08:00
|
|
|
/**
|
|
|
|
* gimp_layer_new_from_tiles:
|
2008-08-08 01:19:32 +08:00
|
|
|
* @tiles: The buffer to make the new layer from.
|
2006-03-29 01:08:36 +08:00
|
|
|
* @dest_image: The image the new layer will be added to.
|
2008-08-08 01:19:32 +08:00
|
|
|
* @type: The #GimpImageType of the new layer.
|
|
|
|
* @name: The new layer's name.
|
|
|
|
* @opacity: The new layer's opacity.
|
|
|
|
* @mode: The new layer's mode.
|
2003-08-28 01:21:49 +08:00
|
|
|
*
|
2002-03-04 22:52:54 +08:00
|
|
|
* Copies %tiles to a layer taking into consideration the
|
|
|
|
* possibility of transforming the contents to meet the requirements
|
|
|
|
* of the target image type
|
2003-08-28 01:21:49 +08:00
|
|
|
*
|
2002-03-04 22:52:54 +08:00
|
|
|
* Return value: The new layer.
|
|
|
|
**/
|
2001-01-29 00:44:22 +08:00
|
|
|
GimpLayer *
|
2002-02-26 01:58:50 +08:00
|
|
|
gimp_layer_new_from_tiles (TileManager *tiles,
|
2006-03-29 01:08:36 +08:00
|
|
|
GimpImage *dest_image,
|
2002-05-21 19:29:20 +08:00
|
|
|
GimpImageType type,
|
2006-04-12 20:49:29 +08:00
|
|
|
const gchar *name,
|
|
|
|
gdouble opacity,
|
|
|
|
GimpLayerModeEffects mode)
|
2005-04-10 01:56:04 +08:00
|
|
|
{
|
|
|
|
PixelRegion bufPR;
|
|
|
|
|
|
|
|
g_return_val_if_fail (tiles != NULL, NULL);
|
2006-03-29 01:08:36 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_IMAGE (dest_image), NULL);
|
2005-04-10 01:56:04 +08:00
|
|
|
|
|
|
|
pixel_region_init (&bufPR, tiles,
|
2006-04-12 20:49:29 +08:00
|
|
|
0, 0,
|
2005-04-10 01:56:04 +08:00
|
|
|
tile_manager_width (tiles),
|
|
|
|
tile_manager_height (tiles),
|
|
|
|
FALSE);
|
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
return gimp_layer_new_from_region (&bufPR, dest_image, type,
|
2005-04-10 01:56:04 +08:00
|
|
|
name, opacity, mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gimp_layer_new_from_pixbuf:
|
2008-08-08 01:19:32 +08:00
|
|
|
* @pixbuf: The pixbuf to make the new layer from.
|
2006-03-29 01:08:36 +08:00
|
|
|
* @dest_image: The image the new layer will be added to.
|
2008-08-08 01:19:32 +08:00
|
|
|
* @type: The #GimpImageType of the new layer.
|
|
|
|
* @name: The new layer's name.
|
|
|
|
* @opacity: The new layer's opacity.
|
|
|
|
* @mode: The new layer's mode.
|
2005-04-10 01:56:04 +08:00
|
|
|
*
|
|
|
|
* Copies %pixbuf to a layer taking into consideration the
|
|
|
|
* possibility of transforming the contents to meet the requirements
|
|
|
|
* of the target image type
|
|
|
|
*
|
|
|
|
* Return value: The new layer.
|
|
|
|
**/
|
|
|
|
GimpLayer *
|
|
|
|
gimp_layer_new_from_pixbuf (GdkPixbuf *pixbuf,
|
2006-03-29 01:08:36 +08:00
|
|
|
GimpImage *dest_image,
|
2005-04-10 01:56:04 +08:00
|
|
|
GimpImageType type,
|
|
|
|
const gchar *name,
|
|
|
|
gdouble opacity,
|
|
|
|
GimpLayerModeEffects mode)
|
|
|
|
{
|
|
|
|
PixelRegion bufPR = { 0, };
|
|
|
|
|
|
|
|
g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
|
2006-03-29 01:08:36 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_IMAGE (dest_image), NULL);
|
2005-04-10 01:56:04 +08:00
|
|
|
|
2005-09-04 01:16:58 +08:00
|
|
|
pixel_region_init_data (&bufPR, gdk_pixbuf_get_pixels (pixbuf),
|
|
|
|
gdk_pixbuf_get_n_channels (pixbuf),
|
|
|
|
gdk_pixbuf_get_rowstride (pixbuf),
|
|
|
|
0, 0,
|
|
|
|
gdk_pixbuf_get_width (pixbuf),
|
|
|
|
gdk_pixbuf_get_height (pixbuf));
|
2005-04-10 01:56:04 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
return gimp_layer_new_from_region (&bufPR, dest_image, type,
|
2005-04-10 01:56:04 +08:00
|
|
|
name, opacity, mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gimp_layer_new_from_region:
|
2008-08-08 01:19:32 +08:00
|
|
|
* @region: A readable pixel region.
|
2006-03-29 01:08:36 +08:00
|
|
|
* @dest_image: The image the new layer will be added to.
|
2008-08-08 01:19:32 +08:00
|
|
|
* @type: The #GimpImageType of the new layer.
|
|
|
|
* @name: The new layer's name.
|
|
|
|
* @opacity: The new layer's opacity.
|
|
|
|
* @mode: The new layer's mode.
|
2005-04-10 01:56:04 +08:00
|
|
|
*
|
|
|
|
* Copies %region to a layer taking into consideration the
|
|
|
|
* possibility of transforming the contents to meet the requirements
|
|
|
|
* of the target image type
|
|
|
|
*
|
|
|
|
* Return value: The new layer.
|
|
|
|
**/
|
|
|
|
GimpLayer *
|
|
|
|
gimp_layer_new_from_region (PixelRegion *region,
|
2006-03-29 01:08:36 +08:00
|
|
|
GimpImage *dest_image,
|
2005-04-10 01:56:04 +08:00
|
|
|
GimpImageType type,
|
|
|
|
const gchar *name,
|
|
|
|
gdouble opacity,
|
|
|
|
GimpLayerModeEffects mode)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2004-07-07 23:07:17 +08:00
|
|
|
GimpLayer *new_layer;
|
|
|
|
PixelRegion layerPR;
|
|
|
|
GimpImageType src_type;
|
|
|
|
gint width;
|
2004-07-07 23:25:27 +08:00
|
|
|
gint height;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2005-04-10 01:56:04 +08:00
|
|
|
g_return_val_if_fail (region != NULL, NULL);
|
2006-03-29 01:08:36 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_IMAGE (dest_image), NULL);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2005-04-10 01:56:04 +08:00
|
|
|
width = region->w;
|
|
|
|
height = region->h;
|
2002-03-04 22:52:54 +08:00
|
|
|
|
2005-04-10 01:56:04 +08:00
|
|
|
switch (region->bytes)
|
2004-07-07 23:07:17 +08:00
|
|
|
{
|
|
|
|
case 1: src_type = GIMP_GRAY_IMAGE; break;
|
|
|
|
case 2: src_type = GIMP_GRAYA_IMAGE; break;
|
|
|
|
case 3: src_type = GIMP_RGB_IMAGE; break;
|
|
|
|
case 4: src_type = GIMP_RGBA_IMAGE; break;
|
|
|
|
default:
|
|
|
|
g_return_val_if_reached (NULL);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
new_layer = gimp_layer_new (dest_image, width, height, type, name,
|
2006-04-12 20:49:29 +08:00
|
|
|
opacity, mode);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2002-03-04 22:52:54 +08:00
|
|
|
if (! new_layer)
|
1999-08-22 19:45:31 +08:00
|
|
|
{
|
2006-08-09 05:06:36 +08:00
|
|
|
g_warning ("%s: could not allocate new layer", G_STRFUNC);
|
1999-08-22 19:45:31 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2007-12-24 00:58:41 +08:00
|
|
|
pixel_region_init (&layerPR,
|
|
|
|
gimp_drawable_get_tiles (GIMP_DRAWABLE (new_layer)),
|
2006-04-12 20:49:29 +08:00
|
|
|
0, 0, width, height,
|
|
|
|
TRUE);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2004-07-07 23:07:17 +08:00
|
|
|
switch (type)
|
2001-12-13 07:48:18 +08:00
|
|
|
{
|
2004-07-07 23:07:17 +08:00
|
|
|
case GIMP_RGB_IMAGE:
|
|
|
|
switch (src_type)
|
|
|
|
{
|
|
|
|
case GIMP_RGB_IMAGE:
|
2005-04-10 01:56:04 +08:00
|
|
|
copy_region (region, &layerPR);
|
2004-07-07 23:07:17 +08:00
|
|
|
break;
|
2008-08-07 21:36:04 +08:00
|
|
|
|
2004-07-07 23:07:17 +08:00
|
|
|
default:
|
|
|
|
g_warning ("%s: unhandled type conversion", G_STRFUNC);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_RGBA_IMAGE:
|
|
|
|
switch (src_type)
|
|
|
|
{
|
|
|
|
case GIMP_RGBA_IMAGE:
|
2005-04-10 01:56:04 +08:00
|
|
|
copy_region (region, &layerPR);
|
2004-07-07 23:07:17 +08:00
|
|
|
break;
|
2008-08-07 21:36:04 +08:00
|
|
|
|
2004-07-07 23:07:17 +08:00
|
|
|
case GIMP_RGB_IMAGE:
|
2005-04-10 01:56:04 +08:00
|
|
|
add_alpha_region (region, &layerPR);
|
2004-07-07 23:07:17 +08:00
|
|
|
break;
|
2008-08-07 21:36:04 +08:00
|
|
|
|
2005-08-09 08:07:21 +08:00
|
|
|
case GIMP_GRAY_IMAGE:
|
2004-07-07 23:07:17 +08:00
|
|
|
case GIMP_GRAYA_IMAGE:
|
2008-01-08 02:53:55 +08:00
|
|
|
gimp_layer_transform_color (dest_image,
|
|
|
|
region, src_type,
|
|
|
|
&layerPR, type);
|
2004-07-07 23:07:17 +08:00
|
|
|
break;
|
2008-08-07 21:36:04 +08:00
|
|
|
|
2004-07-07 23:07:17 +08:00
|
|
|
default:
|
|
|
|
g_warning ("%s: unhandled type conversion", G_STRFUNC);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_GRAY_IMAGE:
|
|
|
|
switch (src_type)
|
|
|
|
{
|
|
|
|
case GIMP_GRAY_IMAGE:
|
2005-04-10 01:56:04 +08:00
|
|
|
copy_region (region, &layerPR);
|
2004-07-07 23:07:17 +08:00
|
|
|
break;
|
2008-08-07 21:36:04 +08:00
|
|
|
|
2004-07-07 23:07:17 +08:00
|
|
|
default:
|
|
|
|
g_warning ("%s: unhandled type conversion", G_STRFUNC);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_GRAYA_IMAGE:
|
|
|
|
switch (src_type)
|
|
|
|
{
|
2005-08-09 08:07:21 +08:00
|
|
|
case GIMP_RGB_IMAGE:
|
2004-07-07 23:07:17 +08:00
|
|
|
case GIMP_RGBA_IMAGE:
|
2008-01-08 02:53:55 +08:00
|
|
|
gimp_layer_transform_color (dest_image,
|
|
|
|
region, src_type,
|
|
|
|
&layerPR, type);
|
2004-07-07 23:07:17 +08:00
|
|
|
break;
|
2008-08-07 21:36:04 +08:00
|
|
|
|
2004-07-07 23:07:17 +08:00
|
|
|
case GIMP_GRAYA_IMAGE:
|
2005-04-10 01:56:04 +08:00
|
|
|
copy_region (region, &layerPR);
|
2004-07-07 23:07:17 +08:00
|
|
|
break;
|
2008-08-07 21:36:04 +08:00
|
|
|
|
2004-07-07 23:07:17 +08:00
|
|
|
case GIMP_GRAY_IMAGE:
|
2005-04-10 01:56:04 +08:00
|
|
|
add_alpha_region (region, &layerPR);
|
2004-07-07 23:07:17 +08:00
|
|
|
break;
|
2008-08-07 21:36:04 +08:00
|
|
|
|
2004-07-07 23:07:17 +08:00
|
|
|
default:
|
|
|
|
g_warning ("%s: unhandled type conversion", G_STRFUNC);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_INDEXED_IMAGE:
|
|
|
|
g_warning ("%s: unhandled type conversion", G_STRFUNC);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_INDEXEDA_IMAGE:
|
|
|
|
switch (src_type)
|
|
|
|
{
|
2005-08-09 08:07:21 +08:00
|
|
|
case GIMP_RGB_IMAGE:
|
2004-07-07 23:07:17 +08:00
|
|
|
case GIMP_RGBA_IMAGE:
|
2005-08-09 08:07:21 +08:00
|
|
|
case GIMP_GRAY_IMAGE:
|
2004-07-07 23:07:17 +08:00
|
|
|
case GIMP_GRAYA_IMAGE:
|
2008-01-08 02:53:55 +08:00
|
|
|
gimp_layer_transform_color (dest_image,
|
|
|
|
region, src_type,
|
|
|
|
&layerPR, type);
|
2004-07-07 23:07:17 +08:00
|
|
|
break;
|
2008-08-07 21:36:04 +08:00
|
|
|
|
2004-07-07 23:07:17 +08:00
|
|
|
default:
|
|
|
|
g_warning ("%s: unhandled type conversion", G_STRFUNC);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2001-12-13 07:48:18 +08:00
|
|
|
}
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
return new_layer;
|
|
|
|
}
|
|
|
|
|
2010-02-07 19:03:07 +08:00
|
|
|
GimpLayer *
|
|
|
|
gimp_layer_get_parent (GimpLayer *layer)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_LAYER (layer), NULL);
|
|
|
|
|
|
|
|
return GIMP_LAYER (gimp_viewable_get_parent (GIMP_VIEWABLE (layer)));
|
|
|
|
}
|
|
|
|
|
2009-07-31 00:59:12 +08:00
|
|
|
GimpLayerMask *
|
|
|
|
gimp_layer_get_mask (const GimpLayer *layer)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_LAYER (layer), NULL);
|
|
|
|
|
|
|
|
return layer->mask;
|
|
|
|
}
|
|
|
|
|
2001-01-29 00:44:22 +08:00
|
|
|
GimpLayerMask *
|
2008-09-16 05:05:01 +08:00
|
|
|
gimp_layer_add_mask (GimpLayer *layer,
|
|
|
|
GimpLayerMask *mask,
|
|
|
|
gboolean push_undo,
|
|
|
|
GError **error)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2006-03-29 01:08:36 +08:00
|
|
|
GimpImage *image;
|
2001-03-05 04:06:48 +08:00
|
|
|
|
|
|
|
g_return_val_if_fail (GIMP_IS_LAYER (layer), NULL);
|
|
|
|
g_return_val_if_fail (GIMP_IS_LAYER_MASK (mask), NULL);
|
2008-10-06 17:26:44 +08:00
|
|
|
g_return_val_if_fail (gimp_item_get_image (GIMP_ITEM (layer)) ==
|
|
|
|
gimp_item_get_image (GIMP_ITEM (mask)), NULL);
|
2008-09-16 05:05:01 +08:00
|
|
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
2001-03-05 04:06:48 +08:00
|
|
|
|
2004-11-16 21:41:55 +08:00
|
|
|
if (! gimp_item_is_attached (GIMP_ITEM (layer)))
|
|
|
|
push_undo = FALSE;
|
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
image = gimp_item_get_image (GIMP_ITEM (layer));
|
2001-03-05 04:06:48 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
if (layer->mask)
|
2001-03-05 04:06:48 +08:00
|
|
|
{
|
2008-11-12 18:56:06 +08:00
|
|
|
g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
|
2008-11-04 20:33:09 +08:00
|
|
|
_("Unable to add a layer mask since "
|
|
|
|
"the layer already has one."));
|
2001-03-05 04:06:48 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-11-03 08:09:01 +08:00
|
|
|
if ((gimp_item_get_width (GIMP_ITEM (layer)) !=
|
|
|
|
gimp_item_get_width (GIMP_ITEM (mask))) ||
|
|
|
|
(gimp_item_get_height (GIMP_ITEM (layer)) !=
|
|
|
|
gimp_item_get_height (GIMP_ITEM (mask))))
|
2001-03-05 04:06:48 +08:00
|
|
|
{
|
2008-11-12 18:56:06 +08:00
|
|
|
g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
|
2008-11-04 20:33:09 +08:00
|
|
|
_("Cannot add layer mask of different "
|
|
|
|
"dimensions than specified layer."));
|
2001-03-05 04:06:48 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2004-11-16 21:41:55 +08:00
|
|
|
if (push_undo)
|
2010-06-08 19:24:11 +08:00
|
|
|
gimp_image_undo_push_layer_mask_add (image, C_("undo-type", "Add Layer Mask"),
|
2004-11-16 21:41:55 +08:00
|
|
|
layer, mask);
|
|
|
|
|
2006-10-17 01:09:17 +08:00
|
|
|
layer->mask = g_object_ref_sink (mask);
|
2003-12-10 02:59:35 +08:00
|
|
|
|
2001-01-29 00:44:22 +08:00
|
|
|
gimp_layer_mask_set_layer (mask, layer);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2008-11-03 02:39:10 +08:00
|
|
|
if (layer->opacity_node)
|
2008-10-10 04:44:23 +08:00
|
|
|
{
|
|
|
|
GeglNode *mask;
|
|
|
|
|
|
|
|
mask = gimp_drawable_get_source_node (GIMP_DRAWABLE (layer->mask));
|
|
|
|
|
2008-11-03 02:39:10 +08:00
|
|
|
gegl_node_connect_to (mask, "output",
|
|
|
|
layer->opacity_node, "aux");
|
2008-10-10 04:44:23 +08:00
|
|
|
}
|
|
|
|
|
2007-12-24 00:58:41 +08:00
|
|
|
if (gimp_layer_mask_get_apply (mask) ||
|
|
|
|
gimp_layer_mask_get_show (mask))
|
To optimize duplicate and/or wrong image updates away, introduced new
2003-09-06 Michael Natterer <mitch@gimp.org>
To optimize duplicate and/or wrong image updates away, introduced
new policy that a child object must never explicitly update or
invalidate its parent object (just like the GUI is not updated
explicitly by the core):
* app/core/gimpdrawable.[ch]: added new signal
GimpDrawable::update(). Never update or invalidate the image when
the drawable is updated or invalidated.
(gimp_drawable_set_visible): don't gimp_drawable_update() the
drawable since its pixels have not changed.
* app/core/gimpimage.[ch]: connect to the "add" and "remove"
signals of the layers and channels containers. Also connect to the
"update" and "visibility_changed" signals of all drawables in
these containers (optimizes away updates issued by drawables which
are not yet added to the image and updates of the selection
mask). Also, don't propagate updates to the image if the emitting
drawable is invisible (optimizes away updates issued by invisible
drawables).
(gimp_image_add_layer,channel)
(gimp_image_remove_layer,channel): don't update the image since
that's done by our "add" and "remove" handlers now.
(gimp_image_position_layer,channel): update just the image, not
the drawable since its pixels have not changed.
(gimp_image_real_colormap_changed)
(gimp_image_set_component_visible): always call
gimp_image_update() *and* gimp_viewable_invalidate_preview() to
get everything updated, since update and invalidate of images are
not connected.
* app/core/gimpimage-undo-push.c (undo_pop_layer,channel): don't
update the drawable since (a) its pixels don't change and (b) the
image updates itself upon adding/removing now.
(undo_pop_layer_mod): replaced gimp_image_update() by
gimp_drawable_update() (just for consistency with other similar
functions).
* app/core/gimplayer.c: connect to "update" of the layer mask and
issue updates on the layer if the mask update has any effect on
the projection.
(gimp_layer_create_mask): don't set the mask's offsets here since
they may be different when we later add the mask to the layer.
* app/core/gimplayermask.c (gimp_layer_mask_set_layer): set the
mask offsets here instead.
* app/core/gimpchannel.c (gimp_channel_translate): update the
channel even if push_undo == FALSE.
* app/paint/gimppaintcore.c (gimp_paint_core_finish)
* app/tools/gimpinktool.c (ink_finish): invalidate both the
drawable and the image preview since invalidating the drawable
doesn't invalidate the image any more.
* app/text/gimptextlayer.c (gimp_text_layer_render_now): also
update the new extents of the text layer, not only the old one.
(gimp_text_layer_render_layout): don't update the drawable since
gimp_drawable_fill() already updated it.
2003-09-07 04:06:53 +08:00
|
|
|
{
|
|
|
|
gimp_drawable_update (GIMP_DRAWABLE (layer),
|
|
|
|
0, 0,
|
2008-11-03 08:09:01 +08:00
|
|
|
gimp_item_get_width (GIMP_ITEM (layer)),
|
|
|
|
gimp_item_get_height (GIMP_ITEM (layer)));
|
To optimize duplicate and/or wrong image updates away, introduced new
2003-09-06 Michael Natterer <mitch@gimp.org>
To optimize duplicate and/or wrong image updates away, introduced
new policy that a child object must never explicitly update or
invalidate its parent object (just like the GUI is not updated
explicitly by the core):
* app/core/gimpdrawable.[ch]: added new signal
GimpDrawable::update(). Never update or invalidate the image when
the drawable is updated or invalidated.
(gimp_drawable_set_visible): don't gimp_drawable_update() the
drawable since its pixels have not changed.
* app/core/gimpimage.[ch]: connect to the "add" and "remove"
signals of the layers and channels containers. Also connect to the
"update" and "visibility_changed" signals of all drawables in
these containers (optimizes away updates issued by drawables which
are not yet added to the image and updates of the selection
mask). Also, don't propagate updates to the image if the emitting
drawable is invisible (optimizes away updates issued by invisible
drawables).
(gimp_image_add_layer,channel)
(gimp_image_remove_layer,channel): don't update the image since
that's done by our "add" and "remove" handlers now.
(gimp_image_position_layer,channel): update just the image, not
the drawable since its pixels have not changed.
(gimp_image_real_colormap_changed)
(gimp_image_set_component_visible): always call
gimp_image_update() *and* gimp_viewable_invalidate_preview() to
get everything updated, since update and invalidate of images are
not connected.
* app/core/gimpimage-undo-push.c (undo_pop_layer,channel): don't
update the drawable since (a) its pixels don't change and (b) the
image updates itself upon adding/removing now.
(undo_pop_layer_mod): replaced gimp_image_update() by
gimp_drawable_update() (just for consistency with other similar
functions).
* app/core/gimplayer.c: connect to "update" of the layer mask and
issue updates on the layer if the mask update has any effect on
the projection.
(gimp_layer_create_mask): don't set the mask's offsets here since
they may be different when we later add the mask to the layer.
* app/core/gimplayermask.c (gimp_layer_mask_set_layer): set the
mask offsets here instead.
* app/core/gimpchannel.c (gimp_channel_translate): update the
channel even if push_undo == FALSE.
* app/paint/gimppaintcore.c (gimp_paint_core_finish)
* app/tools/gimpinktool.c (ink_finish): invalidate both the
drawable and the image preview since invalidating the drawable
doesn't invalidate the image any more.
* app/text/gimptextlayer.c (gimp_text_layer_render_now): also
update the new extents of the text layer, not only the old one.
(gimp_text_layer_render_layout): don't update the drawable since
gimp_drawable_fill() already updated it.
2003-09-07 04:06:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
g_signal_connect (mask, "update",
|
|
|
|
G_CALLBACK (gimp_layer_layer_mask_update),
|
|
|
|
layer);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2003-01-06 06:07:10 +08:00
|
|
|
g_signal_emit (layer, layer_signals[MASK_CHANGED], 0);
|
2001-03-05 04:06:48 +08:00
|
|
|
|
2008-11-20 07:37:15 +08:00
|
|
|
g_object_notify (G_OBJECT (layer), "mask");
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
return layer->mask;
|
|
|
|
}
|
|
|
|
|
2001-01-29 00:44:22 +08:00
|
|
|
GimpLayerMask *
|
2001-12-13 07:48:18 +08:00
|
|
|
gimp_layer_create_mask (const GimpLayer *layer,
|
2006-05-15 00:24:31 +08:00
|
|
|
GimpAddMaskType add_mask_type,
|
|
|
|
GimpChannel *channel)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2003-05-08 01:00:57 +08:00
|
|
|
GimpDrawable *drawable;
|
2003-05-08 19:52:31 +08:00
|
|
|
GimpItem *item;
|
2002-02-21 00:15:53 +08:00
|
|
|
PixelRegion srcPR;
|
|
|
|
PixelRegion destPR;
|
2001-01-29 00:44:22 +08:00
|
|
|
GimpLayerMask *mask;
|
2006-03-29 01:08:36 +08:00
|
|
|
GimpImage *image;
|
2001-01-29 00:44:22 +08:00
|
|
|
gchar *mask_name;
|
2002-03-04 01:38:12 +08:00
|
|
|
GimpRGB black = { 0.0, 0.0, 0.0, GIMP_OPACITY_OPAQUE };
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2002-06-07 03:07:59 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_LAYER (layer), NULL);
|
2006-05-15 00:24:31 +08:00
|
|
|
g_return_val_if_fail (add_mask_type != GIMP_ADD_CHANNEL_MASK ||
|
|
|
|
GIMP_IS_CHANNEL (channel), NULL);
|
2002-06-07 03:07:59 +08:00
|
|
|
|
2003-05-08 01:00:57 +08:00
|
|
|
drawable = GIMP_DRAWABLE (layer);
|
2003-05-08 19:52:31 +08:00
|
|
|
item = GIMP_ITEM (layer);
|
2006-05-15 00:24:31 +08:00
|
|
|
image = gimp_item_get_image (item);
|
2001-02-28 15:54:05 +08:00
|
|
|
|
2001-01-10 11:13:03 +08:00
|
|
|
mask_name = g_strdup_printf (_("%s mask"),
|
2009-09-01 04:47:18 +08:00
|
|
|
gimp_object_get_name (layer));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
mask = gimp_layer_mask_new (image,
|
2008-11-03 08:09:01 +08:00
|
|
|
gimp_item_get_width (item),
|
|
|
|
gimp_item_get_height (item),
|
2006-04-12 20:49:29 +08:00
|
|
|
mask_name, &black);
|
2002-02-21 00:15:53 +08:00
|
|
|
|
|
|
|
g_free (mask_name);
|
|
|
|
|
2002-08-27 22:17:46 +08:00
|
|
|
switch (add_mask_type)
|
|
|
|
{
|
|
|
|
case GIMP_ADD_WHITE_MASK:
|
|
|
|
gimp_channel_all (GIMP_CHANNEL (mask), FALSE);
|
|
|
|
return mask;
|
|
|
|
|
|
|
|
case GIMP_ADD_BLACK_MASK:
|
2003-09-03 07:07:40 +08:00
|
|
|
gimp_channel_clear (GIMP_CHANNEL (mask), NULL, FALSE);
|
2002-08-27 22:17:46 +08:00
|
|
|
return mask;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2006-05-15 00:24:31 +08:00
|
|
|
pixel_region_init (&destPR, gimp_drawable_get_tiles (GIMP_DRAWABLE (mask)),
|
2006-04-12 20:49:29 +08:00
|
|
|
0, 0,
|
2008-11-03 08:09:01 +08:00
|
|
|
gimp_item_get_width (GIMP_ITEM (mask)),
|
|
|
|
gimp_item_get_height (GIMP_ITEM (mask)),
|
2006-04-12 20:49:29 +08:00
|
|
|
TRUE);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
switch (add_mask_type)
|
|
|
|
{
|
2002-03-18 19:07:34 +08:00
|
|
|
case GIMP_ADD_WHITE_MASK:
|
|
|
|
case GIMP_ADD_BLACK_MASK:
|
1997-11-25 06:05:25 +08:00
|
|
|
break;
|
2001-12-13 07:48:18 +08:00
|
|
|
|
2002-03-18 19:07:34 +08:00
|
|
|
case GIMP_ADD_ALPHA_MASK:
|
2003-11-27 00:00:14 +08:00
|
|
|
case GIMP_ADD_ALPHA_TRANSFER_MASK:
|
2003-05-08 01:00:57 +08:00
|
|
|
if (gimp_drawable_has_alpha (drawable))
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
2006-05-15 00:24:31 +08:00
|
|
|
pixel_region_init (&srcPR, gimp_drawable_get_tiles (drawable),
|
2006-04-12 20:49:29 +08:00
|
|
|
0, 0,
|
2008-11-03 08:09:01 +08:00
|
|
|
gimp_item_get_width (item),
|
|
|
|
gimp_item_get_height (item),
|
2006-04-12 20:49:29 +08:00
|
|
|
FALSE);
|
2003-05-08 19:52:31 +08:00
|
|
|
|
2006-04-12 20:49:29 +08:00
|
|
|
extract_alpha_region (&srcPR, NULL, &destPR);
|
2003-11-26 23:48:50 +08:00
|
|
|
|
2003-11-27 00:00:14 +08:00
|
|
|
if (add_mask_type == GIMP_ADD_ALPHA_TRANSFER_MASK)
|
2003-11-26 23:48:50 +08:00
|
|
|
{
|
|
|
|
void *pr;
|
|
|
|
gint w, h;
|
|
|
|
guchar *alpha_ptr;
|
|
|
|
|
2006-05-15 00:24:31 +08:00
|
|
|
gimp_drawable_push_undo (drawable,
|
2010-06-08 19:24:11 +08:00
|
|
|
C_("undo-type", "Transfer Alpha to Mask"),
|
2003-11-26 23:48:50 +08:00
|
|
|
0, 0,
|
2008-11-03 08:09:01 +08:00
|
|
|
gimp_item_get_width (item),
|
|
|
|
gimp_item_get_height (item),
|
2003-11-26 23:48:50 +08:00
|
|
|
NULL, FALSE);
|
|
|
|
|
2006-05-15 00:24:31 +08:00
|
|
|
pixel_region_init (&srcPR, gimp_drawable_get_tiles (drawable),
|
2003-11-26 23:48:50 +08:00
|
|
|
0, 0,
|
2008-11-03 08:09:01 +08:00
|
|
|
gimp_item_get_width (item),
|
|
|
|
gimp_item_get_height (item),
|
2003-11-26 23:48:50 +08:00
|
|
|
TRUE);
|
|
|
|
|
|
|
|
for (pr = pixel_regions_register (1, &srcPR);
|
|
|
|
pr != NULL;
|
|
|
|
pr = pixel_regions_process (pr))
|
|
|
|
{
|
|
|
|
h = srcPR.h;
|
|
|
|
|
|
|
|
while (h--)
|
|
|
|
{
|
|
|
|
w = srcPR.w;
|
|
|
|
alpha_ptr = (srcPR.data + h * srcPR.rowstride +
|
|
|
|
srcPR.bytes - 1);
|
|
|
|
|
|
|
|
while (w--)
|
|
|
|
{
|
|
|
|
*alpha_ptr = OPAQUE_OPACITY;
|
|
|
|
alpha_ptr += srcPR.bytes;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-04-12 20:49:29 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
break;
|
2001-12-13 07:48:18 +08:00
|
|
|
|
2002-03-18 19:07:34 +08:00
|
|
|
case GIMP_ADD_SELECTION_MASK:
|
2006-05-15 00:24:31 +08:00
|
|
|
case GIMP_ADD_CHANNEL_MASK:
|
2002-02-21 00:15:53 +08:00
|
|
|
{
|
2006-05-15 00:24:31 +08:00
|
|
|
gboolean channel_empty;
|
2008-11-04 05:17:50 +08:00
|
|
|
gint offset_x, offset_y;
|
2006-05-15 00:24:31 +08:00
|
|
|
gint copy_x, copy_y;
|
|
|
|
gint copy_width, copy_height;
|
2002-02-21 00:15:53 +08:00
|
|
|
|
2006-05-15 00:24:31 +08:00
|
|
|
if (add_mask_type == GIMP_ADD_SELECTION_MASK)
|
|
|
|
channel = GIMP_CHANNEL (gimp_image_get_mask (image));
|
|
|
|
|
|
|
|
channel_empty = gimp_channel_is_empty (channel);
|
2002-02-21 00:15:53 +08:00
|
|
|
|
2008-11-04 05:17:50 +08:00
|
|
|
gimp_item_get_offset (item, &offset_x, &offset_y);
|
|
|
|
|
2007-12-24 00:58:41 +08:00
|
|
|
gimp_rectangle_intersect (0, 0,
|
2007-12-26 00:21:40 +08:00
|
|
|
gimp_image_get_width (image),
|
|
|
|
gimp_image_get_height (image),
|
2008-11-04 05:17:50 +08:00
|
|
|
offset_x, offset_y,
|
2008-11-03 08:09:01 +08:00
|
|
|
gimp_item_get_width (item),
|
|
|
|
gimp_item_get_height (item),
|
2007-12-24 00:58:41 +08:00
|
|
|
©_x, ©_y,
|
|
|
|
©_width, ©_height);
|
2003-05-08 01:00:57 +08:00
|
|
|
|
2008-11-03 08:09:01 +08:00
|
|
|
if (copy_width < gimp_item_get_width (item) ||
|
|
|
|
copy_height < gimp_item_get_height (item) ||
|
2006-05-15 00:24:31 +08:00
|
|
|
channel_empty)
|
2003-09-03 07:07:40 +08:00
|
|
|
gimp_channel_clear (GIMP_CHANNEL (mask), NULL, FALSE);
|
2003-05-08 01:00:57 +08:00
|
|
|
|
2006-05-15 00:24:31 +08:00
|
|
|
if ((copy_width || copy_height) && ! channel_empty)
|
2003-05-08 01:00:57 +08:00
|
|
|
{
|
2006-05-15 00:24:31 +08:00
|
|
|
pixel_region_init (&srcPR,
|
|
|
|
gimp_drawable_get_tiles (GIMP_DRAWABLE (channel)),
|
2003-05-14 23:32:07 +08:00
|
|
|
copy_x, copy_y,
|
|
|
|
copy_width, copy_height,
|
2003-05-08 01:00:57 +08:00
|
|
|
FALSE);
|
2006-05-15 00:24:31 +08:00
|
|
|
pixel_region_init (&destPR,
|
|
|
|
gimp_drawable_get_tiles (GIMP_DRAWABLE (mask)),
|
2008-11-04 05:17:50 +08:00
|
|
|
copy_x - offset_x, copy_y - offset_y,
|
2003-05-14 23:32:07 +08:00
|
|
|
copy_width, copy_height,
|
|
|
|
TRUE);
|
2003-05-08 01:00:57 +08:00
|
|
|
|
|
|
|
copy_region (&srcPR, &destPR);
|
2003-08-28 01:21:49 +08:00
|
|
|
|
2003-05-14 23:32:07 +08:00
|
|
|
GIMP_CHANNEL (mask)->bounds_known = FALSE;
|
2003-05-08 01:00:57 +08:00
|
|
|
}
|
2002-02-21 00:15:53 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2002-03-18 19:07:34 +08:00
|
|
|
case GIMP_ADD_COPY_MASK:
|
2002-02-21 00:15:53 +08:00
|
|
|
{
|
2009-09-08 23:49:48 +08:00
|
|
|
TileManager *copy_tiles = NULL;
|
2002-02-21 00:15:53 +08:00
|
|
|
|
2009-09-08 23:49:48 +08:00
|
|
|
if (! gimp_drawable_is_gray (drawable))
|
2003-03-03 20:36:42 +08:00
|
|
|
{
|
|
|
|
GimpImageType copy_type;
|
2002-02-21 00:15:53 +08:00
|
|
|
|
2009-09-08 23:49:48 +08:00
|
|
|
copy_type = (gimp_drawable_has_alpha (drawable) ?
|
2003-03-03 20:36:42 +08:00
|
|
|
GIMP_GRAYA_IMAGE : GIMP_GRAY_IMAGE);
|
2002-02-21 00:15:53 +08:00
|
|
|
|
2008-11-03 08:09:01 +08:00
|
|
|
copy_tiles = tile_manager_new (gimp_item_get_width (item),
|
|
|
|
gimp_item_get_height (item),
|
2003-03-03 20:36:42 +08:00
|
|
|
GIMP_IMAGE_TYPE_BYTES (copy_type));
|
2002-02-21 00:15:53 +08:00
|
|
|
|
2009-09-08 23:49:48 +08:00
|
|
|
gimp_drawable_convert_tiles_grayscale (drawable, copy_tiles);
|
2003-03-03 20:36:42 +08:00
|
|
|
|
|
|
|
pixel_region_init (&srcPR, copy_tiles,
|
|
|
|
0, 0,
|
2008-11-03 08:09:01 +08:00
|
|
|
gimp_item_get_width (item),
|
|
|
|
gimp_item_get_height (item),
|
2003-03-03 20:36:42 +08:00
|
|
|
FALSE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-05-15 00:24:31 +08:00
|
|
|
pixel_region_init (&srcPR, gimp_drawable_get_tiles (drawable),
|
2003-03-03 20:36:42 +08:00
|
|
|
0, 0,
|
2008-11-03 08:09:01 +08:00
|
|
|
gimp_item_get_width (item),
|
|
|
|
gimp_item_get_height (item),
|
2003-03-03 20:36:42 +08:00
|
|
|
FALSE);
|
|
|
|
}
|
2002-02-21 00:15:53 +08:00
|
|
|
|
2003-05-08 01:00:57 +08:00
|
|
|
if (gimp_drawable_has_alpha (drawable))
|
2002-02-21 00:15:53 +08:00
|
|
|
{
|
2003-03-03 20:36:42 +08:00
|
|
|
guchar black_uchar[] = { 0, 0, 0, 0 };
|
|
|
|
|
2002-02-21 00:15:53 +08:00
|
|
|
flatten_region (&srcPR, &destPR, black_uchar);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
copy_region (&srcPR, &destPR);
|
|
|
|
}
|
|
|
|
|
2003-03-03 20:36:42 +08:00
|
|
|
if (copy_tiles)
|
2003-05-27 01:02:06 +08:00
|
|
|
tile_manager_unref (copy_tiles);
|
2002-02-21 00:15:53 +08:00
|
|
|
}
|
2002-08-27 22:17:46 +08:00
|
|
|
|
|
|
|
GIMP_CHANNEL (mask)->bounds_known = FALSE;
|
2002-02-21 00:15:53 +08:00
|
|
|
break;
|
|
|
|
}
|
2001-01-29 00:44:22 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
return mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2002-03-18 19:07:34 +08:00
|
|
|
gimp_layer_apply_mask (GimpLayer *layer,
|
2006-04-12 20:49:29 +08:00
|
|
|
GimpMaskApplyMode mode,
|
2002-03-18 19:07:34 +08:00
|
|
|
gboolean push_undo)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2007-12-24 00:58:41 +08:00
|
|
|
GimpItem *item;
|
|
|
|
GimpImage *image;
|
|
|
|
GimpLayerMask *mask;
|
|
|
|
PixelRegion srcPR, maskPR;
|
|
|
|
gboolean view_changed = FALSE;
|
2001-03-05 04:06:48 +08:00
|
|
|
|
|
|
|
g_return_if_fail (GIMP_IS_LAYER (layer));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2007-12-24 00:58:41 +08:00
|
|
|
mask = gimp_layer_get_mask (layer);
|
|
|
|
|
|
|
|
if (! mask)
|
1997-11-25 06:05:25 +08:00
|
|
|
return;
|
|
|
|
|
2007-09-16 03:23:20 +08:00
|
|
|
/* APPLY can only be done to layers with an alpha channel */
|
2002-02-01 00:47:20 +08:00
|
|
|
if (! gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)))
|
2007-09-16 03:23:20 +08:00
|
|
|
g_return_if_fail (mode == GIMP_MASK_DISCARD || push_undo == TRUE);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2007-12-24 00:58:41 +08:00
|
|
|
item = GIMP_ITEM (layer);
|
2006-03-29 01:08:36 +08:00
|
|
|
image = gimp_item_get_image (item);
|
2001-03-05 04:06:48 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
if (! image)
|
2001-03-05 04:06:48 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (push_undo)
|
|
|
|
{
|
2006-03-29 01:08:36 +08:00
|
|
|
gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_LAYER_APPLY_MASK,
|
2004-02-29 02:56:55 +08:00
|
|
|
(mode == GIMP_MASK_APPLY) ?
|
2010-06-08 19:24:11 +08:00
|
|
|
C_("undo-type", "Apply Layer Mask") :
|
|
|
|
C_("undo-type", "Delete Layer Mask"));
|
2001-03-05 04:06:48 +08:00
|
|
|
|
2007-12-24 00:58:41 +08:00
|
|
|
gimp_image_undo_push_layer_mask_remove (image, NULL, layer, mask);
|
2007-09-16 03:23:20 +08:00
|
|
|
|
|
|
|
if (mode == GIMP_MASK_APPLY &&
|
|
|
|
! gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)))
|
|
|
|
{
|
|
|
|
gimp_layer_add_alpha (layer);
|
|
|
|
}
|
2001-03-05 04:06:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* check if applying the mask changes the projection */
|
2007-12-24 00:58:41 +08:00
|
|
|
if (gimp_layer_mask_get_show (mask) ||
|
|
|
|
(mode == GIMP_MASK_APPLY && ! gimp_layer_mask_get_apply (mask)) ||
|
|
|
|
(mode == GIMP_MASK_DISCARD && gimp_layer_mask_get_apply (mask)))
|
2001-03-05 04:06:48 +08:00
|
|
|
{
|
|
|
|
view_changed = TRUE;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2002-03-18 19:07:34 +08:00
|
|
|
if (mode == GIMP_MASK_APPLY)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2001-03-05 04:06:48 +08:00
|
|
|
if (push_undo)
|
2003-02-14 22:14:29 +08:00
|
|
|
gimp_drawable_push_undo (GIMP_DRAWABLE (layer), NULL,
|
2002-06-07 03:44:05 +08:00
|
|
|
0, 0,
|
2008-11-03 08:09:01 +08:00
|
|
|
gimp_item_get_width (item),
|
|
|
|
gimp_item_get_height (item),
|
2002-06-07 03:44:05 +08:00
|
|
|
NULL, FALSE);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Combine the current layer's alpha channel and the mask */
|
2007-12-24 00:58:41 +08:00
|
|
|
pixel_region_init (&srcPR,
|
|
|
|
gimp_drawable_get_tiles (GIMP_DRAWABLE (layer)),
|
2006-04-12 20:49:29 +08:00
|
|
|
0, 0,
|
2008-11-03 08:09:01 +08:00
|
|
|
gimp_item_get_width (item),
|
|
|
|
gimp_item_get_height (item),
|
2006-04-12 20:49:29 +08:00
|
|
|
TRUE);
|
2007-12-24 00:58:41 +08:00
|
|
|
pixel_region_init (&maskPR,
|
|
|
|
gimp_drawable_get_tiles (GIMP_DRAWABLE (mask)),
|
2006-04-12 20:49:29 +08:00
|
|
|
0, 0,
|
2008-11-03 08:09:01 +08:00
|
|
|
gimp_item_get_width (item),
|
|
|
|
gimp_item_get_height (item),
|
2006-04-12 20:49:29 +08:00
|
|
|
FALSE);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1998-01-25 09:24:46 +08:00
|
|
|
apply_mask_to_region (&srcPR, &maskPR, OPAQUE_OPACITY);
|
2001-03-05 04:06:48 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2007-12-24 00:58:41 +08:00
|
|
|
g_signal_handlers_disconnect_by_func (mask,
|
To optimize duplicate and/or wrong image updates away, introduced new
2003-09-06 Michael Natterer <mitch@gimp.org>
To optimize duplicate and/or wrong image updates away, introduced
new policy that a child object must never explicitly update or
invalidate its parent object (just like the GUI is not updated
explicitly by the core):
* app/core/gimpdrawable.[ch]: added new signal
GimpDrawable::update(). Never update or invalidate the image when
the drawable is updated or invalidated.
(gimp_drawable_set_visible): don't gimp_drawable_update() the
drawable since its pixels have not changed.
* app/core/gimpimage.[ch]: connect to the "add" and "remove"
signals of the layers and channels containers. Also connect to the
"update" and "visibility_changed" signals of all drawables in
these containers (optimizes away updates issued by drawables which
are not yet added to the image and updates of the selection
mask). Also, don't propagate updates to the image if the emitting
drawable is invisible (optimizes away updates issued by invisible
drawables).
(gimp_image_add_layer,channel)
(gimp_image_remove_layer,channel): don't update the image since
that's done by our "add" and "remove" handlers now.
(gimp_image_position_layer,channel): update just the image, not
the drawable since its pixels have not changed.
(gimp_image_real_colormap_changed)
(gimp_image_set_component_visible): always call
gimp_image_update() *and* gimp_viewable_invalidate_preview() to
get everything updated, since update and invalidate of images are
not connected.
* app/core/gimpimage-undo-push.c (undo_pop_layer,channel): don't
update the drawable since (a) its pixels don't change and (b) the
image updates itself upon adding/removing now.
(undo_pop_layer_mod): replaced gimp_image_update() by
gimp_drawable_update() (just for consistency with other similar
functions).
* app/core/gimplayer.c: connect to "update" of the layer mask and
issue updates on the layer if the mask update has any effect on
the projection.
(gimp_layer_create_mask): don't set the mask's offsets here since
they may be different when we later add the mask to the layer.
* app/core/gimplayermask.c (gimp_layer_mask_set_layer): set the
mask offsets here instead.
* app/core/gimpchannel.c (gimp_channel_translate): update the
channel even if push_undo == FALSE.
* app/paint/gimppaintcore.c (gimp_paint_core_finish)
* app/tools/gimpinktool.c (ink_finish): invalidate both the
drawable and the image preview since invalidating the drawable
doesn't invalidate the image any more.
* app/text/gimptextlayer.c (gimp_text_layer_render_now): also
update the new extents of the text layer, not only the old one.
(gimp_text_layer_render_layout): don't update the drawable since
gimp_drawable_fill() already updated it.
2003-09-07 04:06:53 +08:00
|
|
|
gimp_layer_layer_mask_update,
|
|
|
|
layer);
|
|
|
|
|
2007-12-24 00:58:41 +08:00
|
|
|
gimp_item_removed (GIMP_ITEM (mask));
|
|
|
|
g_object_unref (mask);
|
2001-03-06 21:28:39 +08:00
|
|
|
layer->mask = NULL;
|
2001-03-05 04:06:48 +08:00
|
|
|
|
|
|
|
if (push_undo)
|
2006-03-29 01:08:36 +08:00
|
|
|
gimp_image_undo_group_end (image);
|
2001-03-05 04:06:48 +08:00
|
|
|
|
2008-11-03 02:39:10 +08:00
|
|
|
if (layer->opacity_node)
|
|
|
|
gegl_node_disconnect (layer->opacity_node, "aux");
|
2008-10-10 04:44:23 +08:00
|
|
|
|
2001-03-05 04:06:48 +08:00
|
|
|
/* If applying actually changed the view */
|
|
|
|
if (view_changed)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2001-07-08 06:49:01 +08:00
|
|
|
gimp_drawable_update (GIMP_DRAWABLE (layer),
|
2006-04-12 20:49:29 +08:00
|
|
|
0, 0,
|
2008-11-03 08:09:01 +08:00
|
|
|
gimp_item_get_width (item),
|
|
|
|
gimp_item_get_height (item));
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
2003-03-24 20:21:58 +08:00
|
|
|
else
|
|
|
|
{
|
2003-04-07 17:27:08 +08:00
|
|
|
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (layer));
|
2003-03-24 20:21:58 +08:00
|
|
|
}
|
2001-03-05 04:06:48 +08:00
|
|
|
|
2003-01-06 06:07:10 +08:00
|
|
|
g_signal_emit (layer, layer_signals[MASK_CHANGED], 0);
|
2008-11-20 07:37:15 +08:00
|
|
|
|
|
|
|
g_object_notify (G_OBJECT (layer), "mask");
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-01-29 00:44:22 +08:00
|
|
|
gimp_layer_add_alpha (GimpLayer *layer)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2007-12-24 00:58:41 +08:00
|
|
|
GimpItem *item;
|
2008-11-04 05:17:50 +08:00
|
|
|
GimpDrawable *drawable;
|
2001-01-29 00:44:22 +08:00
|
|
|
PixelRegion srcPR, destPR;
|
|
|
|
TileManager *new_tiles;
|
2003-08-28 01:21:49 +08:00
|
|
|
GimpImageType new_type;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2002-06-07 03:07:59 +08:00
|
|
|
g_return_if_fail (GIMP_IS_LAYER (layer));
|
|
|
|
|
2001-12-13 07:48:18 +08:00
|
|
|
if (gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)))
|
|
|
|
return;
|
|
|
|
|
2008-11-04 05:17:50 +08:00
|
|
|
item = GIMP_ITEM (layer);
|
|
|
|
drawable = GIMP_DRAWABLE (layer);
|
2007-12-24 00:58:41 +08:00
|
|
|
|
2008-11-04 05:17:50 +08:00
|
|
|
new_type = gimp_drawable_type_with_alpha (drawable);
|
2003-08-28 01:21:49 +08:00
|
|
|
|
|
|
|
/* Allocate the new tiles */
|
2008-11-03 08:09:01 +08:00
|
|
|
new_tiles = tile_manager_new (gimp_item_get_width (item),
|
|
|
|
gimp_item_get_height (item),
|
2006-04-12 20:49:29 +08:00
|
|
|
GIMP_IMAGE_TYPE_BYTES (new_type));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Configure the pixel regions */
|
2008-11-04 05:17:50 +08:00
|
|
|
pixel_region_init (&srcPR, gimp_drawable_get_tiles (drawable),
|
2006-04-12 20:49:29 +08:00
|
|
|
0, 0,
|
2008-11-03 08:09:01 +08:00
|
|
|
gimp_item_get_width (item),
|
|
|
|
gimp_item_get_height (item),
|
2006-04-12 20:49:29 +08:00
|
|
|
FALSE);
|
2003-08-28 01:21:49 +08:00
|
|
|
pixel_region_init (&destPR, new_tiles,
|
2006-04-12 20:49:29 +08:00
|
|
|
0, 0,
|
2008-11-03 08:09:01 +08:00
|
|
|
gimp_item_get_width (item),
|
|
|
|
gimp_item_get_height (item),
|
2006-04-12 20:49:29 +08:00
|
|
|
TRUE);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Add an alpha channel */
|
|
|
|
add_alpha_region (&srcPR, &destPR);
|
|
|
|
|
2004-03-14 19:34:31 +08:00
|
|
|
/* Set the new tiles */
|
2008-11-04 04:51:46 +08:00
|
|
|
gimp_drawable_set_tiles (GIMP_DRAWABLE (layer),
|
|
|
|
gimp_item_is_attached (GIMP_ITEM (layer)),
|
2010-06-08 19:24:11 +08:00
|
|
|
C_("undo-type", "Add Alpha Channel"),
|
2008-11-04 04:51:46 +08:00
|
|
|
new_tiles, new_type);
|
2004-03-14 19:34:31 +08:00
|
|
|
tile_manager_unref (new_tiles);
|
2000-02-27 02:46:08 +08:00
|
|
|
}
|
|
|
|
|
2005-08-08 00:38:35 +08:00
|
|
|
void
|
|
|
|
gimp_layer_flatten (GimpLayer *layer,
|
|
|
|
GimpContext *context)
|
|
|
|
{
|
2007-12-24 00:58:41 +08:00
|
|
|
GimpItem *item;
|
2008-11-04 05:17:50 +08:00
|
|
|
GimpDrawable *drawable;
|
2005-08-08 00:38:35 +08:00
|
|
|
PixelRegion srcPR, destPR;
|
|
|
|
TileManager *new_tiles;
|
|
|
|
GimpImageType new_type;
|
|
|
|
guchar bg[4];
|
|
|
|
|
|
|
|
g_return_if_fail (GIMP_IS_LAYER (layer));
|
|
|
|
g_return_if_fail (GIMP_IS_CONTEXT (context));
|
|
|
|
|
|
|
|
if (! gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)))
|
|
|
|
return;
|
|
|
|
|
2008-11-04 05:17:50 +08:00
|
|
|
item = GIMP_ITEM (layer);
|
|
|
|
drawable = GIMP_DRAWABLE (layer);
|
2007-12-24 00:58:41 +08:00
|
|
|
|
2008-11-04 05:17:50 +08:00
|
|
|
new_type = gimp_drawable_type_without_alpha (drawable);
|
2005-08-08 00:38:35 +08:00
|
|
|
|
2008-11-04 05:17:50 +08:00
|
|
|
gimp_image_get_background (gimp_item_get_image (item), context,
|
|
|
|
gimp_drawable_type (drawable),
|
2006-10-26 06:14:36 +08:00
|
|
|
bg);
|
2005-08-08 00:38:35 +08:00
|
|
|
|
|
|
|
/* Allocate the new tiles */
|
2008-11-03 08:09:01 +08:00
|
|
|
new_tiles = tile_manager_new (gimp_item_get_width (item),
|
|
|
|
gimp_item_get_height (item),
|
2006-04-12 20:49:29 +08:00
|
|
|
GIMP_IMAGE_TYPE_BYTES (new_type));
|
2005-08-08 00:38:35 +08:00
|
|
|
|
|
|
|
/* Configure the pixel regions */
|
2008-11-04 05:17:50 +08:00
|
|
|
pixel_region_init (&srcPR, gimp_drawable_get_tiles (drawable),
|
2006-04-12 20:49:29 +08:00
|
|
|
0, 0,
|
2008-11-03 08:09:01 +08:00
|
|
|
gimp_item_get_width (item),
|
|
|
|
gimp_item_get_height (item),
|
2006-04-12 20:49:29 +08:00
|
|
|
FALSE);
|
2005-08-08 00:38:35 +08:00
|
|
|
pixel_region_init (&destPR, new_tiles,
|
2006-04-12 20:49:29 +08:00
|
|
|
0, 0,
|
2008-11-03 08:09:01 +08:00
|
|
|
gimp_item_get_width (item),
|
|
|
|
gimp_item_get_height (item),
|
2006-04-12 20:49:29 +08:00
|
|
|
TRUE);
|
2005-08-08 00:38:35 +08:00
|
|
|
|
|
|
|
/* Remove alpha channel */
|
|
|
|
flatten_region (&srcPR, &destPR, bg);
|
|
|
|
|
|
|
|
/* Set the new tiles */
|
2008-11-04 04:51:46 +08:00
|
|
|
gimp_drawable_set_tiles (GIMP_DRAWABLE (layer),
|
|
|
|
gimp_item_is_attached (GIMP_ITEM (layer)),
|
2010-06-08 19:24:11 +08:00
|
|
|
C_("undo-type", "Remove Alpha Channel"),
|
2008-11-04 04:51:46 +08:00
|
|
|
new_tiles, new_type);
|
2005-08-08 00:38:35 +08:00
|
|
|
tile_manager_unref (new_tiles);
|
|
|
|
}
|
|
|
|
|
1999-11-27 22:00:26 +08:00
|
|
|
void
|
2004-04-15 07:37:34 +08:00
|
|
|
gimp_layer_resize_to_image (GimpLayer *layer,
|
|
|
|
GimpContext *context)
|
1999-11-27 22:00:26 +08:00
|
|
|
{
|
2006-03-29 01:08:36 +08:00
|
|
|
GimpImage *image;
|
2001-01-29 00:44:22 +08:00
|
|
|
gint offset_x;
|
|
|
|
gint offset_y;
|
1999-11-27 22:00:26 +08:00
|
|
|
|
2002-06-07 03:07:59 +08:00
|
|
|
g_return_if_fail (GIMP_IS_LAYER (layer));
|
2004-11-16 21:41:55 +08:00
|
|
|
g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (layer)));
|
2004-04-15 07:37:34 +08:00
|
|
|
g_return_if_fail (GIMP_IS_CONTEXT (context));
|
2002-06-07 03:07:59 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
image = gimp_item_get_image (GIMP_ITEM (layer));
|
1999-11-27 22:00:26 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_ITEM_RESIZE,
|
2010-06-08 19:24:11 +08:00
|
|
|
C_("undo-type", "Layer to Image Size"));
|
1999-11-27 22:00:26 +08:00
|
|
|
|
2008-11-03 07:03:29 +08:00
|
|
|
gimp_item_get_offset (GIMP_ITEM (layer), &offset_x, &offset_y);
|
2004-04-15 07:37:34 +08:00
|
|
|
gimp_item_resize (GIMP_ITEM (layer), context,
|
2007-12-26 00:21:40 +08:00
|
|
|
gimp_image_get_width (image),
|
|
|
|
gimp_image_get_height (image),
|
|
|
|
offset_x, offset_y);
|
1999-11-27 22:00:26 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
gimp_image_undo_group_end (image);
|
1999-11-27 22:00:26 +08:00
|
|
|
}
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
/**********************/
|
|
|
|
/* access functions */
|
|
|
|
/**********************/
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2009-01-27 06:47:16 +08:00
|
|
|
GimpDrawable *
|
2009-02-01 18:22:22 +08:00
|
|
|
gimp_layer_get_floating_sel_drawable (const GimpLayer *layer)
|
2009-01-27 06:47:16 +08:00
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_LAYER (layer), NULL);
|
|
|
|
|
|
|
|
return layer->fs.drawable;
|
|
|
|
}
|
|
|
|
|
2008-11-17 08:02:15 +08:00
|
|
|
void
|
|
|
|
gimp_layer_set_floating_sel_drawable (GimpLayer *layer,
|
|
|
|
GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_LAYER (layer));
|
|
|
|
g_return_if_fail (drawable == NULL || GIMP_IS_DRAWABLE (drawable));
|
|
|
|
|
|
|
|
if (layer->fs.drawable != drawable)
|
|
|
|
{
|
|
|
|
if (layer->fs.segs)
|
|
|
|
{
|
|
|
|
g_free (layer->fs.segs);
|
|
|
|
layer->fs.segs = NULL;
|
|
|
|
layer->fs.num_segs = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
layer->fs.drawable = drawable;
|
|
|
|
|
|
|
|
g_object_notify (G_OBJECT (layer), "floating-selection");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
gboolean
|
2001-12-13 07:48:18 +08:00
|
|
|
gimp_layer_is_floating_sel (const GimpLayer *layer)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2001-01-29 00:44:22 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_LAYER (layer), FALSE);
|
|
|
|
|
2009-01-27 06:47:16 +08:00
|
|
|
return (gimp_layer_get_floating_sel_drawable (layer) != NULL);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2001-03-12 01:24:47 +08:00
|
|
|
void
|
|
|
|
gimp_layer_set_opacity (GimpLayer *layer,
|
Made drawable/layer properties (visibility, opacity etc.) undoable (fixes
2003-03-17 Michael Natterer <mitch@gimp.org>
Made drawable/layer properties (visibility, opacity etc.)
undoable (fixes bug #73893).
* app/core/core-enums.[ch]: added undo types/groups for
visibility, mode, opacity, linked and preserve_trans.
* app/core/Makefile.am
* app/core/core-types.h
* app/core/gimpitemundo.[ch]: new GimpUndo subclass which holds a
ref'ed GimpItem pointer so (1) this doesn't need to be done by all
undo steps related to an item and (2) the item the undo step is
for can be determined from outside the undo system.
* app/core/gimpimage-undo.[ch]: added gimp_image_undo_push_item()
which returns a new GimpItemUndo.
* app/core/gimpimage-undo-push.[ch]: use it for all item related
undo steps. Removed lots of GimpItem, GimpLayer, GimpDrawable
and GimpVectors pointers from the private undo structs. Added
undo push functions for the new undo types added above.
* app/core/gimpdrawable.[ch] (gimp_drawable_set_visible): added
"gboolean push_undo" parameter.
* app/core/gimplayer.[ch] (gimp_layer_set_opacity, _mode,
_preserve_trans, _linked): added "gboolean push_undo" parameters.
* app/core/gimpimage-mask.c
* app/core/gimpimage-merge.c
* app/core/gimplayer-floating-sel.c
* app/tools/gimpmovetool.c
* app/xcf/xcf-load.c
* app/widgets/gimpdrawablelistitem.c
* app/widgets/gimplayerlistitem.c
* app/widgets/gimplayerlistview.c: changed accordingly.
* tools/pdbgen/pdb/channel.pdb
* tools/pdbgen/pdb/layer.pdb: ditto. Added '$undo' paramaters to
the foo_accessors() functions. Removed $func from foo_accesors()
because we don't manipulate items without using getters/setters
any longer.
* app/pdb/channel_cmds.c
* app/pdb/layer_cmds.c: regenerated.
* app/widgets/gimpcellrenderertoggle.[ch]: added "clicked" signal
which carries an additional "GdkModifierType state" parameter as
in GimpCellRendererViewable .
* app/widgets/gimpcontainertreeview.c: emit "clicked" from
the toggle renderer, not "toggled" so the callbacks get the
modifier state.
* app/widgets/gimpdrawabletreeview.c: resurrected the "exclusive
visible by <shift>+click" feature as in 1.2.
* app/widgets/gimplayertreeview.c: compress layer opacity undos by
looking at the top of the undo stack and not pushing an undo if
there already is a GIMP_UNDO_DRAWABLE_OPACITY for the active
layer.
2003-03-18 02:02:41 +08:00
|
|
|
gdouble opacity,
|
|
|
|
gboolean push_undo)
|
2001-03-12 01:24:47 +08:00
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_LAYER (layer));
|
|
|
|
|
2002-03-04 22:52:54 +08:00
|
|
|
opacity = CLAMP (opacity, GIMP_OPACITY_TRANSPARENT, GIMP_OPACITY_OPAQUE);
|
2001-03-12 01:24:47 +08:00
|
|
|
|
2002-03-04 22:52:54 +08:00
|
|
|
if (layer->opacity != opacity)
|
2001-03-12 01:24:47 +08:00
|
|
|
{
|
2004-11-16 21:41:55 +08:00
|
|
|
if (push_undo && gimp_item_is_attached (GIMP_ITEM (layer)))
|
Made drawable/layer properties (visibility, opacity etc.) undoable (fixes
2003-03-17 Michael Natterer <mitch@gimp.org>
Made drawable/layer properties (visibility, opacity etc.)
undoable (fixes bug #73893).
* app/core/core-enums.[ch]: added undo types/groups for
visibility, mode, opacity, linked and preserve_trans.
* app/core/Makefile.am
* app/core/core-types.h
* app/core/gimpitemundo.[ch]: new GimpUndo subclass which holds a
ref'ed GimpItem pointer so (1) this doesn't need to be done by all
undo steps related to an item and (2) the item the undo step is
for can be determined from outside the undo system.
* app/core/gimpimage-undo.[ch]: added gimp_image_undo_push_item()
which returns a new GimpItemUndo.
* app/core/gimpimage-undo-push.[ch]: use it for all item related
undo steps. Removed lots of GimpItem, GimpLayer, GimpDrawable
and GimpVectors pointers from the private undo structs. Added
undo push functions for the new undo types added above.
* app/core/gimpdrawable.[ch] (gimp_drawable_set_visible): added
"gboolean push_undo" parameter.
* app/core/gimplayer.[ch] (gimp_layer_set_opacity, _mode,
_preserve_trans, _linked): added "gboolean push_undo" parameters.
* app/core/gimpimage-mask.c
* app/core/gimpimage-merge.c
* app/core/gimplayer-floating-sel.c
* app/tools/gimpmovetool.c
* app/xcf/xcf-load.c
* app/widgets/gimpdrawablelistitem.c
* app/widgets/gimplayerlistitem.c
* app/widgets/gimplayerlistview.c: changed accordingly.
* tools/pdbgen/pdb/channel.pdb
* tools/pdbgen/pdb/layer.pdb: ditto. Added '$undo' paramaters to
the foo_accessors() functions. Removed $func from foo_accesors()
because we don't manipulate items without using getters/setters
any longer.
* app/pdb/channel_cmds.c
* app/pdb/layer_cmds.c: regenerated.
* app/widgets/gimpcellrenderertoggle.[ch]: added "clicked" signal
which carries an additional "GdkModifierType state" parameter as
in GimpCellRendererViewable .
* app/widgets/gimpcontainertreeview.c: emit "clicked" from
the toggle renderer, not "toggled" so the callbacks get the
modifier state.
* app/widgets/gimpdrawabletreeview.c: resurrected the "exclusive
visible by <shift>+click" feature as in 1.2.
* app/widgets/gimplayertreeview.c: compress layer opacity undos by
looking at the top of the undo stack and not pushing an undo if
there already is a GIMP_UNDO_DRAWABLE_OPACITY for the active
layer.
2003-03-18 02:02:41 +08:00
|
|
|
{
|
2006-03-29 01:08:36 +08:00
|
|
|
GimpImage *image = gimp_item_get_image (GIMP_ITEM (layer));
|
Made drawable/layer properties (visibility, opacity etc.) undoable (fixes
2003-03-17 Michael Natterer <mitch@gimp.org>
Made drawable/layer properties (visibility, opacity etc.)
undoable (fixes bug #73893).
* app/core/core-enums.[ch]: added undo types/groups for
visibility, mode, opacity, linked and preserve_trans.
* app/core/Makefile.am
* app/core/core-types.h
* app/core/gimpitemundo.[ch]: new GimpUndo subclass which holds a
ref'ed GimpItem pointer so (1) this doesn't need to be done by all
undo steps related to an item and (2) the item the undo step is
for can be determined from outside the undo system.
* app/core/gimpimage-undo.[ch]: added gimp_image_undo_push_item()
which returns a new GimpItemUndo.
* app/core/gimpimage-undo-push.[ch]: use it for all item related
undo steps. Removed lots of GimpItem, GimpLayer, GimpDrawable
and GimpVectors pointers from the private undo structs. Added
undo push functions for the new undo types added above.
* app/core/gimpdrawable.[ch] (gimp_drawable_set_visible): added
"gboolean push_undo" parameter.
* app/core/gimplayer.[ch] (gimp_layer_set_opacity, _mode,
_preserve_trans, _linked): added "gboolean push_undo" parameters.
* app/core/gimpimage-mask.c
* app/core/gimpimage-merge.c
* app/core/gimplayer-floating-sel.c
* app/tools/gimpmovetool.c
* app/xcf/xcf-load.c
* app/widgets/gimpdrawablelistitem.c
* app/widgets/gimplayerlistitem.c
* app/widgets/gimplayerlistview.c: changed accordingly.
* tools/pdbgen/pdb/channel.pdb
* tools/pdbgen/pdb/layer.pdb: ditto. Added '$undo' paramaters to
the foo_accessors() functions. Removed $func from foo_accesors()
because we don't manipulate items without using getters/setters
any longer.
* app/pdb/channel_cmds.c
* app/pdb/layer_cmds.c: regenerated.
* app/widgets/gimpcellrenderertoggle.[ch]: added "clicked" signal
which carries an additional "GdkModifierType state" parameter as
in GimpCellRendererViewable .
* app/widgets/gimpcontainertreeview.c: emit "clicked" from
the toggle renderer, not "toggled" so the callbacks get the
modifier state.
* app/widgets/gimpdrawabletreeview.c: resurrected the "exclusive
visible by <shift>+click" feature as in 1.2.
* app/widgets/gimplayertreeview.c: compress layer opacity undos by
looking at the top of the undo stack and not pushing an undo if
there already is a GIMP_UNDO_DRAWABLE_OPACITY for the active
layer.
2003-03-18 02:02:41 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
gimp_image_undo_push_layer_opacity (image, NULL, layer);
|
Made drawable/layer properties (visibility, opacity etc.) undoable (fixes
2003-03-17 Michael Natterer <mitch@gimp.org>
Made drawable/layer properties (visibility, opacity etc.)
undoable (fixes bug #73893).
* app/core/core-enums.[ch]: added undo types/groups for
visibility, mode, opacity, linked and preserve_trans.
* app/core/Makefile.am
* app/core/core-types.h
* app/core/gimpitemundo.[ch]: new GimpUndo subclass which holds a
ref'ed GimpItem pointer so (1) this doesn't need to be done by all
undo steps related to an item and (2) the item the undo step is
for can be determined from outside the undo system.
* app/core/gimpimage-undo.[ch]: added gimp_image_undo_push_item()
which returns a new GimpItemUndo.
* app/core/gimpimage-undo-push.[ch]: use it for all item related
undo steps. Removed lots of GimpItem, GimpLayer, GimpDrawable
and GimpVectors pointers from the private undo structs. Added
undo push functions for the new undo types added above.
* app/core/gimpdrawable.[ch] (gimp_drawable_set_visible): added
"gboolean push_undo" parameter.
* app/core/gimplayer.[ch] (gimp_layer_set_opacity, _mode,
_preserve_trans, _linked): added "gboolean push_undo" parameters.
* app/core/gimpimage-mask.c
* app/core/gimpimage-merge.c
* app/core/gimplayer-floating-sel.c
* app/tools/gimpmovetool.c
* app/xcf/xcf-load.c
* app/widgets/gimpdrawablelistitem.c
* app/widgets/gimplayerlistitem.c
* app/widgets/gimplayerlistview.c: changed accordingly.
* tools/pdbgen/pdb/channel.pdb
* tools/pdbgen/pdb/layer.pdb: ditto. Added '$undo' paramaters to
the foo_accessors() functions. Removed $func from foo_accesors()
because we don't manipulate items without using getters/setters
any longer.
* app/pdb/channel_cmds.c
* app/pdb/layer_cmds.c: regenerated.
* app/widgets/gimpcellrenderertoggle.[ch]: added "clicked" signal
which carries an additional "GdkModifierType state" parameter as
in GimpCellRendererViewable .
* app/widgets/gimpcontainertreeview.c: emit "clicked" from
the toggle renderer, not "toggled" so the callbacks get the
modifier state.
* app/widgets/gimpdrawabletreeview.c: resurrected the "exclusive
visible by <shift>+click" feature as in 1.2.
* app/widgets/gimplayertreeview.c: compress layer opacity undos by
looking at the top of the undo stack and not pushing an undo if
there already is a GIMP_UNDO_DRAWABLE_OPACITY for the active
layer.
2003-03-18 02:02:41 +08:00
|
|
|
}
|
2003-08-28 01:21:49 +08:00
|
|
|
|
2002-03-04 22:52:54 +08:00
|
|
|
layer->opacity = opacity;
|
2001-03-12 01:24:47 +08:00
|
|
|
|
2003-01-06 06:07:10 +08:00
|
|
|
g_signal_emit (layer, layer_signals[OPACITY_CHANGED], 0);
|
2005-07-12 00:46:28 +08:00
|
|
|
g_object_notify (G_OBJECT (layer), "opacity");
|
2001-07-08 06:49:01 +08:00
|
|
|
|
2008-10-10 04:44:23 +08:00
|
|
|
if (layer->opacity_node)
|
|
|
|
gegl_node_set (layer->opacity_node,
|
2008-10-10 19:30:56 +08:00
|
|
|
"value", layer->opacity,
|
2008-10-10 04:44:23 +08:00
|
|
|
NULL);
|
|
|
|
|
2001-07-08 06:49:01 +08:00
|
|
|
gimp_drawable_update (GIMP_DRAWABLE (layer),
|
2006-04-12 20:49:29 +08:00
|
|
|
0, 0,
|
2008-11-03 08:09:01 +08:00
|
|
|
gimp_item_get_width (GIMP_ITEM (layer)),
|
|
|
|
gimp_item_get_height (GIMP_ITEM (layer)));
|
2001-03-12 01:24:47 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
gdouble
|
2001-12-13 07:48:18 +08:00
|
|
|
gimp_layer_get_opacity (const GimpLayer *layer)
|
2001-03-12 01:24:47 +08:00
|
|
|
{
|
2002-03-04 01:38:12 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_LAYER (layer), GIMP_OPACITY_OPAQUE);
|
2001-03-12 01:24:47 +08:00
|
|
|
|
2002-06-07 03:07:59 +08:00
|
|
|
return layer->opacity;
|
2001-03-12 01:24:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-12-09 07:12:59 +08:00
|
|
|
gimp_layer_set_mode (GimpLayer *layer,
|
Made drawable/layer properties (visibility, opacity etc.) undoable (fixes
2003-03-17 Michael Natterer <mitch@gimp.org>
Made drawable/layer properties (visibility, opacity etc.)
undoable (fixes bug #73893).
* app/core/core-enums.[ch]: added undo types/groups for
visibility, mode, opacity, linked and preserve_trans.
* app/core/Makefile.am
* app/core/core-types.h
* app/core/gimpitemundo.[ch]: new GimpUndo subclass which holds a
ref'ed GimpItem pointer so (1) this doesn't need to be done by all
undo steps related to an item and (2) the item the undo step is
for can be determined from outside the undo system.
* app/core/gimpimage-undo.[ch]: added gimp_image_undo_push_item()
which returns a new GimpItemUndo.
* app/core/gimpimage-undo-push.[ch]: use it for all item related
undo steps. Removed lots of GimpItem, GimpLayer, GimpDrawable
and GimpVectors pointers from the private undo structs. Added
undo push functions for the new undo types added above.
* app/core/gimpdrawable.[ch] (gimp_drawable_set_visible): added
"gboolean push_undo" parameter.
* app/core/gimplayer.[ch] (gimp_layer_set_opacity, _mode,
_preserve_trans, _linked): added "gboolean push_undo" parameters.
* app/core/gimpimage-mask.c
* app/core/gimpimage-merge.c
* app/core/gimplayer-floating-sel.c
* app/tools/gimpmovetool.c
* app/xcf/xcf-load.c
* app/widgets/gimpdrawablelistitem.c
* app/widgets/gimplayerlistitem.c
* app/widgets/gimplayerlistview.c: changed accordingly.
* tools/pdbgen/pdb/channel.pdb
* tools/pdbgen/pdb/layer.pdb: ditto. Added '$undo' paramaters to
the foo_accessors() functions. Removed $func from foo_accesors()
because we don't manipulate items without using getters/setters
any longer.
* app/pdb/channel_cmds.c
* app/pdb/layer_cmds.c: regenerated.
* app/widgets/gimpcellrenderertoggle.[ch]: added "clicked" signal
which carries an additional "GdkModifierType state" parameter as
in GimpCellRendererViewable .
* app/widgets/gimpcontainertreeview.c: emit "clicked" from
the toggle renderer, not "toggled" so the callbacks get the
modifier state.
* app/widgets/gimpdrawabletreeview.c: resurrected the "exclusive
visible by <shift>+click" feature as in 1.2.
* app/widgets/gimplayertreeview.c: compress layer opacity undos by
looking at the top of the undo stack and not pushing an undo if
there already is a GIMP_UNDO_DRAWABLE_OPACITY for the active
layer.
2003-03-18 02:02:41 +08:00
|
|
|
GimpLayerModeEffects mode,
|
|
|
|
gboolean push_undo)
|
2001-03-12 01:24:47 +08:00
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_LAYER (layer));
|
|
|
|
|
|
|
|
if (layer->mode != mode)
|
|
|
|
{
|
2004-11-16 21:41:55 +08:00
|
|
|
if (push_undo && gimp_item_is_attached (GIMP_ITEM (layer)))
|
Made drawable/layer properties (visibility, opacity etc.) undoable (fixes
2003-03-17 Michael Natterer <mitch@gimp.org>
Made drawable/layer properties (visibility, opacity etc.)
undoable (fixes bug #73893).
* app/core/core-enums.[ch]: added undo types/groups for
visibility, mode, opacity, linked and preserve_trans.
* app/core/Makefile.am
* app/core/core-types.h
* app/core/gimpitemundo.[ch]: new GimpUndo subclass which holds a
ref'ed GimpItem pointer so (1) this doesn't need to be done by all
undo steps related to an item and (2) the item the undo step is
for can be determined from outside the undo system.
* app/core/gimpimage-undo.[ch]: added gimp_image_undo_push_item()
which returns a new GimpItemUndo.
* app/core/gimpimage-undo-push.[ch]: use it for all item related
undo steps. Removed lots of GimpItem, GimpLayer, GimpDrawable
and GimpVectors pointers from the private undo structs. Added
undo push functions for the new undo types added above.
* app/core/gimpdrawable.[ch] (gimp_drawable_set_visible): added
"gboolean push_undo" parameter.
* app/core/gimplayer.[ch] (gimp_layer_set_opacity, _mode,
_preserve_trans, _linked): added "gboolean push_undo" parameters.
* app/core/gimpimage-mask.c
* app/core/gimpimage-merge.c
* app/core/gimplayer-floating-sel.c
* app/tools/gimpmovetool.c
* app/xcf/xcf-load.c
* app/widgets/gimpdrawablelistitem.c
* app/widgets/gimplayerlistitem.c
* app/widgets/gimplayerlistview.c: changed accordingly.
* tools/pdbgen/pdb/channel.pdb
* tools/pdbgen/pdb/layer.pdb: ditto. Added '$undo' paramaters to
the foo_accessors() functions. Removed $func from foo_accesors()
because we don't manipulate items without using getters/setters
any longer.
* app/pdb/channel_cmds.c
* app/pdb/layer_cmds.c: regenerated.
* app/widgets/gimpcellrenderertoggle.[ch]: added "clicked" signal
which carries an additional "GdkModifierType state" parameter as
in GimpCellRendererViewable .
* app/widgets/gimpcontainertreeview.c: emit "clicked" from
the toggle renderer, not "toggled" so the callbacks get the
modifier state.
* app/widgets/gimpdrawabletreeview.c: resurrected the "exclusive
visible by <shift>+click" feature as in 1.2.
* app/widgets/gimplayertreeview.c: compress layer opacity undos by
looking at the top of the undo stack and not pushing an undo if
there already is a GIMP_UNDO_DRAWABLE_OPACITY for the active
layer.
2003-03-18 02:02:41 +08:00
|
|
|
{
|
2006-03-29 01:08:36 +08:00
|
|
|
GimpImage *image = gimp_item_get_image (GIMP_ITEM (layer));
|
Made drawable/layer properties (visibility, opacity etc.) undoable (fixes
2003-03-17 Michael Natterer <mitch@gimp.org>
Made drawable/layer properties (visibility, opacity etc.)
undoable (fixes bug #73893).
* app/core/core-enums.[ch]: added undo types/groups for
visibility, mode, opacity, linked and preserve_trans.
* app/core/Makefile.am
* app/core/core-types.h
* app/core/gimpitemundo.[ch]: new GimpUndo subclass which holds a
ref'ed GimpItem pointer so (1) this doesn't need to be done by all
undo steps related to an item and (2) the item the undo step is
for can be determined from outside the undo system.
* app/core/gimpimage-undo.[ch]: added gimp_image_undo_push_item()
which returns a new GimpItemUndo.
* app/core/gimpimage-undo-push.[ch]: use it for all item related
undo steps. Removed lots of GimpItem, GimpLayer, GimpDrawable
and GimpVectors pointers from the private undo structs. Added
undo push functions for the new undo types added above.
* app/core/gimpdrawable.[ch] (gimp_drawable_set_visible): added
"gboolean push_undo" parameter.
* app/core/gimplayer.[ch] (gimp_layer_set_opacity, _mode,
_preserve_trans, _linked): added "gboolean push_undo" parameters.
* app/core/gimpimage-mask.c
* app/core/gimpimage-merge.c
* app/core/gimplayer-floating-sel.c
* app/tools/gimpmovetool.c
* app/xcf/xcf-load.c
* app/widgets/gimpdrawablelistitem.c
* app/widgets/gimplayerlistitem.c
* app/widgets/gimplayerlistview.c: changed accordingly.
* tools/pdbgen/pdb/channel.pdb
* tools/pdbgen/pdb/layer.pdb: ditto. Added '$undo' paramaters to
the foo_accessors() functions. Removed $func from foo_accesors()
because we don't manipulate items without using getters/setters
any longer.
* app/pdb/channel_cmds.c
* app/pdb/layer_cmds.c: regenerated.
* app/widgets/gimpcellrenderertoggle.[ch]: added "clicked" signal
which carries an additional "GdkModifierType state" parameter as
in GimpCellRendererViewable .
* app/widgets/gimpcontainertreeview.c: emit "clicked" from
the toggle renderer, not "toggled" so the callbacks get the
modifier state.
* app/widgets/gimpdrawabletreeview.c: resurrected the "exclusive
visible by <shift>+click" feature as in 1.2.
* app/widgets/gimplayertreeview.c: compress layer opacity undos by
looking at the top of the undo stack and not pushing an undo if
there already is a GIMP_UNDO_DRAWABLE_OPACITY for the active
layer.
2003-03-18 02:02:41 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
gimp_image_undo_push_layer_mode (image, NULL, layer);
|
Made drawable/layer properties (visibility, opacity etc.) undoable (fixes
2003-03-17 Michael Natterer <mitch@gimp.org>
Made drawable/layer properties (visibility, opacity etc.)
undoable (fixes bug #73893).
* app/core/core-enums.[ch]: added undo types/groups for
visibility, mode, opacity, linked and preserve_trans.
* app/core/Makefile.am
* app/core/core-types.h
* app/core/gimpitemundo.[ch]: new GimpUndo subclass which holds a
ref'ed GimpItem pointer so (1) this doesn't need to be done by all
undo steps related to an item and (2) the item the undo step is
for can be determined from outside the undo system.
* app/core/gimpimage-undo.[ch]: added gimp_image_undo_push_item()
which returns a new GimpItemUndo.
* app/core/gimpimage-undo-push.[ch]: use it for all item related
undo steps. Removed lots of GimpItem, GimpLayer, GimpDrawable
and GimpVectors pointers from the private undo structs. Added
undo push functions for the new undo types added above.
* app/core/gimpdrawable.[ch] (gimp_drawable_set_visible): added
"gboolean push_undo" parameter.
* app/core/gimplayer.[ch] (gimp_layer_set_opacity, _mode,
_preserve_trans, _linked): added "gboolean push_undo" parameters.
* app/core/gimpimage-mask.c
* app/core/gimpimage-merge.c
* app/core/gimplayer-floating-sel.c
* app/tools/gimpmovetool.c
* app/xcf/xcf-load.c
* app/widgets/gimpdrawablelistitem.c
* app/widgets/gimplayerlistitem.c
* app/widgets/gimplayerlistview.c: changed accordingly.
* tools/pdbgen/pdb/channel.pdb
* tools/pdbgen/pdb/layer.pdb: ditto. Added '$undo' paramaters to
the foo_accessors() functions. Removed $func from foo_accesors()
because we don't manipulate items without using getters/setters
any longer.
* app/pdb/channel_cmds.c
* app/pdb/layer_cmds.c: regenerated.
* app/widgets/gimpcellrenderertoggle.[ch]: added "clicked" signal
which carries an additional "GdkModifierType state" parameter as
in GimpCellRendererViewable .
* app/widgets/gimpcontainertreeview.c: emit "clicked" from
the toggle renderer, not "toggled" so the callbacks get the
modifier state.
* app/widgets/gimpdrawabletreeview.c: resurrected the "exclusive
visible by <shift>+click" feature as in 1.2.
* app/widgets/gimplayertreeview.c: compress layer opacity undos by
looking at the top of the undo stack and not pushing an undo if
there already is a GIMP_UNDO_DRAWABLE_OPACITY for the active
layer.
2003-03-18 02:02:41 +08:00
|
|
|
}
|
2003-08-28 01:21:49 +08:00
|
|
|
|
2001-03-12 01:24:47 +08:00
|
|
|
layer->mode = mode;
|
|
|
|
|
2003-01-06 06:07:10 +08:00
|
|
|
g_signal_emit (layer, layer_signals[MODE_CHANGED], 0);
|
2005-07-12 00:46:28 +08:00
|
|
|
g_object_notify (G_OBJECT (layer), "mode");
|
2001-07-08 06:49:01 +08:00
|
|
|
|
2009-11-29 20:35:27 +08:00
|
|
|
gimp_layer_sync_mode_node (layer);
|
2008-10-10 04:44:23 +08:00
|
|
|
|
2001-07-08 06:49:01 +08:00
|
|
|
gimp_drawable_update (GIMP_DRAWABLE (layer),
|
2006-04-12 20:49:29 +08:00
|
|
|
0, 0,
|
2008-11-03 08:09:01 +08:00
|
|
|
gimp_item_get_width (GIMP_ITEM (layer)),
|
|
|
|
gimp_item_get_height (GIMP_ITEM (layer)));
|
2001-03-12 01:24:47 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-12-09 07:12:59 +08:00
|
|
|
GimpLayerModeEffects
|
2001-12-13 07:48:18 +08:00
|
|
|
gimp_layer_get_mode (const GimpLayer *layer)
|
2001-03-12 01:24:47 +08:00
|
|
|
{
|
2001-12-09 07:12:59 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_LAYER (layer), GIMP_NORMAL_MODE);
|
2001-03-12 01:24:47 +08:00
|
|
|
|
|
|
|
return layer->mode;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-07-11 05:17:22 +08:00
|
|
|
gimp_layer_set_lock_alpha (GimpLayer *layer,
|
|
|
|
gboolean lock_alpha,
|
|
|
|
gboolean push_undo)
|
2001-03-12 01:24:47 +08:00
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_LAYER (layer));
|
2009-08-24 01:54:19 +08:00
|
|
|
g_return_if_fail (gimp_layer_can_lock_alpha (layer));
|
2001-03-12 01:24:47 +08:00
|
|
|
|
2005-07-11 05:17:22 +08:00
|
|
|
lock_alpha = lock_alpha ? TRUE : FALSE;
|
|
|
|
|
|
|
|
if (layer->lock_alpha != lock_alpha)
|
2001-03-12 01:24:47 +08:00
|
|
|
{
|
2004-11-16 21:41:55 +08:00
|
|
|
if (push_undo && gimp_item_is_attached (GIMP_ITEM (layer)))
|
Made drawable/layer properties (visibility, opacity etc.) undoable (fixes
2003-03-17 Michael Natterer <mitch@gimp.org>
Made drawable/layer properties (visibility, opacity etc.)
undoable (fixes bug #73893).
* app/core/core-enums.[ch]: added undo types/groups for
visibility, mode, opacity, linked and preserve_trans.
* app/core/Makefile.am
* app/core/core-types.h
* app/core/gimpitemundo.[ch]: new GimpUndo subclass which holds a
ref'ed GimpItem pointer so (1) this doesn't need to be done by all
undo steps related to an item and (2) the item the undo step is
for can be determined from outside the undo system.
* app/core/gimpimage-undo.[ch]: added gimp_image_undo_push_item()
which returns a new GimpItemUndo.
* app/core/gimpimage-undo-push.[ch]: use it for all item related
undo steps. Removed lots of GimpItem, GimpLayer, GimpDrawable
and GimpVectors pointers from the private undo structs. Added
undo push functions for the new undo types added above.
* app/core/gimpdrawable.[ch] (gimp_drawable_set_visible): added
"gboolean push_undo" parameter.
* app/core/gimplayer.[ch] (gimp_layer_set_opacity, _mode,
_preserve_trans, _linked): added "gboolean push_undo" parameters.
* app/core/gimpimage-mask.c
* app/core/gimpimage-merge.c
* app/core/gimplayer-floating-sel.c
* app/tools/gimpmovetool.c
* app/xcf/xcf-load.c
* app/widgets/gimpdrawablelistitem.c
* app/widgets/gimplayerlistitem.c
* app/widgets/gimplayerlistview.c: changed accordingly.
* tools/pdbgen/pdb/channel.pdb
* tools/pdbgen/pdb/layer.pdb: ditto. Added '$undo' paramaters to
the foo_accessors() functions. Removed $func from foo_accesors()
because we don't manipulate items without using getters/setters
any longer.
* app/pdb/channel_cmds.c
* app/pdb/layer_cmds.c: regenerated.
* app/widgets/gimpcellrenderertoggle.[ch]: added "clicked" signal
which carries an additional "GdkModifierType state" parameter as
in GimpCellRendererViewable .
* app/widgets/gimpcontainertreeview.c: emit "clicked" from
the toggle renderer, not "toggled" so the callbacks get the
modifier state.
* app/widgets/gimpdrawabletreeview.c: resurrected the "exclusive
visible by <shift>+click" feature as in 1.2.
* app/widgets/gimplayertreeview.c: compress layer opacity undos by
looking at the top of the undo stack and not pushing an undo if
there already is a GIMP_UNDO_DRAWABLE_OPACITY for the active
layer.
2003-03-18 02:02:41 +08:00
|
|
|
{
|
2006-03-29 01:08:36 +08:00
|
|
|
GimpImage *image = gimp_item_get_image (GIMP_ITEM (layer));
|
Made drawable/layer properties (visibility, opacity etc.) undoable (fixes
2003-03-17 Michael Natterer <mitch@gimp.org>
Made drawable/layer properties (visibility, opacity etc.)
undoable (fixes bug #73893).
* app/core/core-enums.[ch]: added undo types/groups for
visibility, mode, opacity, linked and preserve_trans.
* app/core/Makefile.am
* app/core/core-types.h
* app/core/gimpitemundo.[ch]: new GimpUndo subclass which holds a
ref'ed GimpItem pointer so (1) this doesn't need to be done by all
undo steps related to an item and (2) the item the undo step is
for can be determined from outside the undo system.
* app/core/gimpimage-undo.[ch]: added gimp_image_undo_push_item()
which returns a new GimpItemUndo.
* app/core/gimpimage-undo-push.[ch]: use it for all item related
undo steps. Removed lots of GimpItem, GimpLayer, GimpDrawable
and GimpVectors pointers from the private undo structs. Added
undo push functions for the new undo types added above.
* app/core/gimpdrawable.[ch] (gimp_drawable_set_visible): added
"gboolean push_undo" parameter.
* app/core/gimplayer.[ch] (gimp_layer_set_opacity, _mode,
_preserve_trans, _linked): added "gboolean push_undo" parameters.
* app/core/gimpimage-mask.c
* app/core/gimpimage-merge.c
* app/core/gimplayer-floating-sel.c
* app/tools/gimpmovetool.c
* app/xcf/xcf-load.c
* app/widgets/gimpdrawablelistitem.c
* app/widgets/gimplayerlistitem.c
* app/widgets/gimplayerlistview.c: changed accordingly.
* tools/pdbgen/pdb/channel.pdb
* tools/pdbgen/pdb/layer.pdb: ditto. Added '$undo' paramaters to
the foo_accessors() functions. Removed $func from foo_accesors()
because we don't manipulate items without using getters/setters
any longer.
* app/pdb/channel_cmds.c
* app/pdb/layer_cmds.c: regenerated.
* app/widgets/gimpcellrenderertoggle.[ch]: added "clicked" signal
which carries an additional "GdkModifierType state" parameter as
in GimpCellRendererViewable .
* app/widgets/gimpcontainertreeview.c: emit "clicked" from
the toggle renderer, not "toggled" so the callbacks get the
modifier state.
* app/widgets/gimpdrawabletreeview.c: resurrected the "exclusive
visible by <shift>+click" feature as in 1.2.
* app/widgets/gimplayertreeview.c: compress layer opacity undos by
looking at the top of the undo stack and not pushing an undo if
there already is a GIMP_UNDO_DRAWABLE_OPACITY for the active
layer.
2003-03-18 02:02:41 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
gimp_image_undo_push_layer_lock_alpha (image, NULL, layer);
|
Made drawable/layer properties (visibility, opacity etc.) undoable (fixes
2003-03-17 Michael Natterer <mitch@gimp.org>
Made drawable/layer properties (visibility, opacity etc.)
undoable (fixes bug #73893).
* app/core/core-enums.[ch]: added undo types/groups for
visibility, mode, opacity, linked and preserve_trans.
* app/core/Makefile.am
* app/core/core-types.h
* app/core/gimpitemundo.[ch]: new GimpUndo subclass which holds a
ref'ed GimpItem pointer so (1) this doesn't need to be done by all
undo steps related to an item and (2) the item the undo step is
for can be determined from outside the undo system.
* app/core/gimpimage-undo.[ch]: added gimp_image_undo_push_item()
which returns a new GimpItemUndo.
* app/core/gimpimage-undo-push.[ch]: use it for all item related
undo steps. Removed lots of GimpItem, GimpLayer, GimpDrawable
and GimpVectors pointers from the private undo structs. Added
undo push functions for the new undo types added above.
* app/core/gimpdrawable.[ch] (gimp_drawable_set_visible): added
"gboolean push_undo" parameter.
* app/core/gimplayer.[ch] (gimp_layer_set_opacity, _mode,
_preserve_trans, _linked): added "gboolean push_undo" parameters.
* app/core/gimpimage-mask.c
* app/core/gimpimage-merge.c
* app/core/gimplayer-floating-sel.c
* app/tools/gimpmovetool.c
* app/xcf/xcf-load.c
* app/widgets/gimpdrawablelistitem.c
* app/widgets/gimplayerlistitem.c
* app/widgets/gimplayerlistview.c: changed accordingly.
* tools/pdbgen/pdb/channel.pdb
* tools/pdbgen/pdb/layer.pdb: ditto. Added '$undo' paramaters to
the foo_accessors() functions. Removed $func from foo_accesors()
because we don't manipulate items without using getters/setters
any longer.
* app/pdb/channel_cmds.c
* app/pdb/layer_cmds.c: regenerated.
* app/widgets/gimpcellrenderertoggle.[ch]: added "clicked" signal
which carries an additional "GdkModifierType state" parameter as
in GimpCellRendererViewable .
* app/widgets/gimpcontainertreeview.c: emit "clicked" from
the toggle renderer, not "toggled" so the callbacks get the
modifier state.
* app/widgets/gimpdrawabletreeview.c: resurrected the "exclusive
visible by <shift>+click" feature as in 1.2.
* app/widgets/gimplayertreeview.c: compress layer opacity undos by
looking at the top of the undo stack and not pushing an undo if
there already is a GIMP_UNDO_DRAWABLE_OPACITY for the active
layer.
2003-03-18 02:02:41 +08:00
|
|
|
}
|
2003-08-28 01:21:49 +08:00
|
|
|
|
2005-07-11 05:17:22 +08:00
|
|
|
layer->lock_alpha = lock_alpha;
|
2001-03-12 01:24:47 +08:00
|
|
|
|
2005-07-11 05:17:22 +08:00
|
|
|
g_signal_emit (layer, layer_signals[LOCK_ALPHA_CHANGED], 0);
|
2005-07-12 00:46:28 +08:00
|
|
|
g_object_notify (G_OBJECT (layer), "lock-alpha");
|
2001-03-12 01:24:47 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
2005-07-11 05:17:22 +08:00
|
|
|
gimp_layer_get_lock_alpha (const GimpLayer *layer)
|
2001-03-12 01:24:47 +08:00
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_LAYER (layer), FALSE);
|
|
|
|
|
2005-07-11 05:17:22 +08:00
|
|
|
return layer->lock_alpha;
|
2001-03-12 01:24:47 +08:00
|
|
|
}
|
2009-08-24 00:44:05 +08:00
|
|
|
|
|
|
|
gboolean
|
|
|
|
gimp_layer_can_lock_alpha (const GimpLayer *layer)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_LAYER (layer), FALSE);
|
|
|
|
|
|
|
|
if (gimp_viewable_get_children (GIMP_VIEWABLE (layer)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|