[gimp] app: make replacing a drawable's format use almost no undo memory



commit 248199e997666e8498da5fe052461fb615b20f9d
Author: Michael Natterer <mitch gimp org>
Date:   Tue Jul 24 12:20:17 2018 +0200

    app: make replacing a drawable's format use almost no undo memory
    
    Add gimp_drawable_set_format() as low-level part of
    gimp_layer_fix_format_space(), and add a special undo type for it that
    only remembers the format and not the entire drawable buffer, because
    all pixels stay the same.

 app/core/Makefile.am            |   2 +
 app/core/core-enums.c           |   2 +
 app/core/core-enums.h           |   1 +
 app/core/gimpdrawable.c         |  49 +++++++++++++
 app/core/gimpdrawable.h         |   5 ++
 app/core/gimpdrawablepropundo.c | 158 ++++++++++++++++++++++++++++++++++++++++
 app/core/gimpdrawablepropundo.h |  52 +++++++++++++
 app/core/gimpimage-undo-push.c  |  17 +++++
 app/core/gimpimage-undo-push.h  |   3 +
 app/core/gimplayer.c            |  22 +-----
 10 files changed, 290 insertions(+), 21 deletions(-)
---
diff --git a/app/core/Makefile.am b/app/core/Makefile.am
index ff45c4d5dd..9d2aa11b27 100644
--- a/app/core/Makefile.am
+++ b/app/core/Makefile.am
@@ -206,6 +206,8 @@ libappcore_a_sources = \
        gimpdrawablefilter.h                    \
        gimpdrawablemodundo.c                   \
        gimpdrawablemodundo.h                   \
+       gimpdrawablepropundo.c                  \
+       gimpdrawablepropundo.h                  \
        gimpdrawablestack.c                     \
        gimpdrawablestack.h                     \
        gimpdrawableundo.c                      \
diff --git a/app/core/core-enums.c b/app/core/core-enums.c
index 993670f3a2..3561f06531 100644
--- a/app/core/core-enums.c
+++ b/app/core/core-enums.c
@@ -1080,6 +1080,7 @@ gimp_undo_type_get_type (void)
     { GIMP_UNDO_SAMPLE_POINT, "GIMP_UNDO_SAMPLE_POINT", "sample-point" },
     { GIMP_UNDO_DRAWABLE, "GIMP_UNDO_DRAWABLE", "drawable" },
     { GIMP_UNDO_DRAWABLE_MOD, "GIMP_UNDO_DRAWABLE_MOD", "drawable-mod" },
+    { GIMP_UNDO_DRAWABLE_FORMAT, "GIMP_UNDO_DRAWABLE_FORMAT", "drawable-format" },
     { GIMP_UNDO_MASK, "GIMP_UNDO_MASK", "mask" },
     { GIMP_UNDO_ITEM_REORDER, "GIMP_UNDO_ITEM_REORDER", "item-reorder" },
     { GIMP_UNDO_ITEM_RENAME, "GIMP_UNDO_ITEM_RENAME", "item-rename" },
@@ -1178,6 +1179,7 @@ gimp_undo_type_get_type (void)
     { GIMP_UNDO_SAMPLE_POINT, NC_("undo-type", "Sample Point"), NULL },
     { GIMP_UNDO_DRAWABLE, NC_("undo-type", "Layer/Channel"), NULL },
     { GIMP_UNDO_DRAWABLE_MOD, NC_("undo-type", "Layer/Channel modification"), NULL },
+    { GIMP_UNDO_DRAWABLE_FORMAT, NC_("undo-type", "Layer/Channel format"), NULL },
     { GIMP_UNDO_MASK, NC_("undo-type", "Selection mask"), NULL },
     { GIMP_UNDO_ITEM_REORDER, NC_("undo-type", "Reorder item"), NULL },
     { GIMP_UNDO_ITEM_RENAME, NC_("undo-type", "Rename item"), NULL },
diff --git a/app/core/core-enums.h b/app/core/core-enums.h
index 90a690643a..8a53014198 100644
--- a/app/core/core-enums.h
+++ b/app/core/core-enums.h
@@ -515,6 +515,7 @@ typedef enum /*< pdb-skip >*/
   GIMP_UNDO_SAMPLE_POINT,                /*< desc="Sample Point"                   >*/
   GIMP_UNDO_DRAWABLE,                    /*< desc="Layer/Channel"                  >*/
   GIMP_UNDO_DRAWABLE_MOD,                /*< desc="Layer/Channel modification"     >*/
