540 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			540 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/* PIKA - Photo and Image Kooker Application
							 | 
						||
| 
								 | 
							
								 * a rebranding of The GNU Image Manipulation Program (created with heckimp)
							 | 
						||
| 
								 | 
							
								 * A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Original copyright, applying to most contents (license remains unchanged): 
							 | 
						||
| 
								 | 
							
								 * 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 <string.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <cairo.h>
							 | 
						||
| 
								 | 
							
								#include <gegl.h>
							 | 
						||
| 
								 | 
							
								#include <gdk-pixbuf/gdk-pixbuf.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "libpikabase/pikabase.h"
							 | 
						||
| 
								 | 
							
								#include "libpikacolor/pikacolor.h"
							 | 
						||
| 
								 | 
							
								#include "libpikaconfig/pikaconfig.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "core-types.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "pika-memsize.h"
							 | 
						||
| 
								 | 
							
								#include "pikadrawable.h"
							 | 
						||
| 
								 | 
							
								#include "pikagrid.h"
							 | 
						||
| 
								 | 
							
								#include "pikaimage.h"
							 | 
						||
| 
								 | 
							
								#include "pikaimage-color-profile.h"
							 | 
						||
| 
								 | 
							
								#include "pikaimage-colormap.h"
							 | 
						||
| 
								 | 
							
								#include "pikaimage-grid.h"
							 | 
						||
| 
								 | 
							
								#include "pikaimage-metadata.h"
							 | 
						||
| 
								 | 
							
								#include "pikaimage-private.h"
							 | 
						||
| 
								 | 
							
								#include "pikaimageundo.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								enum
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  PROP_0,
							 | 
						||
| 
								 | 
							
								  PROP_PREVIOUS_ORIGIN_X,
							 | 
						||
| 
								 | 
							
								  PROP_PREVIOUS_ORIGIN_Y,
							 | 
						||
| 
								 | 
							
								  PROP_PREVIOUS_WIDTH,
							 | 
						||
| 
								 | 
							
								  PROP_PREVIOUS_HEIGHT,
							 | 
						||
| 
								 | 
							
								  PROP_GRID,
							 | 
						||
| 
								 | 
							
								  PROP_PARASITE_NAME
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void     pika_image_undo_constructed  (GObject             *object);
							 | 
						||
| 
								 | 
							
								static void     pika_image_undo_set_property (GObject             *object,
							 | 
						||
| 
								 | 
							
								                                              guint                property_id,
							 | 
						||
| 
								 | 
							
								                                              const GValue        *value,
							 | 
						||
| 
								 | 
							
								                                              GParamSpec          *pspec);
							 | 
						||
| 
								 | 
							
								static void     pika_image_undo_get_property (GObject             *object,
							 | 
						||
| 
								 | 
							
								                                              guint                property_id,
							 | 
						||
| 
								 | 
							
								                                              GValue              *value,
							 | 
						||
| 
								 | 
							
								                                              GParamSpec          *pspec);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static gint64   pika_image_undo_get_memsize  (PikaObject          *object,
							 | 
						||
| 
								 | 
							
								                                              gint64              *gui_size);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void     pika_image_undo_pop          (PikaUndo            *undo,
							 | 
						||
| 
								 | 
							
								                                              PikaUndoMode         undo_mode,
							 | 
						||
| 
								 | 
							
								                                              PikaUndoAccumulator *accum);
							 | 
						||
| 
								 | 
							
								static void     pika_image_undo_free         (PikaUndo            *undo,
							 | 
						||
| 
								 | 
							
								                                              PikaUndoMode         undo_mode);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								G_DEFINE_TYPE (PikaImageUndo, pika_image_undo, PIKA_TYPE_UNDO)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define parent_class pika_image_undo_parent_class
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void
							 | 
						||
| 
								 | 
							
								pika_image_undo_class_init (PikaImageUndoClass *klass)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  GObjectClass    *object_class      = G_OBJECT_CLASS (klass);
							 | 
						||
| 
								 | 
							
								  PikaObjectClass *pika_object_class = PIKA_OBJECT_CLASS (klass);
							 | 
						||
| 
								 | 
							
								  PikaUndoClass   *undo_class        = PIKA_UNDO_CLASS (klass);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  object_class->constructed      = pika_image_undo_constructed;
							 | 
						||
| 
								 | 
							
								  object_class->set_property     = pika_image_undo_set_property;
							 | 
						||
| 
								 | 
							
								  object_class->get_property     = pika_image_undo_get_property;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  pika_object_class->get_memsize = pika_image_undo_get_memsize;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  undo_class->pop                = pika_image_undo_pop;
							 | 
						||
| 
								 | 
							
								  undo_class->free               = pika_image_undo_free;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  g_object_class_install_property (object_class, PROP_PREVIOUS_ORIGIN_X,
							 | 
						||
| 
								 | 
							
								                                   g_param_spec_int ("previous-origin-x",
							 | 
						||
| 
								 | 
							
								                                                     NULL, NULL,
							 | 
						||
| 
								 | 
							
								                                                     -PIKA_MAX_IMAGE_SIZE,
							 | 
						||
| 
								 | 
							
								                                                     PIKA_MAX_IMAGE_SIZE,
							 | 
						||
| 
								 | 
							
								                                                     0,
							 | 
						||
| 
								 | 
							
								                                                     PIKA_PARAM_READWRITE));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  g_object_class_install_property (object_class, PROP_PREVIOUS_ORIGIN_Y,
							 | 
						||
| 
								 | 
							
								                                   g_param_spec_int ("previous-origin-y",
							 | 
						||
| 
								 | 
							
								                                                     NULL, NULL,
							 | 
						||
| 
								 | 
							
								                                                     -PIKA_MAX_IMAGE_SIZE,
							 | 
						||
| 
								 | 
							
								                                                     PIKA_MAX_IMAGE_SIZE,
							 | 
						||
| 
								 | 
							
								                                                     0,
							 | 
						||
| 
								 | 
							
								                                                     PIKA_PARAM_READWRITE));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  g_object_class_install_property (object_class, PROP_PREVIOUS_WIDTH,
							 | 
						||
| 
								 | 
							
								                                   g_param_spec_int ("previous-width",
							 | 
						||
| 
								 | 
							
								                                                     NULL, NULL,
							 | 
						||
| 
								 | 
							
								                                                     -PIKA_MAX_IMAGE_SIZE,
							 | 
						||
| 
								 | 
							
								                                                     PIKA_MAX_IMAGE_SIZE,
							 | 
						||
| 
								 | 
							
								                                                     0,
							 | 
						||
| 
								 | 
							
								                                                     PIKA_PARAM_READWRITE));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  g_object_class_install_property (object_class, PROP_PREVIOUS_HEIGHT,
							 | 
						||
| 
								 | 
							
								                                   g_param_spec_int ("previous-height",
							 | 
						||
| 
								 | 
							
								                                                     NULL, NULL,
							 | 
						||
| 
								 | 
							
								                                                     -PIKA_MAX_IMAGE_SIZE,
							 | 
						||
| 
								 | 
							
								                                                     PIKA_MAX_IMAGE_SIZE,
							 | 
						||
| 
								 | 
							
								                                                     0,
							 | 
						||
| 
								 | 
							
								                                                     PIKA_PARAM_READWRITE));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  g_object_class_install_property (object_class, PROP_GRID,
							 | 
						||
| 
								 | 
							
								                                   g_param_spec_object ("grid", NULL, NULL,
							 | 
						||
| 
								 | 
							
								                                                        PIKA_TYPE_GRID,
							 | 
						||
| 
								 | 
							
								                                                        PIKA_PARAM_READWRITE |
							 | 
						||
| 
								 | 
							
								                                                        G_PARAM_CONSTRUCT_ONLY));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  g_object_class_install_property (object_class, PROP_PARASITE_NAME,
							 | 
						||
| 
								 | 
							
								                                   g_param_spec_string ("parasite-name",
							 | 
						||
| 
								 | 
							
								                                                        NULL, NULL,
							 | 
						||
| 
								 | 
							
								                                                        NULL,
							 | 
						||
| 
								 | 
							
								                                                        PIKA_PARAM_READWRITE |
							 | 
						||
| 
								 | 
							
								                                                        G_PARAM_CONSTRUCT_ONLY));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void
							 | 
						||
| 
								 | 
							
								pika_image_undo_init (PikaImageUndo *undo)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void
							 | 
						||
| 
								 | 
							
								pika_image_undo_constructed (GObject *object)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  PikaImageUndo *image_undo = PIKA_IMAGE_UNDO (object);
							 | 
						||
| 
								 | 
							
								  PikaImage     *image;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  G_OBJECT_CLASS (parent_class)->constructed (object);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  image = PIKA_UNDO (object)->image;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  switch (PIKA_UNDO (object)->undo_type)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    case PIKA_UNDO_IMAGE_TYPE:
							 | 
						||
| 
								 | 
							
								      image_undo->base_type = pika_image_get_base_type (image);
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case PIKA_UNDO_IMAGE_PRECISION:
							 | 
						||
| 
								 | 
							
								      image_undo->precision = pika_image_get_precision (image);
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case PIKA_UNDO_IMAGE_SIZE:
							 | 
						||
| 
								 | 
							
								      image_undo->width  = pika_image_get_width  (image);
							 | 
						||
| 
								 | 
							
								      image_undo->height = pika_image_get_height (image);
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case PIKA_UNDO_IMAGE_RESOLUTION:
							 | 
						||
| 
								 | 
							
								      pika_image_get_resolution (image,
							 | 
						||
| 
								 | 
							
								                                 &image_undo->xresolution,
							 | 
						||
| 
								 | 
							
								                                 &image_undo->yresolution);
							 | 
						||
| 
								 | 
							
								      image_undo->resolution_unit = pika_image_get_unit (image);
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case PIKA_UNDO_IMAGE_GRID:
							 | 
						||
| 
								 | 
							
								      pika_assert (PIKA_IS_GRID (image_undo->grid));
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case PIKA_UNDO_IMAGE_COLORMAP:
							 | 
						||
| 
								 | 
							
								      image_undo->num_colors = pika_image_get_colormap_size (image);
							 | 
						||
| 
								 | 
							
								      image_undo->colormap   = pika_image_get_colormap (image);
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case PIKA_UNDO_IMAGE_HIDDEN_PROFILE:
							 | 
						||
| 
								 | 
							
								      g_set_object (&image_undo->hidden_profile,
							 | 
						||
| 
								 | 
							
								                    _pika_image_get_hidden_profile (image));
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case PIKA_UNDO_IMAGE_METADATA:
							 | 
						||
| 
								 | 
							
								      image_undo->metadata =
							 | 
						||
| 
								 | 
							
								        pika_metadata_duplicate (pika_image_get_metadata (image));
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case PIKA_UNDO_PARASITE_ATTACH:
							 | 
						||
| 
								 | 
							
								    case PIKA_UNDO_PARASITE_REMOVE:
							 | 
						||
| 
								 | 
							
								      pika_assert (image_undo->parasite_name != NULL);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      image_undo->parasite = pika_parasite_copy
							 | 
						||
| 
								 | 
							
								        (pika_image_parasite_find (image, image_undo->parasite_name));
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    default:
							 | 
						||
| 
								 | 
							
								      g_return_if_reached ();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void
							 | 
						||
| 
								 | 
							
								pika_image_undo_set_property (GObject      *object,
							 | 
						||
| 
								 | 
							
								                              guint         property_id,
							 | 
						||
| 
								 | 
							
								                              const GValue *value,
							 | 
						||
| 
								 | 
							
								                              GParamSpec   *pspec)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  PikaImageUndo *image_undo = PIKA_IMAGE_UNDO (object);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  switch (property_id)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    case PROP_PREVIOUS_ORIGIN_X:
							 | 
						||
| 
								 | 
							
								      image_undo->previous_origin_x = g_value_get_int (value);
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								    case PROP_PREVIOUS_ORIGIN_Y:
							 | 
						||
| 
								 | 
							
								      image_undo->previous_origin_y = g_value_get_int (value);
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								    case PROP_PREVIOUS_WIDTH:
							 | 
						||
| 
								 | 
							
								      image_undo->previous_width = g_value_get_int (value);
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								    case PROP_PREVIOUS_HEIGHT:
							 | 
						||
| 
								 | 
							
								      image_undo->previous_height = g_value_get_int (value);
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								    case PROP_GRID:
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        PikaGrid *grid = g_value_get_object (value);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (grid)
							 | 
						||
| 
								 | 
							
								          image_undo->grid = pika_config_duplicate (PIKA_CONFIG (grid));
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								    case PROP_PARASITE_NAME:
							 | 
						||
| 
								 | 
							
								      image_undo->parasite_name = g_value_dup_string (value);
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    default:
							 | 
						||
| 
								 | 
							
								      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void
							 | 
						||
| 
								 | 
							
								pika_image_undo_get_property (GObject    *object,
							 | 
						||
| 
								 | 
							
								                              guint       property_id,
							 | 
						||
| 
								 | 
							
								                              GValue     *value,
							 | 
						||
| 
								 | 
							
								                              GParamSpec *pspec)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  PikaImageUndo *image_undo = PIKA_IMAGE_UNDO (object);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  switch (property_id)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    case PROP_PREVIOUS_ORIGIN_X:
							 | 
						||
| 
								 | 
							
								      g_value_set_int (value, image_undo->previous_origin_x);
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								    case PROP_PREVIOUS_ORIGIN_Y:
							 | 
						||
| 
								 | 
							
								      g_value_set_int (value, image_undo->previous_origin_y);
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								    case PROP_PREVIOUS_WIDTH:
							 | 
						||
| 
								 | 
							
								      g_value_set_int (value, image_undo->previous_width);
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								    case PROP_PREVIOUS_HEIGHT:
							 | 
						||
| 
								 | 
							
								      g_value_set_int (value, image_undo->previous_height);
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								    case PROP_GRID:
							 | 
						||
| 
								 | 
							
								      g_value_set_object (value, image_undo->grid);
							 | 
						||
| 
								 | 
							
								       break;
							 | 
						||
| 
								 | 
							
								    case PROP_PARASITE_NAME:
							 | 
						||
| 
								 | 
							
								      g_value_set_string (value, image_undo->parasite_name);
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    default:
							 | 
						||
| 
								 | 
							
								      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static gint64
							 | 
						||
| 
								 | 
							
								pika_image_undo_get_memsize (PikaObject *object,
							 | 
						||
| 
								 | 
							
								                             gint64     *gui_size)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  PikaImageUndo *image_undo = PIKA_IMAGE_UNDO (object);
							 | 
						||
| 
								 | 
							
								  gint64         memsize    = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (image_undo->colormap)
							 | 
						||
| 
								 | 
							
								    memsize += PIKA_IMAGE_COLORMAP_SIZE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (image_undo->metadata)
							 | 
						||
| 
								 | 
							
								    memsize += pika_g_object_get_memsize (G_OBJECT (image_undo->metadata));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  memsize += pika_object_get_memsize (PIKA_OBJECT (image_undo->grid),
							 | 
						||
| 
								 | 
							
								                                      gui_size);
							 | 
						||
| 
								 | 
							
								  memsize += pika_string_get_memsize (image_undo->parasite_name);
							 | 
						||
| 
								 | 
							
								  memsize += pika_parasite_get_memsize (image_undo->parasite, gui_size);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return memsize + PIKA_OBJECT_CLASS (parent_class)->get_memsize (object,
							 | 
						||
| 
								 | 
							
								                                                                  gui_size);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void
							 | 
						||
| 
								 | 
							
								pika_image_undo_pop (PikaUndo            *undo,
							 | 
						||
| 
								 | 
							
								                     PikaUndoMode         undo_mode,
							 | 
						||
| 
								 | 
							
								                     PikaUndoAccumulator *accum)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  PikaImageUndo    *image_undo = PIKA_IMAGE_UNDO (undo);
							 | 
						||
| 
								 | 
							
								  PikaImage        *image      = undo->image;
							 | 
						||
| 
								 | 
							
								  PikaImagePrivate *private    = PIKA_IMAGE_GET_PRIVATE (image);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  PIKA_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  switch (undo->undo_type)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    case PIKA_UNDO_IMAGE_TYPE:
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        PikaImageBaseType base_type;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        base_type = image_undo->base_type;
							 | 
						||
| 
								 | 
							
								        image_undo->base_type = pika_image_get_base_type (image);
							 | 
						||
| 
								 | 
							
								        g_object_set (image, "base-type", base_type, NULL);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        pika_image_colormap_changed (image, -1);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (image_undo->base_type != pika_image_get_base_type (image))
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								            if ((image_undo->base_type            == PIKA_GRAY) ||
							 | 
						||
| 
								 | 
							
								                (pika_image_get_base_type (image) == PIKA_GRAY))
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								                /* in case there was no profile undo, we need to emit
							 | 
						||
| 
								 | 
							
								                 * profile-changed anyway
							 | 
						||
| 
								 | 
							
								                 */
							 | 
						||
