gimptextundo.c 9.29 KB
Newer Older
1
/* GIMP - The GNU Image Manipulation Program
2 3
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
4
 * This program is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 3 of the License, or
7 8 9 10 11 12 13 14
 * (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
15
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
16 17 18 19
 */

#include "config.h"

20
#include <gdk-pixbuf/gdk-pixbuf.h>
21
#include <gegl.h>
22

23
#include "libgimpconfig/gimpconfig.h"
24

25
#include "text-types.h"
26

27 28
#include "gegl/gimp-babl.h"

29
#include "core/gimp-memsize.h"
30 31 32 33 34 35 36 37
#include "core/gimpitem.h"
#include "core/gimpitemundo.h"

#include "gimptext.h"
#include "gimptextlayer.h"
#include "gimptextundo.h"


38 39 40 41 42 43 44
enum
{
  PROP_0,
  PROP_PARAM
};


45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
static void     gimp_text_undo_constructed  (GObject             *object);
static void     gimp_text_undo_set_property (GObject             *object,
                                             guint                property_id,
                                             const GValue        *value,
                                             GParamSpec          *pspec);
static void     gimp_text_undo_get_property (GObject             *object,
                                             guint                property_id,
                                             GValue              *value,
                                             GParamSpec          *pspec);

static gint64   gimp_text_undo_get_memsize  (GimpObject          *object,
                                             gint64              *gui_size);

static void     gimp_text_undo_pop          (GimpUndo            *undo,
                                             GimpUndoMode         undo_mode,
                                             GimpUndoAccumulator *accum);
static void     gimp_text_undo_free         (GimpUndo            *undo,
                                             GimpUndoMode         undo_mode);
63 64


65
G_DEFINE_TYPE (GimpTextUndo, gimp_text_undo, GIMP_TYPE_ITEM_UNDO)
66

67
#define parent_class gimp_text_undo_parent_class
68 69 70 71 72


static void
gimp_text_undo_class_init (GimpTextUndoClass *klass)
{
73 74 75
  GObjectClass    *object_class      = G_OBJECT_CLASS (klass);
  GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);
  GimpUndoClass   *undo_class        = GIMP_UNDO_CLASS (klass);
76

77
  object_class->constructed      = gimp_text_undo_constructed;
78 79 80 81 82 83 84 85 86 87 88
  object_class->set_property     = gimp_text_undo_set_property;
  object_class->get_property     = gimp_text_undo_get_property;

  gimp_object_class->get_memsize = gimp_text_undo_get_memsize;

  undo_class->pop                = gimp_text_undo_pop;
  undo_class->free               = gimp_text_undo_free;

  g_object_class_install_property (object_class, PROP_PARAM,
                                   g_param_spec_param ("param", NULL, NULL,
                                                       G_TYPE_PARAM,
89
                                                       GIMP_PARAM_READWRITE |
90 91 92
                                                       G_PARAM_CONSTRUCT_ONLY));
}

93 94 95 96 97
static void
gimp_text_undo_init (GimpTextUndo *undo)
{
}

98 99
static void
gimp_text_undo_constructed (GObject *object)
100
{
101
  GimpTextUndo  *text_undo = GIMP_TEXT_UNDO (object);
102 103
  GimpTextLayer *layer;

104
  G_OBJECT_CLASS (parent_class)->constructed (object);
105

106
  gimp_assert (GIMP_IS_TEXT_LAYER (GIMP_ITEM_UNDO (text_undo)->item));
107 108 109

  layer = GIMP_TEXT_LAYER (GIMP_ITEM_UNDO (text_undo)->item);

110
  switch (GIMP_UNDO (object)->undo_type)
111
    {
112 113 114
    case GIMP_UNDO_TEXT_LAYER:
      if (text_undo->pspec)
        {
115
          gimp_assert (text_undo->pspec->owner_type == GIMP_TYPE_TEXT);
116

117
          text_undo->value = g_slice_new0 (GValue);
118 119 120 121 122 123 124 125 126 127

          g_value_init (text_undo->value, text_undo->pspec->value_type);
          g_object_get_property (G_OBJECT (layer->text),
                                 text_undo->pspec->name, text_undo->value);
        }
      else if (layer->text)
        {
          text_undo->text = gimp_config_duplicate (GIMP_CONFIG (layer->text));
        }
      break;
128

129 130 131
    case GIMP_UNDO_TEXT_LAYER_MODIFIED:
      text_undo->modified = layer->modified;
      break;
132

133 134 135 136
    case GIMP_UNDO_TEXT_LAYER_CONVERT:
      text_undo->format = gimp_drawable_get_format (GIMP_DRAWABLE (layer));
      break;

137
    default:
138
      gimp_assert_not_reached ();
139 140 141 142 143 144 145 146 147 148
    }
}