+  GIMP_UNDO_DRAWABLE_FORMAT,             /*< desc="Layer/Channel format"           >*/
   GIMP_UNDO_MASK,                        /*< desc="Selection mask"                 >*/
   GIMP_UNDO_ITEM_REORDER,                /*< desc="Reorder item"                   >*/
   GIMP_UNDO_ITEM_RENAME,                 /*< desc="Rename item"                    >*/
diff --git a/app/core/gimpdrawable.c b/app/core/gimpdrawable.c
index ce8302e24e..e0c21214d3 100644
--- a/app/core/gimpdrawable.c
+++ b/app/core/gimpdrawable.c
@@ -1314,6 +1314,55 @@ gimp_drawable_steal_buffer (GimpDrawable *drawable,
   g_object_unref (buffer);
 }
 
+void
+gimp_drawable_set_format (GimpDrawable *drawable,
+                          const Babl   *format,
+                          gboolean      copy_buffer,
+                          gboolean      push_undo)
+{
+  GimpItem   *item;
+  GeglBuffer *buffer;
+
+  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
+  g_return_if_fail (format != NULL);
+  g_return_if_fail (format != gimp_drawable_get_format (drawable));
+  g_return_if_fail (gimp_babl_format_get_base_type (format) ==
+                    gimp_drawable_get_base_type (drawable));
+  g_return_if_fail (gimp_babl_format_get_component_type (format) ==
+                    gimp_drawable_get_component_type (drawable));
+  g_return_if_fail (babl_format_has_alpha (format) ==
+                    gimp_drawable_has_alpha (drawable));
+  g_return_if_fail (push_undo == FALSE || copy_buffer == TRUE);
+
+  item = GIMP_ITEM (drawable);
+
+  if (! gimp_item_is_attached (item))
+    push_undo = FALSE;
+
+  if (push_undo)
+    gimp_image_undo_push_drawable_format (gimp_item_get_image (item),
+                                          NULL, drawable);
+
+  buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
+                                            gimp_item_get_width  (item),
+                                            gimp_item_get_height (item)),
+                            format);
+
+  if (copy_buffer)
+    {
+      gegl_buffer_set_format (buffer, gimp_drawable_get_format (drawable));
+
+      gimp_gegl_buffer_copy (gimp_drawable_get_buffer (drawable),
+                             NULL, GEGL_ABYSS_NONE,
+                             buffer, NULL);
+
+      gegl_buffer_set_format (buffer, NULL);
+    }
+
+  gimp_drawable_set_buffer (drawable, FALSE, NULL, buffer);
+  g_object_unref (buffer);
+}
+
 GeglNode *
 gimp_drawable_get_source_node (GimpDrawable *drawable)
 {
diff --git a/app/core/gimpdrawable.h b/app/core/gimpdrawable.h
index 659139ff1b..0ebd5ca875 100644
--- a/app/core/gimpdrawable.h
+++ b/app/core/gimpdrawable.h
@@ -192,6 +192,11 @@ void            gimp_drawable_set_buffer_full    (GimpDrawable       *drawable,
 void            gimp_drawable_steal_buffer       (GimpDrawable       *drawable,
                                                   GimpDrawable       *src_drawable);
 
+void            gimp_drawable_set_format         (GimpDrawable       *drawable,
+                                                  const Babl         *format,
+                                                  gboolean            copy_buffer,
+                                                  gboolean            push_undo);
+
 GeglNode      * gimp_drawable_get_source_node    (GimpDrawable       *drawable);
 GeglNode      * gimp_drawable_get_mode_node      (GimpDrawable       *drawable);
 
diff --git a/app/core/gimpdrawablepropundo.c b/app/core/gimpdrawablepropundo.c
new file mode 100644
index 0000000000..159892fce3
--- /dev/null
+++ b/app/core/gimpdrawablepropundo.c
@@ -0,0 +1,158 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 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, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gegl.h>
+
+#include "core-types.h"
+
+#include "gegl/gimp-gegl-utils.h"
+
+#include "gimp-memsize.h"
+#include "gimpimage.h"
+#include "gimpdrawable.h"
+#include "gimpdrawablepropundo.h"
+
+
+enum
+{
+  PROP_0
+};
+
+
+static void   gimp_drawable_prop_undo_constructed  (GObject             *object);
+static void   gimp_drawable_prop_undo_set_property (GObject             *object,
+                                                    guint                property_id,
+                                                    const GValue        *value,
+                                                    GParamSpec          *pspec);
+static void   gimp_drawable_prop_undo_get_property (GObject             *object,
+                                                    guint                property_id,
+                                                    GValue              *value,
+                                                    GParamSpec          *pspec);
+
+static void   gimp_drawable_prop_undo_pop          (GimpUndo            *undo,
+                                                    GimpUndoMode         undo_mode,
+                                                    GimpUndoAccumulator *accum);
+
+
+G_DEFINE_TYPE (GimpDrawablePropUndo, gimp_drawable_prop_undo,
+               GIMP_TYPE_ITEM_UNDO)
+
+#define parent_class gimp_drawable_prop_undo_parent_class
+
+
+static void
+gimp_drawable_prop_undo_class_init (GimpDrawablePropUndoClass *klass)
+{
+  GObjectClass  *object_class = G_OBJECT_CLASS (klass);
+  GimpUndoClass *undo_class   = GIMP_UNDO_CLASS (klass);
+
+  object_class->constructed  = gimp_drawable_prop_undo_constructed;
+  object_class->set_property = gimp_drawable_prop_undo_set_property;
+  object_class->get_property = gimp_drawable_prop_undo_get_property;
+
+  undo_class->pop            = gimp_drawable_prop_undo_pop;
+}
+
+static void
+gimp_drawable_prop_undo_init (GimpDrawablePropUndo *undo)
+{
+}
+
+static void
+gimp_drawable_prop_undo_constructed (GObject *object)
+{
+  GimpDrawablePropUndo *drawable_prop_undo = GIMP_DRAWABLE_PROP_UNDO (object);
+  GimpDrawable         *drawable;
+
+  G_OBJECT_CLASS (parent_class)->constructed (object);
+
+  gimp_assert (GIMP_IS_DRAWABLE (GIMP_ITEM_UNDO (object)->item));
+
+  drawable = GIMP_DRAWABLE (GIMP_ITEM_UNDO (object)->item);
+
+  switch (GIMP_UNDO (object)->undo_type)
+    {
+    case GIMP_UNDO_DRAWABLE_FORMAT:
+      drawable_prop_undo->format = gimp_drawable_get_format (drawable);
+      break;
+
+    default:
+      g_return_if_reached ();
+   }
+}
+
+static void
+gimp_drawable_prop_undo_set_property (GObject      *object,
+                                      guint         property_id,
+                                      const GValue *value,
+                                      GParamSpec   *pspec)
+{
+  switch (property_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gimp_drawable_prop_undo_get_property (GObject    *object,
+                                      guint       property_id,
+                                      GValue     *value,
+                                      GParamSpec *pspec)
+{
+  switch (property_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gimp_drawable_prop_undo_pop (GimpUndo            *undo,
+                             GimpUndoMode         undo_mode,
+                             GimpUndoAccumulator *accum)
+{
+  GimpDrawablePropUndo *drawable_prop_undo = GIMP_DRAWABLE_PROP_UNDO (undo);
+  GimpDrawable         *drawable;
+
+  drawable = GIMP_DRAWABLE (GIMP_ITEM_UNDO (undo)->item);
+
+  GIMP_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum);
+
+  switch (undo->undo_type)
+    {
+    case GIMP_UNDO_DRAWABLE_FORMAT:
+      {
+        const Babl *format = gimp_drawable_get_format (drawable);
+
+        gimp_drawable_set_format (drawable,
+                                  drawable_prop_undo->format,
+                                  TRUE, FALSE);
+
+        drawable_prop_undo->format = format;
+      }
+      break;
+
+    default:
+      g_return_if_reached ();
+    }
+}
diff --git a/app/core/gimpdrawablepropundo.h b/app/core/gimpdrawablepropundo.h
new file mode 100644
index 0000000000..4cb9fb56bf
--- /dev/null
+++ b/app/core/gimpdrawablepropundo.h
@@ -0,0 +1,52 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 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, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_DRAWABLE_PROP_UNDO_H__
+#define __GIMP_DRAWABLE_PROP_UNDO_H__
+
+
+#include "gimpitemundo.h"
+
+
+#define GIMP_TYPE_DRAWABLE_PROP_UNDO            (gimp_drawable_prop_undo_get_type ())
+#define GIMP_DRAWABLE_PROP_UNDO(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
GIMP_TYPE_DRAWABLE_PROP_UNDO, GimpDrawablePropUndo))
+#define GIMP_DRAWABLE_PROP_UNDO_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), 
GIMP_TYPE_DRAWABLE_PROP_UNDO, GimpDrawablePropUndoClass))
+#define GIMP_IS_DRAWABLE_PROP_UNDO(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
GIMP_TYPE_DRAWABLE_PROP_UNDO))
+#define GIMP_IS_DRAWABLE_PROP_UNDO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), 
GIMP_TYPE_DRAWABLE_PROP_UNDO))
+#define GIMP_DRAWABLE_PROP_UNDO_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), 
GIMP_TYPE_DRAWABLE_PROP_UNDO, GimpDrawablePropUndoClass))
+
+
+typedef struct _GimpDrawablePropUndo      GimpDrawablePropUndo;
+typedef struct _GimpDrawablePropUndoClass GimpDrawablePropUndoClass;
+
+struct _GimpDrawablePropUndo
+{
+  GimpItemUndo  parent_instance;
+
+  const Babl   *format;
+};
+
+struct _GimpDrawablePropUndoClass
+{
+  GimpItemUndoClass  parent_class;
+};
+
+
+GType   gimp_drawable_prop_undo_get_type (void) G_GNUC_CONST;
+
+
+#endif /* __GIMP_DRAWABLE_PROP_UNDO_H__ */
diff --git a/app/core/gimpimage-undo-push.c b/app/core/gimpimage-undo-push.c
index b96c4b45b8..18880586de 100644
--- a/app/core/gimpimage-undo-push.c
+++ b/app/core/gimpimage-undo-push.c
@@ -28,6 +28,7 @@
 #include "gimpchannelpropundo.h"
 #include "gimpchannelundo.h"
 #include "gimpdrawablemodundo.h"