| 
								 | 
							
								                pika_color_managed_profile_changed (PIKA_COLOR_MANAGED (image));
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            accum->mode_changed = TRUE;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case PIKA_UNDO_IMAGE_PRECISION:
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        PikaPrecision precision;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        precision = image_undo->precision;
							 | 
						||
| 
								 | 
							
								        image_undo->precision = pika_image_get_precision (image);
							 | 
						||
| 
								 | 
							
								        g_object_set (image, "precision", precision, NULL);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (image_undo->precision != pika_image_get_precision (image))
							 | 
						||
| 
								 | 
							
								          accum->precision_changed = TRUE;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case PIKA_UNDO_IMAGE_SIZE:
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        gint width;
							 | 
						||
| 
								 | 
							
								        gint height;
							 | 
						||
| 
								 | 
							
								        gint previous_origin_x;
							 | 
						||
| 
								 | 
							
								        gint previous_origin_y;
							 | 
						||
| 
								 | 
							
								        gint previous_width;
							 | 
						||
| 
								 | 
							
								        gint previous_height;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        width             = image_undo->width;
							 | 
						||
| 
								 | 
							
								        height            = image_undo->height;
							 | 
						||
| 
								 | 
							
								        previous_origin_x = image_undo->previous_origin_x;
							 | 
						||