static void
gimp_text_undo_set_property (GObject      *object,
                             guint         property_id,
                             const GValue *value,
                             GParamSpec   *pspec)
{
  GimpTextUndo *text_undo = GIMP_TEXT_UNDO (object);
149

150 151 152 153 154
  switch (property_id)
    {
    case PROP_PARAM:
      text_undo->pspec = g_value_get_param (value);
      break;
155

156 157 158 159
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
160 161 162
}

static void
163 164 165 166
gimp_text_undo_get_property (GObject    *object,
                             guint       property_id,
                             GValue     *value,
                             GParamSpec *pspec)
167
{
168 169 170 171 172 173 174
  GimpTextUndo *text_undo = GIMP_TEXT_UNDO (object);

  switch (property_id)
    {
    case PROP_PARAM:
      g_value_set_param (value, (GParamSpec *) text_undo->pspec);
      break;
175

176 177 178 179
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
180 181 182 183 184 185 186 187 188
}

static gint64
gimp_text_undo_get_memsize (GimpObject *object,
                            gint64     *gui_size)
{
  GimpTextUndo *undo    = GIMP_TEXT_UNDO (object);
  gint64        memsize = 0;

189 190
  memsize += gimp_g_value_get_memsize (undo->value);
  memsize += gimp_object_get_memsize (GIMP_OBJECT (undo->text), NULL);
191 192 193 194 195 196 197 198 199 200 201 202 203

  return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
                                                                  gui_size);
}

static void
gimp_text_undo_pop (GimpUndo            *undo,
                    GimpUndoMode         undo_mode,
                    GimpUndoAccumulator *accum)
{
  GimpTextUndo  *text_undo = GIMP_TEXT_UNDO (undo);
  GimpTextLayer *layer     = GIMP_TEXT_LAYER (GIMP_ITEM_UNDO (undo)->item);

204 205 206
  GIMP_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum);

  switch (undo->undo_type)
207
    {
208 209 210 211
    case GIMP_UNDO_TEXT_LAYER:
      if (text_undo->pspec)
        {
          GValue *value;
212

213
          g_return_if_fail (layer->text != NULL);
214

215
          value = g_slice_new0 (GValue);
216
          g_value_init (value, text_undo->pspec->value_type);
217

218 219
          g_object_get_property (G_OBJECT (layer->text),
                                 text_undo->pspec->name, value);
220

221 222
          g_object_set_property (G_OBJECT (layer->text),
                                 text_undo->pspec->name, text_undo->value);
223

224
          g_value_unset (text_undo->value);
225
          g_slice_free (GValue, text_undo->value);
226

227 228 229 230 231
          text_undo->value = value;
        }
      else
        {
          GimpText *text;
232

233 234
          text = (layer->text ?
                  gimp_config_duplicate (GIMP_CONFIG (layer->text)) : NULL);
235

236 237 238 239 240
          if (layer->text && text_undo->text)
            gimp_config_sync (G_OBJECT (text_undo->text),
                              G_OBJECT (layer->text), 0);
          else
            gimp_text_layer_set_text (layer, text_undo->text);
241

242 243
          if (text_undo->text)
            g_object_unref (text_undo->text);
244

245 246 247
          text_undo->text = text;
        }
      break;
248

249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
    case GIMP_UNDO_TEXT_LAYER_MODIFIED:
      {
        gboolean modified;

#if 0
        g_print ("setting layer->modified from %s to %s\n",
                 layer->modified ? "TRUE" : "FALSE",
                 text_undo->modified ? "TRUE" : "FALSE");
#endif

        modified = layer->modified;
        g_object_set (layer, "modified", text_undo->modified, NULL);
        text_undo->modified = modified;

        gimp_viewable_invalidate_preview (GIMP_VIEWABLE (layer));
      }
      break;

267 268 269 270 271 272 273 274 275
    case GIMP_UNDO_TEXT_LAYER_CONVERT:
      {
        const Babl *format;

        format = gimp_drawable_get_format (GIMP_DRAWABLE (layer));
        gimp_drawable_convert_type (GIMP_DRAWABLE (layer),
                                    gimp_item_get_image (GIMP_ITEM (layer)),
                                    gimp_babl_format_get_base_type (text_undo->format),
                                    gimp_babl_format_get_precision (text_undo->format),
276
                                    babl_format_has_alpha (text_undo->format),
277
                                    NULL, NULL,
278
                                    GEGL_DITHER_NONE, GEGL_DITHER_NONE,
279
                                    FALSE, NULL);
280 281 282 283
        text_undo->format = format;
      }
      break;

284
    default:
285
      gimp_assert_not_reached ();
286
    }
287 288 289 290 291 292 293 294
}

static void
gimp_text_undo_free (GimpUndo     *undo,
                     GimpUndoMode  undo_mode)
{
  GimpTextUndo *text_undo = GIMP_TEXT_UNDO (undo);

295
  g_clear_object (&text_undo->text);
296 297 298 299

  if (text_undo->pspec)
    {
      g_value_unset (text_undo->value);
300
      g_slice_free (GValue, text_undo->value);
301 302 303 304 305 306 307

      text_undo->value = NULL;
      text_undo->pspec = NULL;
    }

  GIMP_UNDO_CLASS (parent_class)->free (undo, undo_mode);
}