+#include "gimpdrawablepropundo.h"
 #include "gimpdrawableundo.h"
 #include "gimpfloatingselectionundo.h"
 #include "gimpgrid.h"
@@ -288,6 +289,22 @@ gimp_image_undo_push_drawable_mod (GimpImage    *image,
                                NULL);
 }
 
+GimpUndo *
+gimp_image_undo_push_drawable_format (GimpImage    *image,
+                                      const gchar  *undo_desc,
+                                      GimpDrawable *drawable)
+{
+  g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
+  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
+  g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), NULL);
+
+  return gimp_image_undo_push (image, GIMP_TYPE_DRAWABLE_PROP_UNDO,
+                               GIMP_UNDO_DRAWABLE_FORMAT, undo_desc,
+                               GIMP_DIRTY_ITEM | GIMP_DIRTY_DRAWABLE,
+                               "item", drawable,
+                               NULL);
+}
+
 
 /****************/
 /*  Mask Undos  */
diff --git a/app/core/gimpimage-undo-push.h b/app/core/gimpimage-undo-push.h
index f06fcd873e..0cbd19a357 100644
--- a/app/core/gimpimage-undo-push.h
+++ b/app/core/gimpimage-undo-push.h
@@ -72,6 +72,9 @@ GimpUndo * gimp_image_undo_push_drawable_mod        (GimpImage     *image,
                                                      const gchar   *undo_desc,
                                                      GimpDrawable  *drawable,
                                                      gboolean       copy_buffer);