| 
								 | 
							
								        previous_origin_y = image_undo->previous_origin_y;
							 | 
						||
| 
								 | 
							
								        previous_width    = image_undo->previous_width;
							 | 
						||
| 
								 | 
							
								        previous_height   = image_undo->previous_height;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /* Transform to a redo */
							 | 
						||
| 
								 | 
							
								        image_undo->width             = pika_image_get_width  (image);
							 | 
						||
| 
								 | 
							
								        image_undo->height            = pika_image_get_height (image);
							 | 
						||
| 
								 | 
							
								        image_undo->previous_origin_x = -previous_origin_x;
							 | 
						||
| 
								 | 
							
								        image_undo->previous_origin_y = -previous_origin_y;
							 | 
						||
| 
								 | 
							
								        image_undo->previous_width    = width;
							 | 
						||
| 
								 | 
							
								        image_undo->previous_height   = height;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        g_object_set (image,
							 | 
						||
| 
								 | 
							
								                      "width",  width,
							 | 
						||
| 
								 | 
							
								                      "height", height,
							 | 
						||
| 
								 | 
							
								                      NULL);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        pika_drawable_invalidate_boundary
							 | 
						||
| 
								 | 
							
								          (PIKA_DRAWABLE (pika_image_get_mask (image)));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (pika_image_get_width  (image) != image_undo->width ||
							 | 
						||
| 
								 | 
							
								            pika_image_get_height (image) != image_undo->height)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								            accum->size_changed      = TRUE;
							 | 
						||
