2006-12-10 05:33:38 +08:00
|
|
|
/* GIMP - The GNU Image Manipulation Program
|
1998-06-30 23:31:32 +08:00
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
2000-12-17 05:37:03 +08:00
|
|
|
|
2000-05-27 06:28:40 +08:00
|
|
|
#include "config.h"
|
|
|
|
|
2001-08-14 22:53:55 +08:00
|
|
|
#include <glib-object.h>
|
2000-12-17 05:37:03 +08:00
|
|
|
|
2006-08-29 22:46:32 +08:00
|
|
|
#include "libgimpbase/gimpbase.h"
|
2001-01-24 07:56:18 +08:00
|
|
|
#include "libgimpcolor/gimpcolor.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/pixel-region.h"
|
2004-01-06 22:02:08 +08:00
|
|
|
#include "base/temp-buf.h"
|
2001-05-15 19:25:25 +08:00
|
|
|
#include "base/tile.h"
|
|
|
|
#include "base/tile-manager.h"
|
|
|
|
|
2001-04-07 23:58:26 +08:00
|
|
|
#include "paint-funcs/paint-funcs.h"
|
2007-08-08 16:35:45 +08:00
|
|
|
#include "paint-funcs/scale-region.h"
|
2001-04-07 23:58:26 +08:00
|
|
|
|
2001-02-02 02:44:22 +08:00
|
|
|
#include "gimpchannel.h"
|
2001-07-08 06:49:01 +08:00
|
|
|
#include "gimpcontext.h"
|
2003-10-06 22:40:12 +08:00
|
|
|
#include "gimpdrawable-combine.h"
|
2001-02-07 08:06:58 +08:00
|
|
|
#include "gimpdrawable-preview.h"
|
2003-05-13 21:57:11 +08:00
|
|
|
#include "gimpdrawable-transform.h"
|
2000-12-30 08:16:50 +08:00
|
|
|
#include "gimpimage.h"
|
2006-04-07 17:21:18 +08:00
|
|
|
#include "gimpimage-colormap.h"
|
2003-02-14 22:14:29 +08:00
|
|
|
#include "gimpimage-undo-push.h"
|
2004-04-13 21:54:54 +08:00
|
|
|
#include "gimplayer.h"
|
|
|
|
#include "gimplayer-floating-sel.h"
|
2001-11-23 07:46:13 +08:00
|
|
|
#include "gimpmarshal.h"
|
2004-01-06 22:02:08 +08:00
|
|
|
#include "gimppattern.h"
|
2004-07-14 07:04:05 +08:00
|
|
|
#include "gimppickable.h"
|
2001-02-02 02:44:22 +08:00
|
|
|
#include "gimppreviewcache.h"
|
2004-08-11 02:47:21 +08:00
|
|
|
#include "gimpprogress.h"
|
2001-05-25 01:09:57 +08:00
|
|
|
|
2003-03-26 00:38:19 +08:00
|
|
|
#include "gimp-intl.h"
|
1998-06-30 23:31:32 +08:00
|
|
|
|
2000-05-27 06:28:40 +08:00
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
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
|
|
|
UPDATE,
|
2003-05-21 19:34:00 +08:00
|
|
|
ALPHA_CHANGED,
|
1998-06-30 23:31:32 +08:00
|
|
|
LAST_SIGNAL
|
|
|
|
};
|
|
|
|
|
2001-01-20 21:21:49 +08:00
|
|
|
|
2001-07-11 20:39:49 +08:00
|
|
|
/* local function prototypes */
|
|
|
|
|
2005-12-11 03:24:36 +08:00
|
|
|
static void gimp_drawable_pickable_iface_init (GimpPickableInterface *iface);
|
2001-08-11 22:39:19 +08:00
|
|
|
|
2003-02-11 21:52:47 +08:00
|
|
|
static void gimp_drawable_finalize (GObject *object);
|
2001-08-11 22:39:19 +08:00
|
|
|
|
2003-11-17 01:51:36 +08:00
|
|
|
static gint64 gimp_drawable_get_memsize (GimpObject *object,
|
|
|
|
gint64 *gui_size);
|
2002-01-31 00:14:26 +08:00
|
|
|
|
2005-05-25 18:05:17 +08:00
|
|
|
static gboolean gimp_drawable_get_size (GimpViewable *viewable,
|
|
|
|
gint *width,
|
|
|
|
gint *height);
|
2003-02-11 21:52:47 +08:00
|
|
|
static void gimp_drawable_invalidate_preview (GimpViewable *viewable);
|
|
|
|
|
|
|
|
static GimpItem * gimp_drawable_duplicate (GimpItem *item,
|
2008-01-08 19:46:15 +08:00
|
|
|
GType new_type);
|
2004-04-13 21:54:54 +08:00
|
|
|
static void gimp_drawable_translate (GimpItem *item,
|
|
|
|
gint offset_x,
|
|
|
|
gint offset_y,
|
|
|
|
gboolean push_undo);
|
2003-05-07 19:09:00 +08:00
|
|
|
static void gimp_drawable_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,
|
2007-12-04 19:30:31 +08:00
|
|
|
GimpProgress *progress);
|
2003-05-07 21:01:17 +08:00
|
|
|
static void gimp_drawable_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-13 21:57:11 +08:00
|
|
|
static void gimp_drawable_flip (GimpItem *item,
|
2004-04-15 07:37:34 +08:00
|
|
|
GimpContext *context,
|
2003-05-13 21:57:11 +08:00
|
|
|
GimpOrientationType flip_type,
|
|
|
|
gdouble axis,
|
|
|
|
gboolean clip_result);
|
2003-05-20 18:36:29 +08:00
|
|
|
static void gimp_drawable_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-13 21:57:11 +08:00
|
|
|
static void gimp_drawable_transform (GimpItem *item,
|
2004-04-15 07:37:34 +08:00
|
|
|
GimpContext *context,
|
2003-07-07 21:50:48 +08:00
|
|
|
const GimpMatrix3 *matrix,
|
2007-12-04 19:30:31 +08:00
|
|
|
GimpTransformDirection direction,
|
|
|
|
GimpInterpolationType interpolation_type,
|
2004-03-14 01:45:58 +08:00
|
|
|
gint recursion_level,
|
2007-12-04 19:30:31 +08:00
|
|
|
GimpTransformResize clip_result,
|
2004-08-11 02:47:21 +08:00
|
|
|
GimpProgress *progress);
|
1998-06-30 23:31:32 +08:00
|
|
|
|
2007-04-28 00:07:49 +08:00
|
|
|
static gboolean gimp_drawable_get_pixel_at (GimpPickable *pickable,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
guchar *pixel);
|
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_drawable_real_update (GimpDrawable *drawable,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint width,
|
|
|
|
gint height);
|
|
|
|
|
2007-12-04 19:30:31 +08:00
|
|
|
static gint64 gimp_drawable_real_estimate_memsize (const GimpDrawable *drawable,
|
|
|
|
gint width,
|
|
|
|
gint height);
|
|
|
|
|
2007-12-18 19:20:23 +08:00
|
|
|
static TileManager * gimp_drawable_real_get_tiles (GimpDrawable *drawable);
|
2004-03-13 21:56:09 +08:00
|
|
|
static void gimp_drawable_real_set_tiles (GimpDrawable *drawable,
|
|
|
|
gboolean push_undo,
|
|
|
|
const gchar *undo_desc,
|
|
|
|
TileManager *tiles,
|
2004-03-16 03:34:35 +08:00
|
|
|
GimpImageType type,
|
|
|
|
gint offset_x,
|
|
|
|
gint offset_y);
|
2004-03-13 21:56:09 +08:00
|
|
|
|
2004-04-01 22:51:58 +08:00
|
|
|
static void gimp_drawable_real_push_undo (GimpDrawable *drawable,
|
|
|
|
const gchar *undo_desc,
|
|
|
|
TileManager *tiles,
|
|
|
|
gboolean sparse,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint width,
|
|
|
|
gint height);
|
2004-03-15 22:10:30 +08:00
|
|
|
static void gimp_drawable_real_swap_pixels (GimpDrawable *drawable,
|
|
|
|
TileManager *tiles,
|
|
|
|
gboolean sparse,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint width,
|
|
|
|
gint height);
|
|
|
|
|
2001-01-10 08:36:54 +08:00
|
|
|
|
2005-12-11 03:24:36 +08:00
|
|
|
G_DEFINE_TYPE_WITH_CODE (GimpDrawable, gimp_drawable, GIMP_TYPE_ITEM,
|
|
|
|
G_IMPLEMENT_INTERFACE (GIMP_TYPE_PICKABLE,
|
2006-05-15 17:46:31 +08:00
|
|
|
gimp_drawable_pickable_iface_init))
|
2001-01-20 21:21:49 +08:00
|
|
|
|
2005-12-11 03:24:36 +08:00
|
|
|
#define parent_class gimp_drawable_parent_class
|
2000-12-29 00:19:55 +08:00
|
|
|
|
2005-12-11 03:24:36 +08:00
|
|
|
static guint gimp_drawable_signals[LAST_SIGNAL] = { 0 };
|
2000-12-29 00:19:55 +08:00
|
|
|
|
1998-06-30 23:31:32 +08:00
|
|
|
|
|
|
|
static void
|
2000-12-29 00:19:55 +08:00
|
|
|
gimp_drawable_class_init (GimpDrawableClass *klass)
|
1998-06-30 23:31:32 +08:00
|
|
|
{
|
2004-07-14 18:31:59 +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);
|
2001-01-10 08:36:54 +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
|
|
|
gimp_drawable_signals[UPDATE] =
|
|
|
|
g_signal_new ("update",
|
2004-07-14 18:31:59 +08:00
|
|
|
G_TYPE_FROM_CLASS (klass),
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
G_STRUCT_OFFSET (GimpDrawableClass, update),
|
|
|
|
NULL, NULL,
|
|
|
|
gimp_marshal_VOID__INT_INT_INT_INT,
|
|
|
|
G_TYPE_NONE, 4,
|
|
|
|
G_TYPE_INT,
|
|
|
|
G_TYPE_INT,
|
|
|
|
G_TYPE_INT,
|
|
|
|
G_TYPE_INT);
|
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
|
|
|
|
2003-05-21 19:34:00 +08:00
|
|
|
gimp_drawable_signals[ALPHA_CHANGED] =
|
2005-05-28 00:51:39 +08:00
|
|
|
g_signal_new ("alpha-changed",
|
2004-07-14 18:31:59 +08:00
|
|
|
G_TYPE_FROM_CLASS (klass),
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
G_STRUCT_OFFSET (GimpDrawableClass, alpha_changed),
|
|
|
|
NULL, NULL,
|
|
|
|
gimp_marshal_VOID__VOID,
|
|
|
|
G_TYPE_NONE, 0);
|
2003-05-21 19:34:00 +08:00
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
object_class->finalize = gimp_drawable_finalize;
|
2000-12-29 00:19:55 +08:00
|
|
|
|
2002-01-31 00:14:26 +08:00
|
|
|
gimp_object_class->get_memsize = gimp_drawable_get_memsize;
|
2001-01-10 11:13:03 +08:00
|
|
|
|
2005-05-25 18:05:17 +08:00
|
|
|
viewable_class->get_size = gimp_drawable_get_size;
|
2001-02-05 06:10:54 +08:00
|
|
|
viewable_class->invalidate_preview = gimp_drawable_invalidate_preview;
|
2001-02-07 08:06:58 +08:00
|
|
|
viewable_class->get_preview = gimp_drawable_get_preview;
|
2001-02-05 06:10:54 +08:00
|
|
|
|
2003-02-11 21:52:47 +08:00
|
|
|
item_class->duplicate = gimp_drawable_duplicate;
|
2004-04-13 21:54:54 +08:00
|
|
|
item_class->translate = gimp_drawable_translate;
|
2003-05-07 19:09:00 +08:00
|
|
|
item_class->scale = gimp_drawable_scale;
|
2003-05-07 21:01:17 +08:00
|
|
|
item_class->resize = gimp_drawable_resize;
|
2003-05-13 21:57:11 +08:00
|
|
|
item_class->flip = gimp_drawable_flip;
|
2003-05-20 18:36:29 +08:00
|
|
|
item_class->rotate = gimp_drawable_rotate;
|
2003-05-13 21:57:11 +08:00
|
|
|
item_class->transform = gimp_drawable_transform;
|
2003-02-11 21:52:47 +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
|
|
|
klass->update = gimp_drawable_real_update;
|
2003-05-21 19:34:00 +08:00
|
|
|
klass->alpha_changed = NULL;
|
2007-12-04 19:30:31 +08:00
|
|
|
klass->estimate_memsize = gimp_drawable_real_estimate_memsize;
|
2003-09-04 19:33:06 +08:00
|
|
|
klass->invalidate_boundary = NULL;
|
2003-10-06 22:40:12 +08:00
|
|
|
klass->get_active_components = NULL;
|
|
|
|
klass->apply_region = gimp_drawable_real_apply_region;
|
|
|
|
klass->replace_region = gimp_drawable_real_replace_region;
|
2007-12-18 19:20:23 +08:00
|
|
|
klass->get_tiles = gimp_drawable_real_get_tiles;
|
2004-03-13 21:56:09 +08:00
|
|
|
klass->set_tiles = gimp_drawable_real_set_tiles;
|
2004-04-01 22:51:58 +08:00
|
|
|
klass->push_undo = gimp_drawable_real_push_undo;
|
2004-03-15 22:10:30 +08:00
|
|
|
klass->swap_pixels = gimp_drawable_real_swap_pixels;
|
1998-06-30 23:31:32 +08:00
|
|
|
}
|
|
|
|
|
2001-01-20 21:21:49 +08:00
|
|
|
static void
|
|
|
|
gimp_drawable_init (GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
drawable->tiles = NULL;
|
|
|
|
drawable->bytes = 0;
|
|
|
|
drawable->type = -1;
|
|
|
|
drawable->has_alpha = FALSE;
|
|
|
|
drawable->preview_cache = NULL;
|
|
|
|
drawable->preview_valid = FALSE;
|
|
|
|
}
|
|
|
|
|
2006-11-25 06:41:03 +08:00
|
|
|
/* sorry for the evil casts */
|
|
|
|
|
2004-07-14 07:04:05 +08:00
|
|
|
static void
|
2005-12-11 03:24:36 +08:00
|
|
|
gimp_drawable_pickable_iface_init (GimpPickableInterface *iface)
|
2004-07-14 07:04:05 +08:00
|
|
|
{
|
2006-11-25 06:41:03 +08:00
|
|
|
iface->get_image = (GimpImage * (*) (GimpPickable *pickable)) gimp_item_get_image;
|
|
|
|
iface->get_image_type = (GimpImageType (*) (GimpPickable *pickable)) gimp_drawable_type;
|
|
|
|
iface->get_bytes = (gint (*) (GimpPickable *pickable)) gimp_drawable_bytes;
|
|
|
|
iface->get_tiles = (TileManager * (*) (GimpPickable *pickable)) gimp_drawable_get_tiles;
|
2007-04-28 00:07:49 +08:00
|
|
|
iface->get_pixel_at = gimp_drawable_get_pixel_at;
|
2004-07-14 07:04:05 +08:00
|
|
|
}
|
|
|
|
|
2001-01-20 21:21:49 +08:00
|
|
|
static void
|
2001-08-11 22:39:19 +08:00
|
|
|
gimp_drawable_finalize (GObject *object)
|
2001-01-20 21:21:49 +08:00
|
|
|
{
|
2003-09-02 21:43:26 +08:00
|
|
|
GimpDrawable *drawable = GIMP_DRAWABLE (object);
|
2001-01-20 21:21:49 +08:00
|
|
|
|
|
|
|
if (drawable->tiles)
|
Port to glib/gtk+ 2.0 episode I (every segfault has it's beginning)
2001-07-24 Michael Natterer <mitch@gimp.org>
Port to glib/gtk+ 2.0 episode I (every segfault has it's beginning)
* configure.in: require glib/gtk+ >= 1.3.7, commented out the
gtkxmhtml stuff.
From now on, you will need glib, pango, atk and gtk+ HEAD from CVS
to hack or use GIMP HEAD.
Beware, it crashes randomly :)
* app/core/Makefile.am
* app/core/gimpmarshal.list: new file plus rules to generate
gimpmarshal.[ch] from it.
* app/core/*
* app/tools/*
* app/widgets/*
* libgimpwidgets/*: started to use the glib object system. All
core/ objects are still gtk objects however. All signals are
created using g_signal_new(). There are many gtk+ artefacts left.
Finally, we will _not_ use the gtk_signal_foo() wrappers and
friends any more.
* app/colormaps.c
* app/devices.[ch]
* app/disp_callbacks.c
* app/errorconsole.c
* app/file-save.[ch]
* app/interface.c
* app/module_db.c
* app/nav_window.c
* app/ops_buttons.c
* app/scroll.c
* app/user_install.c
* app/gui/about-dialog.c
* app/gui/brush-editor.c
* app/gui/brushes-commands.c
* app/gui/color-notebook.c
* app/gui/colormap-dialog.c
* app/gui/dialogs-commands.c
* app/gui/dialogs-constructors.c
* app/gui/file-commands.c
* app/gui/file-dialog-utils.c
* app/gui/file-new-dialog.c
* app/gui/file-open-dialog.[ch]
* app/gui/file-save-dialog.c
* app/gui/gradient-editor.c
* app/gui/gradients-commands.c
* app/gui/image-commands.c
* app/gui/info-dialog.[ch]
* app/gui/layer-select.c
* app/gui/layers-commands.c
* app/gui/menus.c
* app/gui/offset-dialog.c
* app/gui/palette-editor.c
* app/gui/palettes-commands.c
* app/gui/patterns-commands.c
* app/gui/preferences-dialog.c
* app/gui/resize-dialog.[ch]
* app/gui/splash.c
* app/gui/tips-dialog.c
* app/gui/tool-options-dialog.c
* app/gui/toolbox.c
* app/gui/tools-commands.c
* libgimp/gimpbrushmenu.c
* libgimp/gimpmenu.c
* libgimp/gimppatternmenu.c
* libgimp/gimpui.c
* libgimpbase/gimpenv.c: tons and tons of changes like "const
gchar*", switch from GdkDeviceInfo to GdkDevice (very incomplete
and currently disables), lots of s/gtk_signal/g_signal/,
removal/replacement of deprecated stuff,
s/GtkSignalFunc/GCallback/ and lots of small changes and fixes
while I was on it, zillions of warnings left...
* modules/Makefile.am: disabled the water color selector
temporarily (XInput issues).
* plug-ins/Makefile.am
* plug-ins/common/.cvsignore
* plug-ins/common/Makefile.am
* plug-ins/common/plugin-defs.pl: simply excluded all plug-ins
which did not build (including Script-Fu). They are trivial to
fix.
2001-07-25 05:27:11 +08:00
|
|
|
{
|
2003-05-27 01:02:06 +08:00
|
|
|
tile_manager_unref (drawable->tiles);
|
Port to glib/gtk+ 2.0 episode I (every segfault has it's beginning)
2001-07-24 Michael Natterer <mitch@gimp.org>
Port to glib/gtk+ 2.0 episode I (every segfault has it's beginning)
* configure.in: require glib/gtk+ >= 1.3.7, commented out the
gtkxmhtml stuff.
From now on, you will need glib, pango, atk and gtk+ HEAD from CVS
to hack or use GIMP HEAD.
Beware, it crashes randomly :)
* app/core/Makefile.am
* app/core/gimpmarshal.list: new file plus rules to generate
gimpmarshal.[ch] from it.
* app/core/*
* app/tools/*
* app/widgets/*
* libgimpwidgets/*: started to use the glib object system. All
core/ objects are still gtk objects however. All signals are
created using g_signal_new(). There are many gtk+ artefacts left.
Finally, we will _not_ use the gtk_signal_foo() wrappers and
friends any more.
* app/colormaps.c
* app/devices.[ch]
* app/disp_callbacks.c
* app/errorconsole.c
* app/file-save.[ch]
* app/interface.c
* app/module_db.c
* app/nav_window.c
* app/ops_buttons.c
* app/scroll.c
* app/user_install.c
* app/gui/about-dialog.c
* app/gui/brush-editor.c
* app/gui/brushes-commands.c
* app/gui/color-notebook.c
* app/gui/colormap-dialog.c
* app/gui/dialogs-commands.c
* app/gui/dialogs-constructors.c
* app/gui/file-commands.c
* app/gui/file-dialog-utils.c
* app/gui/file-new-dialog.c
* app/gui/file-open-dialog.[ch]
* app/gui/file-save-dialog.c
* app/gui/gradient-editor.c
* app/gui/gradients-commands.c
* app/gui/image-commands.c
* app/gui/info-dialog.[ch]
* app/gui/layer-select.c
* app/gui/layers-commands.c
* app/gui/menus.c
* app/gui/offset-dialog.c
* app/gui/palette-editor.c
* app/gui/palettes-commands.c
* app/gui/patterns-commands.c
* app/gui/preferences-dialog.c
* app/gui/resize-dialog.[ch]
* app/gui/splash.c
* app/gui/tips-dialog.c
* app/gui/tool-options-dialog.c
* app/gui/toolbox.c
* app/gui/tools-commands.c
* libgimp/gimpbrushmenu.c
* libgimp/gimpmenu.c
* libgimp/gimppatternmenu.c
* libgimp/gimpui.c
* libgimpbase/gimpenv.c: tons and tons of changes like "const
gchar*", switch from GdkDeviceInfo to GdkDevice (very incomplete
and currently disables), lots of s/gtk_signal/g_signal/,
removal/replacement of deprecated stuff,
s/GtkSignalFunc/GCallback/ and lots of small changes and fixes
while I was on it, zillions of warnings left...
* modules/Makefile.am: disabled the water color selector
temporarily (XInput issues).
* plug-ins/Makefile.am
* plug-ins/common/.cvsignore
* plug-ins/common/Makefile.am
* plug-ins/common/plugin-defs.pl: simply excluded all plug-ins
which did not build (including Script-Fu). They are trivial to
fix.
2001-07-25 05:27:11 +08:00
|
|
|
drawable->tiles = NULL;
|
|
|
|
}
|
2001-01-20 21:21:49 +08:00
|
|
|
|
|
|
|
if (drawable->preview_cache)
|
|
|
|
gimp_preview_cache_invalidate (&drawable->preview_cache);
|
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
2001-01-20 21:21:49 +08:00
|
|
|
}
|
|
|
|
|
2003-11-17 01:51:36 +08:00
|
|
|
static gint64
|
2003-08-25 18:49:33 +08:00
|
|
|
gimp_drawable_get_memsize (GimpObject *object,
|
2003-11-17 01:51:36 +08:00
|
|
|
gint64 *gui_size)
|
2002-01-31 00:14:26 +08:00
|
|
|
{
|
2004-07-14 18:31:59 +08:00
|
|
|
GimpDrawable *drawable = GIMP_DRAWABLE (object);
|
|
|
|
gint64 memsize = 0;
|
2002-01-31 00:14:26 +08:00
|
|
|
|
2007-12-24 00:58:41 +08:00
|
|
|
memsize += tile_manager_get_memsize (gimp_drawable_get_tiles (drawable),
|
|
|
|
FALSE);
|
2002-01-31 00:14:26 +08:00
|
|
|
|
2007-11-17 02:19:30 +08:00
|
|
|
*gui_size += gimp_preview_cache_get_memsize (drawable->preview_cache);
|
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
|
|
|
}
|
|
|
|
|
2005-05-25 18:05:17 +08:00
|
|
|
static gboolean
|
|
|
|
gimp_drawable_get_size (GimpViewable *viewable,
|
|
|
|
gint *width,
|
|
|
|
gint *height)
|
|
|
|
{
|
|
|
|
GimpItem *item = GIMP_ITEM (viewable);
|
|
|
|
|
2007-12-24 00:58:41 +08:00
|
|
|
*width = gimp_item_width (item);
|
|
|
|
*height = gimp_item_height (item);
|
2005-05-25 18:05:17 +08:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2001-02-05 06:10:54 +08:00
|
|
|
static void
|
|
|
|
gimp_drawable_invalidate_preview (GimpViewable *viewable)
|
|
|
|
{
|
2004-07-14 18:31:59 +08:00
|
|
|
GimpDrawable *drawable = GIMP_DRAWABLE (viewable);
|
2001-02-05 06:10:54 +08:00
|
|
|
|
2001-05-07 00:14:34 +08:00
|
|
|
if (GIMP_VIEWABLE_CLASS (parent_class)->invalidate_preview)
|
|
|
|
GIMP_VIEWABLE_CLASS (parent_class)->invalidate_preview (viewable);
|
|
|
|
|
2001-02-05 06:10:54 +08:00
|
|
|
drawable->preview_valid = FALSE;
|
|
|
|
|
2003-03-07 00:47:34 +08:00
|
|
|
if (drawable->preview_cache)
|
|
|
|
gimp_preview_cache_invalidate (&drawable->preview_cache);
|
2001-02-05 06:10:54 +08:00
|
|
|
}
|
|
|
|
|
2003-02-11 21:52:47 +08:00
|
|
|
static GimpItem *
|
|
|
|
gimp_drawable_duplicate (GimpItem *item,
|
2008-01-08 19:46:15 +08:00
|
|
|
GType new_type)
|
2001-12-13 07:48:18 +08:00
|
|
|
{
|
2005-12-23 09:15:19 +08:00
|
|
|
GimpItem *new_item;
|
2001-12-13 07:48:18 +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_DRAWABLE (new_item))
|
|
|
|
{
|
|
|
|
GimpDrawable *drawable = GIMP_DRAWABLE (item);
|
|
|
|
GimpDrawable *new_drawable = GIMP_DRAWABLE (new_item);
|
|
|
|
PixelRegion srcPR;
|
|
|
|
PixelRegion destPR;
|
|
|
|
|
|
|
|
gimp_drawable_configure (new_drawable,
|
|
|
|
gimp_item_get_image (item),
|
|
|
|
item->offset_x,
|
|
|
|
item->offset_y,
|
2007-12-24 00:58:41 +08:00
|
|
|
gimp_item_width (item),
|
|
|
|
gimp_item_height (item),
|
2008-01-08 19:46:15 +08:00
|
|
|
gimp_drawable_type (drawable),
|
2005-12-23 09:15:19 +08:00
|
|
|
GIMP_OBJECT (new_drawable)->name);
|
|
|
|
|
2007-12-24 00:58:41 +08:00
|
|
|
pixel_region_init (&srcPR, gimp_drawable_get_tiles (drawable),
|
2005-12-23 09:15:19 +08:00
|
|
|
0, 0,
|
2007-12-24 00:58:41 +08:00
|
|
|
gimp_item_width (item),
|
|
|
|
gimp_item_height (item),
|
2005-12-23 09:15:19 +08:00
|
|
|
FALSE);
|
2007-12-24 00:58:41 +08:00
|
|
|
pixel_region_init (&destPR, gimp_drawable_get_tiles (new_drawable),
|
2005-12-23 09:15:19 +08:00
|
|
|
0, 0,
|
2007-12-24 00:58:41 +08:00
|
|
|
gimp_item_width (new_item),
|
|
|
|
gimp_item_height (new_item),
|
2005-12-23 09:15:19 +08:00
|
|
|
TRUE);
|
|
|
|
|
2008-01-08 19:46:15 +08:00
|
|
|
copy_region (&srcPR, &destPR);
|
2005-12-23 09:15:19 +08:00
|
|
|
}
|
2001-12-13 07:48:18 +08:00
|
|
|
|
2003-02-11 21:52:47 +08:00
|
|
|
return new_item;
|
|
|
|
}
|
|
|
|
|
2004-04-13 21:54:54 +08:00
|
|
|
static void
|
|
|
|
gimp_drawable_translate (GimpItem *item,
|
|
|
|
gint offset_x,
|
|
|
|
gint offset_y,
|
|
|
|
gboolean push_undo)
|
|
|
|
{
|
|
|
|
GimpDrawable *drawable = GIMP_DRAWABLE (item);
|
2006-03-29 01:08:36 +08:00
|
|
|
GimpImage *image = gimp_item_get_image (item);
|
2004-04-13 21:54:54 +08:00
|
|
|
|
|
|
|
if (gimp_drawable_has_floating_sel (drawable))
|
2006-03-29 01:08:36 +08:00
|
|
|
floating_sel_relax (gimp_image_floating_sel (image), FALSE);
|
2004-04-13 21:54:54 +08:00
|
|
|
|
|
|
|
GIMP_ITEM_CLASS (parent_class)->translate (item, offset_x, offset_y,
|
|
|
|
push_undo);
|
|
|
|
|
|
|
|
if (gimp_drawable_has_floating_sel (drawable))
|
2006-03-29 01:08:36 +08:00
|
|
|
floating_sel_rigor (gimp_image_floating_sel (image), FALSE);
|
2004-04-13 21:54:54 +08:00
|
|
|
}
|
|
|
|
|
2003-05-07 19:09:00 +08:00
|
|
|
static void
|
|
|
|
gimp_drawable_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-03-16 04:05:31 +08:00
|
|
|
GimpDrawable *drawable = GIMP_DRAWABLE (item);
|
2003-05-07 19:09:00 +08:00
|
|
|
TileManager *new_tiles;
|
2007-12-24 00:58:41 +08:00
|
|
|
PixelRegion srcPR, destPR;
|
2003-05-07 19:09:00 +08:00
|
|
|
|
|
|
|
new_tiles = tile_manager_new (new_width, new_height, drawable->bytes);
|
|
|
|
|
2007-12-24 00:58:41 +08:00
|
|
|
pixel_region_init (&srcPR, gimp_drawable_get_tiles (drawable),
|
|
|
|
0, 0,
|
|
|
|
gimp_item_width (item),
|
|
|
|
gimp_item_height (item),
|
2003-05-07 19:09:00 +08:00
|
|
|
FALSE);
|
|
|
|
pixel_region_init (&destPR, new_tiles,
|
2007-12-24 00:58:41 +08:00
|
|
|
0, 0,
|
|
|
|
new_width, new_height,
|
2003-05-07 19:09:00 +08:00
|
|
|
TRUE);
|
|
|
|
|
|
|
|
/* Scale the drawable -
|
|
|
|
* If the drawable is indexed, then we don't use pixel-value
|
|
|
|
* resampling because that doesn't necessarily make sense for indexed
|
|
|
|
* images.
|
|
|
|
*/
|
2003-05-09 08:38:51 +08:00
|
|
|
scale_region (&srcPR, &destPR,
|
|
|
|
gimp_drawable_is_indexed (drawable) ?
|
2004-02-09 08:09:20 +08:00
|
|
|
GIMP_INTERPOLATION_NONE : interpolation_type,
|
2004-08-11 02:47:21 +08:00
|
|
|
progress ? gimp_progress_update_and_flush : NULL,
|
|
|
|
progress);
|
2003-05-07 19:09:00 +08:00
|
|
|
|
2005-01-16 03:17:11 +08:00
|
|
|
gimp_drawable_set_tiles_full (drawable, gimp_item_is_attached (item), NULL,
|
2004-03-16 03:34:35 +08:00
|
|
|
new_tiles, gimp_drawable_type (drawable),
|
|
|
|
new_offset_x, new_offset_y);
|
2004-03-14 19:34:31 +08:00
|
|
|
tile_manager_unref (new_tiles);
|
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_drawable_resize (GimpItem *item,
|
|
|
|
GimpContext *context,
|
|
|
|
gint new_width,
|
|
|
|
gint new_height,
|
|
|
|
gint offset_x,
|
|
|
|
gint offset_y)
|
2003-05-07 21:01:17 +08:00
|
|
|
{
|
2004-03-16 04:05:31 +08:00
|
|
|
GimpDrawable *drawable = GIMP_DRAWABLE (item);
|
2003-05-07 21:01:17 +08:00
|
|
|
PixelRegion srcPR, destPR;
|
|
|
|
TileManager *new_tiles;
|
2003-05-14 23:32:07 +08:00
|
|
|
gint new_offset_x;
|
|
|
|
gint new_offset_y;
|
|
|
|
gint copy_x, copy_y;
|
|
|
|
gint copy_width, copy_height;
|
2003-05-07 21:01:17 +08:00
|
|
|
|
2004-11-23 17:32:54 +08:00
|
|
|
/* if the size doesn't change, this is a nop */
|
2007-12-24 00:58:41 +08:00
|
|
|
if (new_width == gimp_item_width (item) &&
|
|
|
|
new_height == gimp_item_height (item) &&
|
|
|
|
offset_x == 0 &&
|
2004-11-26 22:45:10 +08:00
|
|
|
offset_y == 0)
|
2004-11-23 17:32:54 +08:00
|
|
|
return;
|
|
|
|
|
2003-05-14 23:32:07 +08:00
|
|
|
new_offset_x = item->offset_x - offset_x;
|
|
|
|
new_offset_y = item->offset_y - offset_y;
|
2003-05-07 21:01:17 +08:00
|
|
|
|
2003-05-14 23:32:07 +08:00
|
|
|
gimp_rectangle_intersect (item->offset_x, item->offset_y,
|
2007-12-24 00:58:41 +08:00
|
|
|
gimp_item_width (item),
|
|
|
|
gimp_item_height (item),
|
2003-05-14 23:32:07 +08:00
|
|
|
new_offset_x, new_offset_y,
|
|
|
|
new_width, new_height,
|
|
|
|
©_x, ©_y,
|
|
|
|
©_width, ©_height);
|
2003-05-07 21:01:17 +08:00
|
|
|
|
2004-03-16 04:05:31 +08:00
|
|
|
new_tiles = tile_manager_new (new_width, new_height, drawable->bytes);
|
2003-05-07 21:01:17 +08:00
|
|
|
|
|
|
|
/* Determine whether the new tiles need to be initially cleared */
|
2003-05-14 23:32:07 +08:00
|
|
|
if (copy_width != new_width ||
|
|
|
|
copy_height != new_height)
|
2003-05-07 21:01:17 +08:00
|
|
|
{
|
2003-05-14 23:32:07 +08:00
|
|
|
guchar bg[MAX_CHANNELS] = { 0, };
|
|
|
|
|
2003-05-07 21:01:17 +08:00
|
|
|
pixel_region_init (&destPR, new_tiles,
|
|
|
|
0, 0,
|
|
|
|
new_width, new_height,
|
|
|
|
TRUE);
|
|
|
|
|
2003-05-14 23:32:07 +08:00
|
|
|
if (! gimp_drawable_has_alpha (drawable) && ! GIMP_IS_CHANNEL (drawable))
|
2006-10-26 06:14:36 +08:00
|
|
|
gimp_image_get_background (gimp_item_get_image (item), context,
|
|
|
|
gimp_drawable_type (drawable), bg);
|
2003-05-14 23:32:07 +08:00
|
|
|
|
|
|
|
color_region (&destPR, bg);
|
2003-05-07 21:01:17 +08:00
|
|
|
}
|
|
|
|
|
2003-05-14 23:32:07 +08:00
|
|
|
/* Determine whether anything needs to be copied */
|
|
|
|
if (copy_width && copy_height)
|
2003-05-07 21:01:17 +08:00
|
|
|
{
|
2007-12-24 00:58:41 +08:00
|
|
|
pixel_region_init (&srcPR, gimp_drawable_get_tiles (drawable),
|
2003-05-14 23:32:07 +08:00
|
|
|
copy_x - item->offset_x, copy_y - item->offset_y,
|
|
|
|
copy_width, copy_height,
|
|
|
|
FALSE);
|
|
|
|
|
2003-05-07 21:01:17 +08:00
|
|
|
pixel_region_init (&destPR, new_tiles,
|
2003-05-14 23:32:07 +08:00
|
|
|
copy_x - new_offset_x, copy_y - new_offset_y,
|
|
|
|
copy_width, copy_height,
|
2003-05-07 21:01:17 +08:00
|
|
|
TRUE);
|
|
|
|
|
|
|
|
copy_region (&srcPR, &destPR);
|
|
|
|
}
|
|
|
|
|
2005-01-16 03:17:11 +08:00
|
|
|
gimp_drawable_set_tiles_full (drawable, gimp_item_is_attached (item), NULL,
|
2004-03-16 03:34:35 +08:00
|
|
|
new_tiles, gimp_drawable_type (drawable),
|
2004-03-16 04:05:31 +08:00
|
|
|
new_offset_x, new_offset_y);
|
2004-03-14 19:34:31 +08:00
|
|
|
tile_manager_unref (new_tiles);
|
2003-05-07 21:01:17 +08:00
|
|
|
}
|
|
|
|
|
2003-05-13 21:57:11 +08:00
|
|
|
static void
|
|
|
|
gimp_drawable_flip (GimpItem *item,
|
2004-04-15 07:37:34 +08:00
|
|
|
GimpContext *context,
|
2003-05-13 21:57:11 +08:00
|
|
|
GimpOrientationType flip_type,
|
|
|
|
gdouble axis,
|
|
|
|
gboolean clip_result)
|
|
|
|
{
|
2004-04-13 19:43:27 +08:00
|
|
|
GimpDrawable *drawable = GIMP_DRAWABLE (item);
|
2003-05-13 21:57:11 +08:00
|
|
|
TileManager *tiles;
|
|
|
|
gint off_x, off_y;
|
|
|
|
gint old_off_x, old_off_y;
|
|
|
|
|
|
|
|
gimp_item_offsets (item, &off_x, &off_y);
|
|
|
|
|
2007-12-24 00:58:41 +08:00
|
|
|
tile_manager_get_offsets (gimp_drawable_get_tiles (drawable),
|
|
|
|
&old_off_x, &old_off_y);
|
|
|
|
tile_manager_set_offsets (gimp_drawable_get_tiles (drawable),
|
|
|
|
off_x, off_y);
|
2003-05-13 21:57:11 +08:00
|
|
|
|
2004-04-15 07:37:34 +08:00
|
|
|
tiles = gimp_drawable_transform_tiles_flip (drawable, context,
|
2007-12-24 00:58:41 +08:00
|
|
|
gimp_drawable_get_tiles (drawable),
|
2003-05-13 21:57:11 +08:00
|
|
|
flip_type, axis,
|
|
|
|
clip_result);
|
|
|
|
|
2007-12-24 00:58:41 +08:00
|
|
|
tile_manager_set_offsets (gimp_drawable_get_tiles (drawable),
|
|
|
|
old_off_x, old_off_y);
|
2003-05-13 21:57:11 +08:00
|
|
|
|
|
|
|
if (tiles)
|
2003-05-27 01:02:06 +08:00
|
|
|
{
|
|
|
|
gimp_drawable_transform_paste (drawable, tiles, FALSE);
|
|
|
|
tile_manager_unref (tiles);
|
|
|
|
}
|
2003-05-13 21:57:11 +08:00
|
|
|
}
|
|
|
|
|
2003-05-20 18:36:29 +08:00
|
|
|
static void
|
|
|
|
gimp_drawable_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
|
|
|
GimpDrawable *drawable = GIMP_DRAWABLE (item);
|
2003-05-20 18:36:29 +08:00
|
|
|
TileManager *tiles;
|
|
|
|
gint off_x, off_y;
|
|
|
|
gint old_off_x, old_off_y;
|
|
|
|
|
|
|
|
gimp_item_offsets (item, &off_x, &off_y);
|
|
|
|
|
2007-12-24 00:58:41 +08:00
|
|
|
tile_manager_get_offsets (gimp_drawable_get_tiles (drawable),
|
|
|
|
&old_off_x, &old_off_y);
|
|
|
|
tile_manager_set_offsets (gimp_drawable_get_tiles (drawable),
|
|
|
|
off_x, off_y);
|
2003-05-20 18:36:29 +08:00
|
|
|
|
2004-04-15 07:37:34 +08:00
|
|
|
tiles = gimp_drawable_transform_tiles_rotate (drawable, context,
|
2007-12-24 00:58:41 +08:00
|
|
|
gimp_drawable_get_tiles (drawable),
|
2003-05-20 18:36:29 +08:00
|
|
|
rotate_type, center_x, center_y,
|
|
|
|
clip_result);
|
|
|
|
|
2007-12-24 00:58:41 +08:00
|
|
|
tile_manager_set_offsets (gimp_drawable_get_tiles (drawable),
|
|
|
|
old_off_x, old_off_y);
|
2003-05-20 18:36:29 +08:00
|
|
|
|
|
|
|
if (tiles)
|
2003-05-27 01:02:06 +08:00
|
|
|
{
|
|
|
|
gimp_drawable_transform_paste (drawable, tiles, FALSE);
|
|
|
|
tile_manager_unref (tiles);
|
|
|
|
}
|
2003-05-20 18:36:29 +08:00
|
|
|
}
|
|
|
|
|
2003-05-13 21:57:11 +08:00
|
|
|
static void
|
|
|
|
gimp_drawable_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-13 21:57:11 +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-13 21:57:11 +08:00
|
|
|
{
|
2004-04-13 19:43:27 +08:00
|
|
|
GimpDrawable *drawable = GIMP_DRAWABLE (item);
|
2003-05-13 21:57:11 +08:00
|
|
|
TileManager *tiles;
|
|
|
|
gint off_x, off_y;
|
|
|
|
gint old_off_x, old_off_y;
|
|
|
|
|
|
|
|
gimp_item_offsets (item, &off_x, &off_y);
|
|
|
|
|
2007-12-24 00:58:41 +08:00
|
|
|
tile_manager_get_offsets (gimp_drawable_get_tiles (drawable),
|
|
|
|
&old_off_x, &old_off_y);
|
|
|
|
tile_manager_set_offsets (gimp_drawable_get_tiles (drawable),
|
|
|
|
off_x, off_y);
|
2003-05-13 21:57:11 +08:00
|
|
|
|
2004-04-15 07:37:34 +08:00
|
|
|
tiles = gimp_drawable_transform_tiles_affine (drawable, context,
|
2007-12-24 00:58:41 +08:00
|
|
|
gimp_drawable_get_tiles (drawable),
|
2003-05-13 21:57:11 +08:00
|
|
|
matrix, direction,
|
|
|
|
interpolation_type,
|
2007-09-10 23:29:48 +08:00
|
|
|
recursion_level,
|
2003-05-13 21:57:11 +08:00
|
|
|
clip_result,
|
2004-08-11 02:47:21 +08:00
|
|
|
progress);
|
2003-05-13 21:57:11 +08:00
|
|
|
|
2007-12-24 00:58:41 +08:00
|
|
|
tile_manager_set_offsets (gimp_drawable_get_tiles (drawable),
|
|
|
|
old_off_x, old_off_y);
|
2003-05-13 21:57:11 +08:00
|
|
|
|
|
|
|
if (tiles)
|
2003-05-27 01:02:06 +08:00
|
|
|
{
|
|
|
|
gimp_drawable_transform_paste (drawable, tiles, FALSE);
|
|
|
|
tile_manager_unref (tiles);
|
|
|
|
}
|
2003-05-13 21:57:11 +08:00
|
|
|
}
|
|
|
|
|
2007-04-28 00:07:49 +08:00
|
|
|
static gboolean
|
|
|
|
gimp_drawable_get_pixel_at (GimpPickable *pickable,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
guchar *pixel)
|
|
|
|
{
|
|
|
|
GimpDrawable *drawable = GIMP_DRAWABLE (pickable);
|
|
|
|
|
|
|
|
/* do not make this a g_return_if_fail() */
|
2007-12-24 00:58:41 +08:00
|
|
|
if (x < 0 || x >= gimp_item_width (GIMP_ITEM (drawable)) ||
|
|
|
|
y < 0 || y >= gimp_item_height (GIMP_ITEM (drawable)))
|
2007-04-28 00:07:49 +08:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
read_pixel_data_1 (gimp_drawable_get_tiles (drawable), x, y, pixel);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
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_drawable_real_update (GimpDrawable *drawable,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint width,
|
|
|
|
gint height)
|
|
|
|
{
|
|
|
|
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (drawable));
|
|
|
|
}
|
|
|
|
|
2007-12-04 19:30:31 +08:00
|
|
|
static gint64
|
|
|
|
gimp_drawable_real_estimate_memsize (const GimpDrawable *drawable,
|
|
|
|
gint width,
|
|
|
|
gint height)
|
|
|
|
{
|
|
|
|
return (gint64) gimp_drawable_bytes (drawable) * width * height;
|
|
|
|
}
|
|
|
|
|
2007-12-18 19:20:23 +08:00
|
|
|
static TileManager *
|
|
|
|
gimp_drawable_real_get_tiles (GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
return drawable->tiles;
|
|
|
|
}
|
|
|
|
|
2004-03-13 21:56:09 +08:00
|
|
|
static void
|
|
|
|
gimp_drawable_real_set_tiles (GimpDrawable *drawable,
|
|
|
|
gboolean push_undo,
|
|
|
|
const gchar *undo_desc,
|
|
|
|
TileManager *tiles,
|
2004-03-16 03:34:35 +08:00
|
|
|
GimpImageType type,
|
|
|
|
gint offset_x,
|
|
|
|
gint offset_y)
|
2004-03-13 21:56:09 +08:00
|
|
|
{
|
2004-03-16 03:34:35 +08:00
|
|
|
GimpItem *item;
|
|
|
|
gboolean old_has_alpha;
|
2004-03-15 23:37:12 +08:00
|
|
|
|
2004-03-13 21:56:09 +08:00
|
|
|
g_return_if_fail (tile_manager_bpp (tiles) == GIMP_IMAGE_TYPE_BYTES (type));
|
|
|
|
|
2004-03-16 03:34:35 +08:00
|
|
|
item = GIMP_ITEM (drawable);
|
|
|
|
|
2004-03-15 23:37:12 +08:00
|
|
|
old_has_alpha = gimp_drawable_has_alpha (drawable);
|
|
|
|
|
2004-03-16 01:53:55 +08:00
|
|
|
gimp_drawable_invalidate_boundary (drawable);
|
|
|
|
|
2004-03-16 04:58:07 +08:00
|
|
|
if (push_undo)
|
|
|
|
gimp_image_undo_push_drawable_mod (gimp_item_get_image (item), undo_desc,
|
|
|
|
drawable);
|
|
|
|
|
2004-03-17 00:23:06 +08:00
|
|
|
/* ref new before unrefing old, they might be the same */
|
|
|
|
tile_manager_ref (tiles);
|
|
|
|
|
2004-03-13 21:56:09 +08:00
|
|
|
if (drawable->tiles)
|
|
|
|
tile_manager_unref (drawable->tiles);
|
|
|
|
|
2004-03-17 00:23:06 +08:00
|
|
|
drawable->tiles = tiles;
|
2004-03-13 21:56:09 +08:00
|
|
|
drawable->type = type;
|
|
|
|
drawable->bytes = tile_manager_bpp (tiles);
|
|
|
|
drawable->has_alpha = GIMP_IMAGE_TYPE_HAS_ALPHA (type);
|
2004-03-15 23:37:12 +08:00
|
|
|
|
2004-03-16 03:34:35 +08:00
|
|
|
item->offset_x = offset_x;
|
|
|
|
item->offset_y = offset_y;
|
|
|
|
|
2007-12-24 00:58:41 +08:00
|
|
|
if (gimp_item_width (item) != tile_manager_width (tiles) ||
|
|
|
|
gimp_item_height (item) != tile_manager_height (tiles))
|
2004-03-16 03:34:35 +08:00
|
|
|
{
|
|
|
|
item->width = tile_manager_width (tiles);
|
|
|
|
item->height = tile_manager_height (tiles);
|
|
|
|
|
|
|
|
gimp_viewable_size_changed (GIMP_VIEWABLE (drawable));
|
|
|
|
}
|
|
|
|
|
2004-03-15 23:37:12 +08:00
|
|
|
if (old_has_alpha != gimp_drawable_has_alpha (drawable))
|
|
|
|
gimp_drawable_alpha_changed (drawable);
|
2004-03-13 21:56:09 +08:00
|
|
|
}
|
|
|
|
|
2004-04-01 22:51:58 +08:00
|
|
|
static void
|
|
|
|
gimp_drawable_real_push_undo (GimpDrawable *drawable,
|
|
|
|
const gchar *undo_desc,
|
|
|
|
TileManager *tiles,
|
|
|
|
gboolean sparse,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint width,
|
|
|
|
gint height)
|
|
|
|
{
|
|
|
|
gboolean new_tiles = FALSE;
|
|
|
|
|
|
|
|
if (! tiles)
|
|
|
|
{
|
|
|
|
PixelRegion srcPR, destPR;
|
|
|
|
|
|
|
|
tiles = tile_manager_new (width, height, gimp_drawable_bytes (drawable));
|
2006-04-07 17:21:18 +08:00
|
|
|
pixel_region_init (&srcPR, gimp_drawable_get_tiles (drawable),
|
2004-04-01 22:51:58 +08:00
|
|
|
x, y, width, height, FALSE);
|
|
|
|
pixel_region_init (&destPR, tiles,
|
|
|
|
0, 0, width, height, TRUE);
|
|
|
|
copy_region (&srcPR, &destPR);
|
|
|
|
|
|
|
|
new_tiles = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
gimp_image_undo_push_drawable (gimp_item_get_image (GIMP_ITEM (drawable)),
|
|
|
|
undo_desc, drawable,
|
|
|
|
tiles, sparse,
|
|
|
|
x, y, width, height);
|
|
|
|
|
|
|
|
if (new_tiles)
|
|
|
|
tile_manager_unref (tiles);
|
|
|
|
}
|
|
|
|
|
2004-03-15 22:10:30 +08:00
|
|
|
static void
|
2006-04-07 17:21:18 +08:00
|
|
|
gimp_drawable_real_swap_pixels (GimpDrawable *drawable,
|
|
|
|
TileManager *tiles,
|
|
|
|
gboolean sparse,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint width,
|
|
|
|
gint height)
|
2004-03-15 22:10:30 +08:00
|
|
|
{
|
|
|
|
if (sparse)
|
|
|
|
{
|
|
|
|
gint i, j;
|
|
|
|
|
|
|
|
for (i = y; i < (y + height); i += (TILE_HEIGHT - (i % TILE_HEIGHT)))
|
2004-07-14 18:31:59 +08:00
|
|
|
{
|
|
|
|
for (j = x; j < (x + width); j += (TILE_WIDTH - (j % TILE_WIDTH)))
|
|
|
|
{
|
2004-03-15 22:10:30 +08:00
|
|
|
Tile *src_tile;
|
|
|
|
Tile *dest_tile;
|
|
|
|
|
2004-07-14 18:31:59 +08:00
|
|
|
src_tile = tile_manager_get_tile (tiles, j, i, FALSE, FALSE);
|
2004-03-15 22:10:30 +08:00
|
|
|
|
2004-07-14 18:31:59 +08:00
|
|
|
if (tile_is_valid (src_tile))
|
|
|
|
{
|
|
|
|
/* swap tiles, not pixels! */
|
2004-03-15 22:10:30 +08:00
|
|
|
|
2004-07-14 18:31:59 +08:00
|
|
|
src_tile = tile_manager_get_tile (tiles,
|
2004-03-15 22:10:30 +08:00
|
|
|
j, i, TRUE, FALSE /*TRUE*/);
|
2006-04-07 17:21:18 +08:00
|
|
|
dest_tile = tile_manager_get_tile (gimp_drawable_get_tiles (drawable),
|
|
|
|
j, i, TRUE, FALSE /* TRUE */);
|
2004-03-15 22:10:30 +08:00
|
|
|
|
2004-07-14 18:31:59 +08:00
|
|
|
tile_manager_map_tile (tiles,
|
2004-03-15 22:10:30 +08:00
|
|
|
j, i, dest_tile);
|
2006-04-07 17:21:18 +08:00
|
|
|
tile_manager_map_tile (gimp_drawable_get_tiles (drawable),
|
2004-03-15 22:10:30 +08:00
|
|
|
j, i, src_tile);
|
2007-09-13 02:29:11 +08:00
|
|
|
|
|
|
|
tile_release (dest_tile, FALSE);
|
|
|
|
tile_release (src_tile, FALSE);
|
2004-07-14 18:31:59 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-03-15 22:10:30 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PixelRegion PR1, PR2;
|
|
|
|
|
|
|
|
pixel_region_init (&PR1, tiles,
|
2004-07-14 18:31:59 +08:00
|
|
|
0, 0, width, height, TRUE);
|
2006-04-07 17:21:18 +08:00
|
|
|
pixel_region_init (&PR2, gimp_drawable_get_tiles (drawable),
|
2004-07-14 18:31:59 +08:00
|
|
|
x, y, width, height, TRUE);
|
2004-03-15 22:10:30 +08:00
|
|
|
|
|
|
|
swap_region (&PR1, &PR2);
|
|
|
|
}
|
|
|
|
|
|
|
|
gimp_drawable_update (drawable, x, y, width, height);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* public functions */
|
|
|
|
|
2007-12-04 19:30:31 +08:00
|
|
|
gint64
|
|
|
|
gimp_drawable_estimate_memsize (const GimpDrawable *drawable,
|
|
|
|
gint width,
|
|
|
|
gint height)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), 0);
|
|
|
|
|
|
|
|
return GIMP_DRAWABLE_GET_CLASS (drawable)->estimate_memsize (drawable,
|
|
|
|
width, height);
|
|
|
|
}
|
|
|
|
|
2003-02-11 21:52:47 +08:00
|
|
|
void
|
|
|
|
gimp_drawable_configure (GimpDrawable *drawable,
|
2006-03-29 01:08:36 +08:00
|
|
|
GimpImage *image,
|
2003-02-11 21:52:47 +08:00
|
|
|
gint offset_x,
|
|
|
|
gint offset_y,
|
2004-07-14 18:31:59 +08:00
|
|
|
gint width,
|
|
|
|
gint height,
|
|
|
|
GimpImageType type,
|
|
|
|
const gchar *name)
|
2003-02-11 21:52:47 +08:00
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
|
2006-03-29 01:08:36 +08:00
|
|
|
g_return_if_fail (GIMP_IS_IMAGE (image));
|
2004-04-03 20:03:27 +08:00
|
|
|
g_return_if_fail (width > 0 && height > 0);
|
2003-02-11 21:52:47 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
gimp_item_configure (GIMP_ITEM (drawable), image,
|
2003-05-08 22:21:39 +08:00
|
|
|
offset_x, offset_y, width, height, name);
|
2003-05-08 19:52:31 +08:00
|
|
|
|
2003-02-11 21:52:47 +08:00
|
|
|
drawable->type = type;
|
|
|
|
drawable->bytes = GIMP_IMAGE_TYPE_BYTES (type);
|
|
|
|
drawable->has_alpha = GIMP_IMAGE_TYPE_HAS_ALPHA (type);
|
|
|
|
|
|
|
|
if (drawable->tiles)
|
2003-05-27 01:02:06 +08:00
|
|
|
tile_manager_unref (drawable->tiles);
|
2003-02-11 21:52:47 +08:00
|
|
|
|
2003-06-12 18:43:00 +08:00
|
|
|
drawable->tiles = tile_manager_new (width, height, drawable->bytes);
|
2003-02-11 21:52:47 +08:00
|
|
|
|
|
|
|
/* preview variables */
|
|
|
|
drawable->preview_cache = NULL;
|
|
|
|
drawable->preview_valid = FALSE;
|
2001-12-13 07:48:18 +08:00
|
|
|
}
|
|
|
|
|
2001-07-08 06:49:01 +08:00
|
|
|
void
|
|
|
|
gimp_drawable_update (GimpDrawable *drawable,
|
2004-07-14 18:31:59 +08:00
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint width,
|
|
|
|
gint height)
|
2001-07-08 06:49:01 +08:00
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
|
|
|
|
|
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_emit (drawable, gimp_drawable_signals[UPDATE], 0,
|
|
|
|
x, y, width, height);
|
2001-07-08 06:49:01 +08:00
|
|
|
}
|
|
|
|
|
2003-10-06 22:40:12 +08:00
|
|
|
void
|
|
|
|
gimp_drawable_alpha_changed (GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
|
|
|
|
|
|
|
|
g_signal_emit (drawable, gimp_drawable_signals[ALPHA_CHANGED], 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_drawable_invalidate_boundary (GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
GimpDrawableClass *drawable_class;
|
|
|
|
|
|
|
|
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
|
|
|
|
|
|
|
|
drawable_class = GIMP_DRAWABLE_GET_CLASS (drawable);
|
|
|
|
|
|
|
|
if (drawable_class->invalidate_boundary)
|
|
|
|
drawable_class->invalidate_boundary (drawable);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_drawable_get_active_components (const GimpDrawable *drawable,
|
|
|
|
gboolean *active)
|
|
|
|
{
|
|
|
|
GimpDrawableClass *drawable_class;
|
|
|
|
|
|
|
|
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
|
|
|
|
g_return_if_fail (active != NULL);
|
|
|
|
|
|
|
|
drawable_class = GIMP_DRAWABLE_GET_CLASS (drawable);
|
|
|
|
|
|
|
|
if (drawable_class->get_active_components)
|
|
|
|
drawable_class->get_active_components (drawable, active);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_drawable_apply_region (GimpDrawable *drawable,
|
|
|
|
PixelRegion *src2PR,
|
|
|
|
gboolean push_undo,
|
|
|
|
const gchar *undo_desc,
|
|
|
|
gdouble opacity,
|
|
|
|
GimpLayerModeEffects mode,
|
|
|
|
TileManager *src1_tiles,
|
|
|
|
gint x,
|
|
|
|
gint y)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
|
2004-11-16 21:41:55 +08:00
|
|
|
g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
|
2003-10-09 01:20:06 +08:00
|
|
|
g_return_if_fail (src2PR != NULL);
|
2003-10-06 22:40:12 +08:00
|
|
|
|
|
|
|
GIMP_DRAWABLE_GET_CLASS (drawable)->apply_region (drawable, src2PR,
|
|
|
|
push_undo, undo_desc,
|
|
|
|
opacity, mode,
|
|
|
|
src1_tiles,
|
|
|
|
x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_drawable_replace_region (GimpDrawable *drawable,
|
|
|
|
PixelRegion *src2PR,
|
|
|
|
gboolean push_undo,
|
|
|
|
const gchar *undo_desc,
|
|
|
|
gdouble opacity,
|
|
|
|
PixelRegion *maskPR,
|
|
|
|
gint x,
|
|
|
|
gint y)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
|
2004-11-16 21:41:55 +08:00
|
|
|
g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
|
2003-10-09 01:20:06 +08:00
|
|
|
g_return_if_fail (src2PR != NULL);
|
|
|
|
g_return_if_fail (maskPR != NULL);
|
2003-10-06 22:40:12 +08:00
|
|
|
|
|
|
|
GIMP_DRAWABLE_GET_CLASS (drawable)->replace_region (drawable, src2PR,
|
|
|
|
push_undo, undo_desc,
|
|
|
|
opacity, maskPR,
|
|
|
|
x, y);
|
|
|
|
}
|
|
|
|
|
2006-04-07 17:21:18 +08:00
|
|
|
TileManager *
|
2007-12-18 19:20:23 +08:00
|
|
|
gimp_drawable_get_tiles (GimpDrawable *drawable)
|
2006-04-07 17:21:18 +08:00
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
|
|
|
|
|
2007-12-18 19:20:23 +08:00
|
|
|
return GIMP_DRAWABLE_GET_CLASS (drawable)->get_tiles (drawable);
|
2006-04-07 17:21:18 +08:00
|
|
|
}
|
|
|
|
|
2004-03-13 21:56:09 +08:00
|
|
|
void
|
|
|
|
gimp_drawable_set_tiles (GimpDrawable *drawable,
|
|
|
|
gboolean push_undo,
|
|
|
|
const gchar *undo_desc,
|
2004-03-16 03:34:35 +08:00
|
|
|
TileManager *tiles)
|
|
|
|
{
|
|
|
|
gint offset_x, offset_y;
|
|
|
|
|
|
|
|
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
|
|
|
|
g_return_if_fail (tiles != NULL);
|
|
|
|
|
2004-11-16 21:41:55 +08:00
|
|
|
if (! gimp_item_is_attached (GIMP_ITEM (drawable)))
|
|
|
|
push_undo = FALSE;
|
|
|
|
|
2004-03-16 03:34:35 +08:00
|
|
|
gimp_item_offsets (GIMP_ITEM (drawable), &offset_x, &offset_y);
|
|
|
|
|
|
|
|
gimp_drawable_set_tiles_full (drawable, push_undo, undo_desc, tiles,
|
|
|
|
gimp_drawable_type (drawable),
|
|
|
|
offset_x, offset_y);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_drawable_set_tiles_full (GimpDrawable *drawable,
|
|
|
|
gboolean push_undo,
|
|
|
|
const gchar *undo_desc,
|
|
|
|
TileManager *tiles,
|
|
|
|
GimpImageType type,
|
|
|
|
gint offset_x,
|
|
|
|
gint offset_y)
|
2004-03-13 21:56:09 +08:00
|
|
|
{
|
2004-04-13 21:54:54 +08:00
|
|
|
GimpItem *item;
|
2006-03-29 01:08:36 +08:00
|
|
|
GimpImage *image;
|
2004-03-16 04:05:31 +08:00
|
|
|
|
2004-03-13 21:56:09 +08:00
|
|
|
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
|
|
|
|
g_return_if_fail (tiles != NULL);
|
2004-03-16 04:58:07 +08:00
|
|
|
g_return_if_fail (tile_manager_bpp (tiles) == GIMP_IMAGE_TYPE_BYTES (type));
|
2004-03-13 21:56:09 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
item = GIMP_ITEM (drawable);
|
|
|
|
image = gimp_item_get_image (item);
|
2004-04-13 21:54:54 +08:00
|
|
|
|
2004-11-16 21:41:55 +08:00
|
|
|
if (! gimp_item_is_attached (GIMP_ITEM (drawable)))
|
|
|
|
push_undo = FALSE;
|
|
|
|
|
2007-12-24 00:58:41 +08:00
|
|
|
if (gimp_item_width (item) != tile_manager_width (tiles) ||
|
|
|
|
gimp_item_height (item) != tile_manager_height (tiles) ||
|
|
|
|
item->offset_x != offset_x ||
|
|
|
|
item->offset_y != offset_y)
|
2004-03-16 04:05:31 +08:00
|
|
|
{
|
2007-12-24 00:58:41 +08:00
|
|
|
gimp_drawable_update (drawable,
|
|
|
|
0, 0,
|
|
|
|
gimp_item_width (item),
|
|
|
|
gimp_item_height (item));
|
2004-03-16 04:05:31 +08:00
|
|
|
}
|
|
|
|
|
2004-04-13 21:54:54 +08:00
|
|
|
if (gimp_drawable_has_floating_sel (drawable))
|
2006-03-29 01:08:36 +08:00
|
|
|
floating_sel_relax (gimp_image_floating_sel (image), FALSE);
|
2004-04-13 21:54:54 +08:00
|
|
|
|
2004-03-13 21:56:09 +08:00
|
|
|
GIMP_DRAWABLE_GET_CLASS (drawable)->set_tiles (drawable,
|
|
|
|
push_undo, undo_desc,
|
2004-03-16 03:34:35 +08:00
|
|
|
tiles, type,
|
|
|
|
offset_x, offset_y);
|
2004-03-16 04:05:31 +08:00
|
|
|
|
2004-04-13 21:54:54 +08:00
|
|
|
if (gimp_drawable_has_floating_sel (drawable))
|
2006-03-29 01:08:36 +08:00
|
|
|
floating_sel_rigor (gimp_image_floating_sel (image), FALSE);
|
2004-04-13 21:54:54 +08:00
|
|
|
|
2007-12-24 00:58:41 +08:00
|
|
|
gimp_drawable_update (drawable,
|
|
|
|
0, 0,
|
|
|
|
gimp_item_width (item),
|
|
|
|
gimp_item_height (item));
|
2004-03-13 21:56:09 +08:00
|
|
|
}
|
|
|
|
|
2004-03-15 22:10:30 +08:00
|
|
|
void
|
|
|
|
gimp_drawable_swap_pixels (GimpDrawable *drawable,
|
|
|
|
TileManager *tiles,
|
|
|
|
gboolean sparse,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint width,
|
|
|
|
gint height)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
|
|
|
|
g_return_if_fail (tiles != NULL);
|
|
|
|
|
|
|
|
GIMP_DRAWABLE_GET_CLASS (drawable)->swap_pixels (drawable, tiles, sparse,
|
|
|
|
x, y, width, height);
|
|
|
|
}
|
|
|
|
|
2001-07-08 06:49:01 +08:00
|
|
|
void
|
2003-02-14 22:14:29 +08:00
|
|
|
gimp_drawable_push_undo (GimpDrawable *drawable,
|
|
|
|
const gchar *undo_desc,
|
2002-06-07 03:44:05 +08:00
|
|
|
gint x1,
|
|
|
|
gint y1,
|
|
|
|
gint x2,
|
2003-09-02 21:43:26 +08:00
|
|
|
gint y2,
|
2002-06-07 03:44:05 +08:00
|
|
|
TileManager *tiles,
|
|
|
|
gboolean sparse)
|
2001-07-08 06:49:01 +08:00
|
|
|
{
|
2004-03-15 22:10:30 +08:00
|
|
|
GimpItem *item;
|
2004-04-01 22:51:58 +08:00
|
|
|
gint x, y;
|
|
|
|
gint width, height;
|
2004-03-15 22:10:30 +08:00
|
|
|
|
2001-07-08 06:49:01 +08:00
|
|
|
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
|
2004-03-15 22:10:30 +08:00
|
|
|
g_return_if_fail (sparse == FALSE || tiles != NULL);
|
|
|
|
|
|
|
|
item = GIMP_ITEM (drawable);
|
|
|
|
|
2004-11-16 21:41:55 +08:00
|
|
|
g_return_if_fail (gimp_item_is_attached (item));
|
2004-03-15 22:10:30 +08:00
|
|
|
g_return_if_fail (sparse == FALSE ||
|
|
|
|
tile_manager_width (tiles) == gimp_item_width (item));
|
|
|
|
g_return_if_fail (sparse == FALSE ||
|
|
|
|
tile_manager_height (tiles) == gimp_item_height (item));
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
g_printerr ("gimp_drawable_push_undo (%s, %d, %d, %d, %d)\n",
|
|
|
|
sparse ? "TRUE" : "FALSE", x1, y1, x2 - x1, y2 - y1);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (! gimp_rectangle_intersect (x1, y1,
|
|
|
|
x2 - x1, y2 - y1,
|
|
|
|
0, 0,
|
|
|
|
gimp_item_width (item),
|
|
|
|
gimp_item_height (item),
|
|
|
|
&x, &y, &width, &height))
|
|
|
|
{
|
2004-05-12 16:13:33 +08:00
|
|
|
g_warning ("%s: tried to push empty region", G_STRFUNC);
|
2004-03-15 22:10:30 +08:00
|
|
|
return;
|
|
|
|
}
|
2001-07-08 06:49:01 +08:00
|
|
|
|
2004-04-01 22:51:58 +08:00
|
|
|
GIMP_DRAWABLE_GET_CLASS (drawable)->push_undo (drawable, undo_desc,
|
|
|
|
tiles, sparse,
|
|
|
|
x, y, width, height);
|
2001-07-08 06:49:01 +08:00
|
|
|
}
|
|
|
|
|
2003-10-07 02:26:06 +08:00
|
|
|
TileManager *
|
2006-04-07 17:50:23 +08:00
|
|
|
gimp_drawable_get_shadow_tiles (GimpDrawable *drawable)
|
2003-10-07 02:26:06 +08:00
|
|
|
{
|
2004-11-16 21:41:55 +08:00
|
|
|
GimpItem *item;
|
2003-10-07 02:26:06 +08:00
|
|
|
|
|
|
|
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
|
|
|
|
|
2004-11-16 21:41:55 +08:00
|
|
|
item = GIMP_ITEM (drawable);
|
2003-10-07 02:26:06 +08:00
|
|
|
|
2004-11-16 21:41:55 +08:00
|
|
|
g_return_val_if_fail (gimp_item_is_attached (item), NULL);
|
2003-10-07 02:26:06 +08:00
|
|
|
|
2006-04-07 17:50:23 +08:00
|
|
|
return gimp_image_get_shadow_tiles (gimp_item_get_image (item),
|
2007-12-24 00:58:41 +08:00
|
|
|
gimp_item_width (item),
|
|
|
|
gimp_item_height (item),
|
2006-04-07 17:50:23 +08:00
|
|
|
drawable->bytes);
|
2003-10-07 02:26:06 +08:00
|
|
|
}
|
|
|
|
|
1998-06-30 23:31:32 +08:00
|
|
|
void
|
1999-08-22 19:45:31 +08:00
|
|
|
gimp_drawable_merge_shadow (GimpDrawable *drawable,
|
2004-07-14 18:31:59 +08:00
|
|
|
gboolean push_undo,
|
2003-02-14 22:14:29 +08:00
|
|
|
const gchar *undo_desc)
|
1998-06-30 23:31:32 +08:00
|
|
|
{
|
2006-03-29 01:08:36 +08:00
|
|
|
GimpImage *image;
|
2004-11-16 21:41:55 +08:00
|
|
|
gint x, y, width, height;
|
1998-06-30 23:31:32 +08:00
|
|
|
|
2000-02-17 19:44:27 +08:00
|
|
|
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
|
2004-11-16 21:41:55 +08:00
|
|
|
g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
|
1998-06-30 23:31:32 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
image = gimp_item_get_image (GIMP_ITEM (drawable));
|
2000-12-29 00:19:55 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
g_return_if_fail (image->shadow != NULL);
|
1999-01-28 06:00:44 +08:00
|
|
|
|
1998-06-30 23:31:32 +08:00
|
|
|
/* A useful optimization here is to limit the update to the
|
|
|
|
* extents of the selection mask, as it cannot extend beyond
|
|
|
|
* them.
|
|
|
|
*/
|
2004-10-20 06:52:04 +08:00
|
|
|
if (gimp_drawable_mask_intersect (drawable, &x, &y, &width, &height))
|
|
|
|
{
|
|
|
|
PixelRegion shadowPR;
|
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
pixel_region_init (&shadowPR, image->shadow,
|
2004-10-20 06:52:04 +08:00
|
|
|
x, y, width, height, FALSE);
|
|
|
|
gimp_drawable_apply_region (drawable, &shadowPR,
|
|
|
|
push_undo, undo_desc,
|
|
|
|
GIMP_OPACITY_OPAQUE, GIMP_REPLACE_MODE,
|
|
|
|
NULL, x, y);
|
|
|
|
}
|
1998-06-30 23:31:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2004-01-06 22:02:08 +08:00
|
|
|
gimp_drawable_fill (GimpDrawable *drawable,
|
2004-07-14 18:31:59 +08:00
|
|
|
const GimpRGB *color,
|
2004-01-06 22:02:08 +08:00
|
|
|
const GimpPattern *pattern)
|
1998-06-30 23:31:32 +08:00
|
|
|
{
|
2003-09-06 21:41:58 +08:00
|
|
|
GimpItem *item;
|
2006-03-29 01:08:36 +08:00
|
|
|
GimpImage *image;
|
2003-09-06 21:41:58 +08:00
|
|
|
GimpImageType drawable_type;
|
|
|
|
PixelRegion destPR;
|
1998-06-30 23:31:32 +08:00
|
|
|
|
2000-02-17 19:44:27 +08:00
|
|
|
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
|
2004-01-06 22:02:08 +08:00
|
|
|
g_return_if_fail (color != NULL || pattern != NULL);
|
|
|
|
g_return_if_fail (pattern == NULL || GIMP_IS_PATTERN (pattern));
|
2000-02-17 19:44:27 +08:00
|
|
|
|
2006-05-08 19:15:51 +08:00
|
|
|
item = GIMP_ITEM (drawable);
|
2006-03-29 01:08:36 +08:00
|
|
|
image = gimp_item_get_image (item);
|
2000-12-29 00:19:55 +08:00
|
|
|
|
2003-09-06 21:41:58 +08:00
|
|
|
drawable_type = gimp_drawable_type (drawable);
|
|
|
|
|
2006-04-07 17:21:18 +08:00
|
|
|
pixel_region_init (&destPR, gimp_drawable_get_tiles (drawable),
|
2004-01-06 22:02:08 +08:00
|
|
|
0, 0, gimp_item_width (item), gimp_item_height (item),
|
|
|
|
TRUE);
|
2003-09-06 21:41:58 +08:00
|
|
|
|
2004-01-06 22:02:08 +08:00
|
|
|
if (color)
|
1998-06-30 23:31:32 +08:00
|
|
|
{
|
2004-01-06 22:02:08 +08:00
|
|
|
guchar tmp[MAX_CHANNELS];
|
|
|
|
guchar c[MAX_CHANNELS];
|
2000-12-29 00:19:55 +08:00
|
|
|
|
2004-01-06 22:02:08 +08:00
|
|
|
gimp_rgba_get_uchar (color,
|
|
|
|
&tmp[RED_PIX],
|
|
|
|
&tmp[GREEN_PIX],
|
|
|
|
&tmp[BLUE_PIX],
|
|
|
|
&tmp[ALPHA_PIX]);
|
2003-09-06 21:41:58 +08:00
|
|
|
|
2006-10-26 06:14:36 +08:00
|
|
|
gimp_image_transform_color (image, drawable_type, c, GIMP_RGB, tmp);
|
2000-12-29 00:19:55 +08:00
|
|
|
|
2004-01-06 22:02:08 +08:00
|
|
|
if (GIMP_IMAGE_TYPE_HAS_ALPHA (drawable_type))
|
|
|
|
c[GIMP_IMAGE_TYPE_BYTES (drawable_type) - 1] = tmp[ALPHA_PIX];
|
|
|
|
else
|
|
|
|
c[GIMP_IMAGE_TYPE_BYTES (drawable_type)] = OPAQUE_OPACITY;
|
2003-09-06 21:41:58 +08:00
|
|
|
|
2004-01-06 22:02:08 +08:00
|
|
|
color_region (&destPR, c);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TempBuf *pat_buf;
|
|
|
|
gboolean new_buf;
|
2003-09-06 21:41:58 +08:00
|
|
|
|
2006-10-26 06:14:36 +08:00
|
|
|
pat_buf = gimp_image_transform_temp_buf (image, drawable_type,
|
2004-01-06 22:02:08 +08:00
|
|
|
pattern->mask, &new_buf);
|
2000-12-29 00:19:55 +08:00
|
|
|
|
2004-01-06 22:02:08 +08:00
|
|
|
pattern_region (&destPR, NULL, pat_buf, 0, 0);
|
1998-06-30 23:31:32 +08:00
|
|
|
|
2004-01-06 22:02:08 +08:00
|
|
|
if (new_buf)
|
|
|
|
temp_buf_free (pat_buf);
|
|
|
|
}
|
2001-07-08 06:49:01 +08:00
|
|
|
|
|
|
|
gimp_drawable_update (drawable,
|
2004-07-14 18:31:59 +08:00
|
|
|
0, 0,
|
|
|
|
gimp_item_width (item),
|
|
|
|
gimp_item_height (item));
|
2001-07-08 06:49:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_drawable_fill_by_type (GimpDrawable *drawable,
|
2004-07-14 18:31:59 +08:00
|
|
|
GimpContext *context,
|
|
|
|
GimpFillType fill_type)
|
2001-07-08 06:49:01 +08:00
|
|
|
{
|
2004-01-06 22:02:08 +08:00
|
|
|
GimpRGB color;
|
|
|
|
GimpPattern *pattern = NULL;
|
2001-07-08 06:49:01 +08:00
|
|
|
|
|
|
|
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
|
|
|
|
|
|
|
|
switch (fill_type)
|
|
|
|
{
|
2002-03-18 19:07:34 +08:00
|
|
|
case GIMP_FOREGROUND_FILL:
|
2001-07-08 06:49:01 +08:00
|
|
|
gimp_context_get_foreground (context, &color);
|
|
|
|
break;
|
|
|
|
|
2003-09-06 21:41:58 +08:00
|
|
|
case GIMP_BACKGROUND_FILL:
|
2001-07-08 06:49:01 +08:00
|
|
|
gimp_context_get_background (context, &color);
|
|
|
|
break;
|
|
|
|
|
2002-03-18 19:07:34 +08:00
|
|
|
case GIMP_WHITE_FILL:
|
2003-09-06 21:41:58 +08:00
|
|
|
gimp_rgba_set (&color, 1.0, 1.0, 1.0, GIMP_OPACITY_OPAQUE);
|
2001-07-08 06:49:01 +08:00
|
|
|
break;
|
|
|
|
|
2002-03-18 19:07:34 +08:00
|
|
|
case GIMP_TRANSPARENT_FILL:
|
2002-03-04 01:38:12 +08:00
|
|
|
gimp_rgba_set (&color, 0.0, 0.0, 0.0, GIMP_OPACITY_TRANSPARENT);
|
2001-07-08 06:49:01 +08:00
|
|
|
break;
|
|
|
|
|
2004-01-06 22:02:08 +08:00
|
|
|
case GIMP_PATTERN_FILL:
|
|
|
|
pattern = gimp_context_get_pattern (context);
|
|
|
|
break;
|
|
|
|
|
2003-09-06 21:41:58 +08:00
|
|
|
case GIMP_NO_FILL:
|
2001-07-08 06:49:01 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
default:
|
2004-05-12 16:13:33 +08:00
|
|
|
g_warning ("%s: unknown fill type %d", G_STRFUNC, fill_type);
|
2001-07-08 06:49:01 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-01-06 22:02:08 +08:00
|
|
|
gimp_drawable_fill (drawable, pattern ? NULL : &color, pattern);
|
1998-06-30 23:31:32 +08:00
|
|
|
}
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
gboolean
|
2003-09-02 21:43:26 +08:00
|
|
|
gimp_drawable_mask_bounds (GimpDrawable *drawable,
|
2004-07-14 18:31:59 +08:00
|
|
|
gint *x1,
|
|
|
|
gint *y1,
|
|
|
|
gint *x2,
|
|
|
|
gint *y2)
|
1998-06-30 23:31:32 +08:00
|
|
|
{
|
2003-10-07 02:26:06 +08:00
|
|
|
GimpItem *item;
|
2006-03-29 01:08:36 +08:00
|
|
|
GimpImage *image;
|
2003-10-07 02:26:06 +08:00
|
|
|
GimpChannel *selection;
|
2006-08-04 02:17:42 +08:00
|
|
|
gint tmp_x1, tmp_y1;
|
|
|
|
gint tmp_x2, tmp_y2;
|
|
|
|
gboolean retval;
|
1998-06-30 23:31:32 +08:00
|
|
|
|
2000-02-17 19:44:27 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
|
1998-06-30 23:31:32 +08:00
|
|
|
|
2004-11-08 07:17:39 +08:00
|
|
|
item = GIMP_ITEM (drawable);
|
|
|
|
|
2004-10-20 06:52:04 +08:00
|
|
|
g_return_val_if_fail (gimp_item_is_attached (item), FALSE);
|
1998-06-30 23:31:32 +08:00
|
|
|
|
2006-08-04 02:17:42 +08:00
|
|
|
image = gimp_item_get_image (item);
|
2006-03-29 01:08:36 +08:00
|
|
|
selection = gimp_image_get_mask (image);
|
2003-10-07 02:26:06 +08:00
|
|
|
|
|
|
|
if (GIMP_DRAWABLE (selection) != drawable &&
|
2006-08-04 02:17:42 +08:00
|
|
|
gimp_channel_bounds (selection, &tmp_x1, &tmp_y1, &tmp_x2, &tmp_y2))
|
1998-06-30 23:31:32 +08:00
|
|
|
{
|
2003-05-08 21:12:46 +08:00
|
|
|
gint off_x, off_y;
|
|
|
|
|
2003-05-08 22:06:03 +08:00
|
|
|
gimp_item_offsets (item, &off_x, &off_y);
|
2003-05-08 21:12:46 +08:00
|
|
|
|
2006-08-04 02:17:42 +08:00
|
|
|
tmp_x1 = CLAMP (tmp_x1 - off_x, 0, gimp_item_width (item));
|
|
|
|
tmp_y1 = CLAMP (tmp_y1 - off_y, 0, gimp_item_height (item));
|
|
|
|
tmp_x2 = CLAMP (tmp_x2 - off_x, 0, gimp_item_width (item));
|
|
|
|
tmp_y2 = CLAMP (tmp_y2 - off_y, 0, gimp_item_height (item));
|
|
|
|
|
|
|
|
retval = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tmp_x1 = 0;
|
|
|
|
tmp_y1 = 0;
|
|
|
|
tmp_x2 = gimp_item_width (item);
|
|
|
|
tmp_y2 = gimp_item_height (item);
|
2003-10-07 02:26:06 +08:00
|
|
|
|
2006-08-04 02:17:42 +08:00
|
|
|
retval = FALSE;
|
1998-06-30 23:31:32 +08:00
|
|
|
}
|
2003-10-07 02:26:06 +08:00
|
|
|
|
2006-08-04 02:17:42 +08:00
|
|
|
if (x1) *x1 = tmp_x1;
|
|
|
|
if (y1) *y1 = tmp_y1;
|
|
|
|
if (x2) *x2 = tmp_x2;
|
|
|
|
if (y2) *y2 = tmp_y2;
|
2004-11-10 16:23:05 +08:00
|
|
|
|
2006-08-04 02:17:42 +08:00
|
|
|
return retval;;
|
1998-06-30 23:31:32 +08:00
|
|
|
}
|
|
|
|
|
2004-10-20 06:52:04 +08:00
|
|
|
gboolean
|
|
|
|
gimp_drawable_mask_intersect (GimpDrawable *drawable,
|
|
|
|
gint *x,
|
|
|
|
gint *y,
|
|
|
|
gint *width,
|
|
|
|
gint *height)
|
|
|
|
{
|
|
|
|
GimpItem *item;
|
2006-03-29 01:08:36 +08:00
|
|
|
GimpImage *image;
|
2004-10-20 06:52:04 +08:00
|
|
|
GimpChannel *selection;
|
2006-08-04 02:17:42 +08:00
|
|
|
gint tmp_x, tmp_y;
|
|
|
|
gint tmp_width, tmp_height;
|
|
|
|
gboolean retval;
|
2004-10-20 06:52:04 +08:00
|
|
|
|
|
|
|
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
|
|
|
|
|
|
|
|
item = GIMP_ITEM (drawable);
|
|
|
|
|
|
|
|
g_return_val_if_fail (gimp_item_is_attached (item), FALSE);
|
|
|
|
|
2006-08-04 02:17:42 +08:00
|
|
|
image = gimp_item_get_image (item);
|
2006-03-29 01:08:36 +08:00
|
|
|
selection = gimp_image_get_mask (image);
|
2004-10-20 06:52:04 +08:00
|
|
|
|
|
|
|
if (GIMP_DRAWABLE (selection) != drawable &&
|
2006-08-04 02:17:42 +08:00
|
|
|
gimp_channel_bounds (selection, &tmp_x, &tmp_y, &tmp_width, &tmp_height))
|
2004-10-20 06:52:04 +08:00
|
|
|
{
|
|
|
|
gint off_x, off_y;
|
|
|
|
|
|
|
|
gimp_item_offsets (item, &off_x, &off_y);
|
|
|
|
|
2006-08-04 02:17:42 +08:00
|
|
|
retval = gimp_rectangle_intersect (tmp_x - off_x, tmp_y - off_y,
|
|
|
|
tmp_width - tmp_x, tmp_height - tmp_y,
|
|
|
|
0, 0,
|
|
|
|
gimp_item_width (item),
|
|
|
|
gimp_item_height (item),
|
|
|
|
&tmp_x, &tmp_y,
|
|
|
|
&tmp_width, &tmp_height);
|
2004-10-20 06:52:04 +08:00
|
|
|
}
|
2006-08-04 02:17:42 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
tmp_x = 0;
|
|
|
|
tmp_y = 0;
|
|
|
|
tmp_width = gimp_item_width (item);
|
|
|
|
tmp_height = gimp_item_height (item);
|
2004-10-20 06:52:04 +08:00
|
|
|
|
2006-08-04 02:17:42 +08:00
|
|
|
retval = TRUE;
|
|
|
|
}
|
2004-11-10 16:23:05 +08:00
|
|
|
|
2006-08-04 02:17:42 +08:00
|
|
|
if (x) *x = tmp_x;
|
|
|
|
if (y) *y = tmp_y;
|
|
|
|
if (width) *width = tmp_width;
|
|
|
|
if (height) *height = tmp_height;
|
|
|
|
|
|
|
|
return retval;
|
2004-10-20 06:52:04 +08:00
|
|
|
}
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
gboolean
|
2000-12-29 00:19:55 +08:00
|
|
|
gimp_drawable_has_alpha (const GimpDrawable *drawable)
|
1999-08-22 19:45:31 +08:00
|
|
|
{
|
2000-02-17 19:44:27 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
|
|
|
|
|
|
|
|
return drawable->has_alpha;
|
1999-08-22 19:45:31 +08:00
|
|
|
}
|
1998-10-14 10:54:02 +08:00
|
|
|
|
Actually use the enum types GimpImageType, GimpImageBaseType,
* app/*.[ch]: Actually use the enum types GimpImageType,
GimpImageBaseType, LayerModeEffects, PaintApplicationMode,
BrushApplicationMode, GimpFillType and ConvertPaletteType, instead
of just int or gint. Hopefully I catched most of the places
where these should be used.
Add an enum ConvolutionType, suffix the too general constants
NORMAL, ABSOLUTE and NEGATIVE with _CONVOL. Use NORMAL_MODE
instead of NORMAL in some places (this was what was intended). Fix
some minor gccisms.
* app/apptypes.h: New file. This file contains the above
enumeration types, and some opaque struct typedefs. It was
necessary to collect these in one header that doesn't include
other headers, because when we started using the above mentioned
types in the headers, all hell broke loose because of the
spaghetti-like cross-inclusion mess between headers.
(An example: Header A includes header B, which includes header C
which includes A. B uses a type defined in A. This is not defined,
because A hasn't defined it yet at the point where it includes B,
and A included from B of course is skipped as we already are
reading A.)
1999-08-19 07:41:39 +08:00
|
|
|
GimpImageType
|
2000-12-29 00:19:55 +08:00
|
|
|
gimp_drawable_type (const GimpDrawable *drawable)
|
1998-06-30 23:31:32 +08:00
|
|
|
{
|
2000-02-17 19:44:27 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);
|
|
|
|
|
|
|
|
return drawable->type;
|
1998-06-30 23:31:32 +08:00
|
|
|
}
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
GimpImageType
|
2000-12-29 00:19:55 +08:00
|
|
|
gimp_drawable_type_with_alpha (const GimpDrawable *drawable)
|
1998-06-30 23:31:32 +08:00
|
|
|
{
|
2000-02-17 19:44:27 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);
|
1999-08-22 19:45:31 +08:00
|
|
|
|
2001-12-14 23:30:31 +08:00
|
|
|
return GIMP_IMAGE_TYPE_WITH_ALPHA (gimp_drawable_type (drawable));
|
2001-12-13 07:48:18 +08:00
|
|
|
}
|
|
|
|
|
2004-01-15 03:41:00 +08:00
|
|
|
GimpImageType
|
|
|
|
gimp_drawable_type_without_alpha (const GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);
|
|
|
|
|
|
|
|
return GIMP_IMAGE_TYPE_WITHOUT_ALPHA (gimp_drawable_type (drawable));
|
|
|
|
}
|
|
|
|
|
2001-12-13 07:48:18 +08:00
|
|
|
gboolean
|
|
|
|
gimp_drawable_is_rgb (const GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
|
|
|
|
|
2001-12-14 23:30:31 +08:00
|
|
|
return GIMP_IMAGE_TYPE_IS_RGB (gimp_drawable_type (drawable));
|
2001-12-13 07:48:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
gimp_drawable_is_gray (const GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
|
|
|
|
|
2001-12-14 23:30:31 +08:00
|
|
|
return GIMP_IMAGE_TYPE_IS_GRAY (gimp_drawable_type (drawable));
|
2001-12-13 07:48:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
gimp_drawable_is_indexed (const GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
|
|
|
|
|
2001-12-14 23:30:31 +08:00
|
|
|
return GIMP_IMAGE_TYPE_IS_INDEXED (gimp_drawable_type (drawable));
|
2001-12-13 07:48:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
gint
|
|
|
|
gimp_drawable_bytes (const GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);
|
|
|
|
|
|
|
|
return drawable->bytes;
|
|
|
|
}
|
|
|
|
|
|
|
|
gint
|
|
|
|
gimp_drawable_bytes_with_alpha (const GimpDrawable *drawable)
|
|
|
|
{
|
2001-12-14 23:30:31 +08:00
|
|
|
GimpImageType type;
|
|
|
|
|
2001-12-13 07:48:18 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);
|
|
|
|
|
2001-12-14 23:30:31 +08:00
|
|
|
type = GIMP_IMAGE_TYPE_WITH_ALPHA (gimp_drawable_type (drawable));
|
2001-12-13 07:48:18 +08:00
|
|
|
|
2001-12-14 23:30:31 +08:00
|
|
|
return GIMP_IMAGE_TYPE_BYTES (type);
|
2001-12-13 07:48:18 +08:00
|
|
|
}
|
|
|
|
|
2004-01-15 03:41:00 +08:00
|
|
|
gint
|
|
|
|
gimp_drawable_bytes_without_alpha (const GimpDrawable *drawable)
|
|
|
|
{
|
|
|
|
GimpImageType type;
|
|
|
|
|
|
|
|
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);
|
|
|
|
|
|
|
|
type = GIMP_IMAGE_TYPE_WITHOUT_ALPHA (gimp_drawable_type (drawable));
|
|
|
|
|
|
|
|
return GIMP_IMAGE_TYPE_BYTES (type);
|
|
|
|
}
|
|
|
|
|
2004-04-13 21:54:54 +08:00
|
|
|
gboolean
|
|
|
|
gimp_drawable_has_floating_sel (const GimpDrawable *drawable)
|
|
|
|
{
|
2006-03-29 01:08:36 +08:00
|
|
|
GimpImage *image;
|
2004-04-13 21:54:54 +08:00
|
|
|
GimpLayer *floating_sel;
|
|
|
|
|
|
|
|
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
|
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
image = gimp_item_get_image (GIMP_ITEM (drawable));
|
2004-04-13 21:54:54 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
floating_sel = gimp_image_floating_sel (image);
|
2004-04-13 21:54:54 +08:00
|
|
|
|
|
|
|
return (floating_sel && floating_sel->fs.drawable == drawable);
|
|
|
|
}
|
|
|
|
|
2006-04-07 17:21:18 +08:00
|
|
|
const guchar *
|
2006-04-07 17:30:37 +08:00
|
|
|
gimp_drawable_get_colormap (const GimpDrawable *drawable)
|
2001-12-13 07:48:18 +08:00
|
|
|
{
|
2006-03-29 01:08:36 +08:00
|
|
|
GimpImage *image;
|
2001-12-13 07:48:18 +08:00
|
|
|
|
|
|
|
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
|
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
image = gimp_item_get_image (GIMP_ITEM (drawable));
|
2003-09-06 21:41:58 +08:00
|
|
|
|
2006-04-07 17:21:18 +08:00
|
|
|
return image ? gimp_image_get_colormap (image) : NULL;
|
2001-12-13 07:48:18 +08:00
|
|
|
}
|