From c24ff243110d75cde2e90052e6b1b57711d156e4 Mon Sep 17 00:00:00 2001 From: Michael Natterer Date: Sat, 28 Apr 2012 16:14:52 +0200 Subject: [PATCH] app: when converting an image's precision, don't forget the selection mask --- app/core/gimpimage-convert.c | 19 ++++++ app/core/gimpimage-undo-push.c | 25 +++++++- app/core/gimpimage-undo-push.h | 5 +- app/core/gimpmaskundo.c | 106 +++++++++++++++++++++++++++++---- app/core/gimpmaskundo.h | 3 + 5 files changed, 143 insertions(+), 15 deletions(-) diff --git a/app/core/gimpimage-convert.c b/app/core/gimpimage-convert.c index 3617e3f241..8e48f21cff 100644 --- a/app/core/gimpimage-convert.c +++ b/app/core/gimpimage-convert.c @@ -1158,6 +1158,25 @@ gimp_image_convert_precision (GimpImage *image, (gdouble) nth_drawable / (gdouble) n_drawables); } + /* convert the selection mask */ + { + GimpChannel *mask = gimp_image_get_mask (image); + GeglBuffer *buffer; + + gimp_image_undo_push_mask_precision (image, NULL, mask); + + buffer = gimp_gegl_buffer_new (GEGL_RECTANGLE (0, 0, + gimp_image_get_width (image), + gimp_image_get_height (image)), + gimp_image_get_mask_format (image)); + + gegl_buffer_copy (gimp_drawable_get_buffer (GIMP_DRAWABLE (mask)), NULL, + buffer, NULL); + + gimp_drawable_set_buffer (GIMP_DRAWABLE (mask), FALSE, NULL, buffer); + g_object_unref (buffer); + } + gimp_image_undo_group_end (image); gimp_image_precision_changed (image); diff --git a/app/core/gimpimage-undo-push.c b/app/core/gimpimage-undo-push.c index 7db3f4dab0..a7aa422c92 100644 --- a/app/core/gimpimage-undo-push.c +++ b/app/core/gimpimage-undo-push.c @@ -264,9 +264,9 @@ gimp_image_undo_push_drawable_mod (GimpImage *image, } -/***************/ -/* Mask Undo */ -/***************/ +/****************/ +/* Mask Undos */ +/****************/ GimpUndo * gimp_image_undo_push_mask (GimpImage *image, @@ -286,6 +286,25 @@ gimp_image_undo_push_mask (GimpImage *image, NULL); } +GimpUndo * +gimp_image_undo_push_mask_precision (GimpImage *image, + const gchar *undo_desc, + GimpChannel *mask) +{ + g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); + g_return_val_if_fail (GIMP_IS_CHANNEL (mask), NULL); + g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (mask)), NULL); + + return gimp_image_undo_push (image, GIMP_TYPE_MASK_UNDO, + GIMP_UNDO_MASK, undo_desc, + GIMP_IS_SELECTION (mask) ? + GIMP_DIRTY_SELECTION : + GIMP_DIRTY_ITEM | GIMP_DIRTY_DRAWABLE, + "item", mask, + "convert-precision", TRUE, + NULL); +} + /****************/ /* Item Undos */ diff --git a/app/core/gimpimage-undo-push.h b/app/core/gimpimage-undo-push.h index 41e93c8f34..d1c56cad87 100644 --- a/app/core/gimpimage-undo-push.h +++ b/app/core/gimpimage-undo-push.h @@ -70,11 +70,14 @@ GimpUndo * gimp_image_undo_push_drawable_mod (GimpImage *image, gboolean copy_buffer); -/* mask undo */ +/* mask undos */ GimpUndo * gimp_image_undo_push_mask (GimpImage *image, const gchar *undo_desc, GimpChannel *mask); +GimpUndo * gimp_image_undo_push_mask_precision (GimpImage *image, + const gchar *undo_desc, + GimpChannel *mask); /* item undos */ diff --git a/app/core/gimpmaskundo.c b/app/core/gimpmaskundo.c index 24962e1357..f673240274 100644 --- a/app/core/gimpmaskundo.c +++ b/app/core/gimpmaskundo.c @@ -28,16 +28,31 @@ #include "gimpmaskundo.h" -static void gimp_mask_undo_constructed (GObject *object); +enum +{ + PROP_0, + PROP_CONVERT_PRECISION +}; -static gint64 gimp_mask_undo_get_memsize (GimpObject *object, - gint64 *gui_size); -static void gimp_mask_undo_pop (GimpUndo *undo, - GimpUndoMode undo_mode, - GimpUndoAccumulator *accum); -static void gimp_mask_undo_free (GimpUndo *undo, - GimpUndoMode undo_mode); +static void gimp_mask_undo_constructed (GObject *object); +static void gimp_mask_undo_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_mask_undo_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +static gint64 gimp_mask_undo_get_memsize (GimpObject *object, + gint64 *gui_size); + +static void gimp_mask_undo_pop (GimpUndo *undo, + GimpUndoMode undo_mode, + GimpUndoAccumulator *accum); +static void gimp_mask_undo_free (GimpUndo *undo, + GimpUndoMode undo_mode); G_DEFINE_TYPE (GimpMaskUndo, gimp_mask_undo, GIMP_TYPE_ITEM_UNDO) @@ -53,11 +68,20 @@ gimp_mask_undo_class_init (GimpMaskUndoClass *klass) GimpUndoClass *undo_class = GIMP_UNDO_CLASS (klass); object_class->constructed = gimp_mask_undo_constructed; + object_class->set_property = gimp_mask_undo_set_property; + object_class->get_property = gimp_mask_undo_get_property; gimp_object_class->get_memsize = gimp_mask_undo_get_memsize; undo_class->pop = gimp_mask_undo_pop; undo_class->free = gimp_mask_undo_free; + + g_object_class_install_property (object_class, PROP_CONVERT_PRECISION, + g_param_spec_boolean ("convert-precision", + NULL, NULL, + FALSE, + GIMP_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); } static void @@ -70,6 +94,7 @@ gimp_mask_undo_constructed (GObject *object) { GimpMaskUndo *mask_undo = GIMP_MASK_UNDO (object); GimpChannel *channel; + GimpDrawable *drawable; gint x1, y1, x2, y2; if (G_OBJECT_CLASS (parent_class)->constructed) @@ -77,12 +102,11 @@ gimp_mask_undo_constructed (GObject *object) g_assert (GIMP_IS_CHANNEL (GIMP_ITEM_UNDO (object)->item)); - channel = GIMP_CHANNEL (GIMP_ITEM_UNDO (object)->item); + channel = GIMP_CHANNEL (GIMP_ITEM_UNDO (object)->item); + drawable = GIMP_DRAWABLE (channel); if (gimp_channel_bounds (channel, &x1, &y1, &x2, &y2)) { - GimpDrawable *drawable = GIMP_DRAWABLE (channel); - mask_undo->buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, x2 - x1, y2 - y1), gimp_drawable_get_format (drawable)); @@ -95,6 +119,48 @@ gimp_mask_undo_constructed (GObject *object) mask_undo->x = x1; mask_undo->y = y1; } + + mask_undo->format = gimp_drawable_get_format (drawable); +} + +static void +gimp_mask_undo_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpMaskUndo *mask_undo = GIMP_MASK_UNDO (object); + + switch (property_id) + { + case PROP_CONVERT_PRECISION: + mask_undo->convert_precision = g_value_get_boolean (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_mask_undo_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GimpMaskUndo *mask_undo = GIMP_MASK_UNDO (object); + + switch (property_id) + { + case PROP_CONVERT_PRECISION: + g_value_set_boolean (value, mask_undo->convert_precision); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } } static gint64 @@ -119,6 +185,7 @@ gimp_mask_undo_pop (GimpUndo *undo, GimpChannel *channel = GIMP_CHANNEL (GIMP_ITEM_UNDO (undo)->item); GimpDrawable *drawable = GIMP_DRAWABLE (channel); GeglBuffer *new_buffer; + const Babl *format; gint x1, y1, x2, y2; gint width = 0; gint height = 0; @@ -143,6 +210,22 @@ gimp_mask_undo_pop (GimpUndo *undo, new_buffer = NULL; } + format = gimp_drawable_get_format (drawable); + + if (mask_undo->convert_precision) + { + GeglBuffer *buffer; + gint width = gimp_item_get_width (GIMP_ITEM (channel)); + gint height = gimp_item_get_height (GIMP_ITEM (channel)); + + buffer = gimp_gegl_buffer_new (GEGL_RECTANGLE (0, 0, width, height), + mask_undo->format); + gegl_buffer_clear (buffer, NULL); + + gimp_drawable_set_buffer (drawable, FALSE, NULL, buffer); + g_object_unref (buffer); + } + if (mask_undo->buffer) { width = gegl_buffer_get_width (mask_undo->buffer); @@ -183,6 +266,7 @@ gimp_mask_undo_pop (GimpUndo *undo, mask_undo->buffer = new_buffer; mask_undo->x = x1; mask_undo->y = y1; + mask_undo->format = format; gimp_drawable_update (GIMP_DRAWABLE (channel), 0, 0, diff --git a/app/core/gimpmaskundo.h b/app/core/gimpmaskundo.h index 0161cff6ba..ae39550158 100644 --- a/app/core/gimpmaskundo.h +++ b/app/core/gimpmaskundo.h @@ -36,9 +36,12 @@ struct _GimpMaskUndo { GimpItemUndo parent_instance; + gboolean convert_precision; + GeglBuffer *buffer; gint x; gint y; + const Babl *format; }; struct _GimpMaskUndoClass