| 
								 | 
							
								            accum->previous_origin_x = previous_origin_x;
							 | 
						||
| 
								 | 
							
								            accum->previous_origin_y = previous_origin_y;
							 | 
						||
| 
								 | 
							
								            accum->previous_width    = previous_width;
							 | 
						||
| 
								 | 
							
								            accum->previous_height   = previous_height;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case PIKA_UNDO_IMAGE_RESOLUTION:
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        gdouble xres;
							 | 
						||
| 
								 | 
							
								        gdouble yres;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        pika_image_get_resolution (image, &xres, &yres);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (ABS (image_undo->xresolution - xres) >= 1e-5 ||
							 | 
						||
| 
								 | 
							
								            ABS (image_undo->yresolution - yres) >= 1e-5)
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								            private->xresolution = image_undo->xresolution;
							 | 
						||
| 
								 | 
							
								            private->yresolution = image_undo->yresolution;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            image_undo->xresolution = xres;
							 | 
						||
| 
								 | 
							
								            image_undo->yresolution = yres;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            accum->resolution_changed = TRUE;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (image_undo->resolution_unit != pika_image_get_unit (image))
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          PikaUnit unit;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          unit = pika_image_get_unit (image);
							 | 
						||
| 
								 | 
							
								          private->resolution_unit = image_undo->resolution_unit;
							 | 
						||