+GimpUndo * gimp_image_undo_push_drawable_format     (GimpImage     *image,
+                                                     const gchar   *undo_desc,
+                                                     GimpDrawable  *drawable);
 
 
 /*  mask undos  */
diff --git a/app/core/gimplayer.c b/app/core/gimplayer.c
index b1fdd4d361..616c9ca2d3 100644
--- a/app/core/gimplayer.c
+++ b/app/core/gimplayer.c
@@ -1807,27 +1807,7 @@ gimp_layer_fix_format_space (GimpLayer *layer,
 
   if (format != gimp_drawable_get_format (drawable))
     {
-      GeglBuffer *buffer;
-
-      buffer = gegl_buffer_new
-        (GEGL_RECTANGLE (0, 0,
-                         gimp_item_get_width  (GIMP_ITEM (layer)),
-                         gimp_item_get_height (GIMP_ITEM (layer))),
-         format);
-
-      if (copy_buffer)
-        {
-          gegl_buffer_set_format (buffer, gimp_drawable_get_format (drawable));
-
-          gimp_gegl_buffer_copy (gimp_drawable_get_buffer (drawable),
-                                 NULL, GEGL_ABYSS_NONE,
-                                 buffer, NULL);
-
-          gegl_buffer_set_format (buffer, NULL);
-        }
-
-      gimp_drawable_set_buffer (drawable, push_undo, NULL, buffer);
-      g_object_unref (buffer);
+      gimp_drawable_set_format (drawable, format, copy_buffer, push_undo);
     }
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]