| 
								 | 
							
								          image_undo->resolution_unit = unit;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          accum->unit_changed = TRUE;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case PIKA_UNDO_IMAGE_GRID:
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        PikaGrid *grid;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        grid = pika_config_duplicate (PIKA_CONFIG (pika_image_get_grid (image)));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        pika_image_set_grid (image, image_undo->grid, FALSE);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        g_object_unref (image_undo->grid);
							 | 
						||
| 
								 | 
							
								        image_undo->grid = grid;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case PIKA_UNDO_IMAGE_COLORMAP:
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        guchar *colormap;
							 | 
						||
| 
								 | 
							
								        gint    num_colors;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        num_colors = pika_image_get_colormap_size (image);
							 | 
						||
| 
								 | 
							
								        colormap   = pika_image_get_colormap (image);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (image_undo->colormap)
							 | 
						||
| 
								 | 
							
								          pika_image_set_colormap (image,
							 | 
						||
| 
								 | 
							
								                                   image_undo->colormap, image_undo->num_colors,
							 | 
						||
| 
								 | 
							
								                                   FALSE);
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								          pika_image_unset_colormap (image, FALSE);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (image_undo->colormap)
							 | 
						||
| 
								 | 
							
								          g_free (image_undo->colormap);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        image_undo->num_colors = num_colors;
							 | 
						||
| 
								 | 
							
								        image_undo->colormap   = colormap;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case PIKA_UNDO_IMAGE_HIDDEN_PROFILE:
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        PikaColorProfile *hidden_profile = NULL;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        g_set_object (&hidden_profile, _pika_image_get_hidden_profile (image));
							 | 
						||
| 
								 | 
							
								        _pika_image_set_hidden_profile (image, image_undo->hidden_profile,
							 | 
						||
| 
								 | 
							
								                                        FALSE);
							 | 
						||
| 
								 | 
							
								        image_undo->hidden_profile = hidden_profile;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case PIKA_UNDO_IMAGE_METADATA:
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        PikaMetadata *metadata;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        metadata = pika_metadata_duplicate (pika_image_get_metadata (image));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        pika_image_set_metadata (image, image_undo->metadata, FALSE);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (image_undo->metadata)
							 | 
						||
| 
								 | 
							
								          g_object_unref (image_undo->metadata);
							 | 
						||
| 
								 | 
							
								        image_undo->metadata = metadata;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case PIKA_UNDO_PARASITE_ATTACH:
							 | 
						||
| 
								 | 
							
								    case PIKA_UNDO_PARASITE_REMOVE:
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        PikaParasite *parasite = image_undo->parasite;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        image_undo->parasite = pika_parasite_copy
							 | 
						||
| 
								 | 
							
								          (pika_image_parasite_find (image, image_undo->parasite_name));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (parasite)
							 | 
						||
| 
								 | 
							
								          pika_image_parasite_attach (image, parasite, FALSE);
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								          pika_image_parasite_detach (image, image_undo->parasite_name, FALSE);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (parasite)
							 | 
						||
| 
								 | 
							
								          pika_parasite_free (parasite);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    default:
							 | 
						||
| 
								 | 
							
								      g_return_if_reached ();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void
							 | 
						||
| 
								 | 
							
								pika_image_undo_free (PikaUndo     *undo,
							 | 
						||
| 
								 | 
							
								                      PikaUndoMode  undo_mode)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  PikaImageUndo *image_undo = PIKA_IMAGE_UNDO (undo);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  g_clear_object (&image_undo->grid);
							 | 
						||
| 
								 | 
							
								  g_clear_pointer (&image_undo->colormap, g_free);
							 | 
						||
| 
								 | 
							
								  g_clear_object (&image_undo->hidden_profile);
							 | 
						||
| 
								 | 
							
								  g_clear_object (&image_undo->metadata);
							 | 
						||
| 
								 | 
							
								  g_clear_pointer (&image_undo->parasite_name, g_free);
							 | 
						||
| 
								 | 
							
								  g_clear_pointer (&image_undo->parasite, pika_parasite_free);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  PIKA_UNDO_CLASS (parent_class)->free (undo, undo_mode);
							 | 
						||
| 
								 | 
							
								}
							 |