gimpimage.c 147 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 <string.h>
21
#include <time.h>
22

23
#include <cairo.h>
24
#include <gdk-pixbuf/gdk-pixbuf.h>
25
#include <gegl.h>
26
#include <gexiv2/gexiv2.h>
Sven Neumann's avatar
Sven Neumann committed
27

28
#include "libgimpcolor/gimpcolor.h"
29
#include "libgimpmath/gimpmath.h"
30
#include "libgimpbase/gimpbase.h"
31
#include "libgimpconfig/gimpconfig.h"
32

33 34
#include "core-types.h"

35
#include "config/gimpcoreconfig.h"
36

37 38
#include "operations/layer-modes/gimp-layer-modes.h"

39
#include "gegl/gimp-babl.h"
40

41
#include "gimp.h"
42
#include "gimp-memsize.h"
43
#include "gimp-parasites.h"
44
#include "gimp-utils.h"
45
#include "gimpcontext.h"
46
#include "gimpdrawable-floating-selection.h"
47
#include "gimpdrawablestack.h"
48
#include "gimpgrid.h"
49
#include "gimperror.h"
50
#include "gimpguide.h"
Martin Nordholts's avatar
Martin Nordholts committed
51
#include "gimpidtable.h"
52
#include "gimpimage.h"
53
#include "gimpimage-color-profile.h"
54
#include "gimpimage-colormap.h"
55
#include "gimpimage-guides.h"
56
#include "gimpimage-item-list.h"
57
#include "gimpimage-metadata.h"
58
#include "gimpimage-sample-points.h"
59
#include "gimpimage-preview.h"
60
#include "gimpimage-private.h"
61
#include "gimpimage-quick-mask.h"
Jehan's avatar
Jehan committed
62
#include "gimpimage-symmetry.h"
63
#include "gimpimage-undo.h"
64
#include "gimpimage-undo-push.h"
65
#include "gimpitemtree.h"
66
#include "gimplayer.h"
67
#include "gimplayer-floating-selection.h"
68
#include "gimplayermask.h"
Ell's avatar
Ell committed
69
#include "gimplayerstack.h"
70
#include "gimpmarshal.h"
71
#include "gimpparasitelist.h"
72
#include "gimppickable.h"
73
#include "gimpprojectable.h"
74
#include "gimpprojection.h"
75
#include "gimpsamplepoint.h"
76
#include "gimpselection.h"
Jehan's avatar
Jehan committed
77
#include "gimpsymmetry.h"
78
#include "gimptempbuf.h"
79
#include "gimptemplate.h"
80
#include "gimpundostack.h"
81

Michael Natterer's avatar
Michael Natterer committed
82 83
#include "vectors/gimpvectors.h"

84
#include "gimp-log.h"
85
#include "gimp-intl.h"
86

87

88
#ifdef DEBUG
89
#define TRC(x) g_printerr x
90 91 92 93 94
#else
#define TRC(x)
#endif


95 96 97
enum
{
  MODE_CHANGED,
98
  PRECISION_CHANGED,
99 100 101 102
  ALPHA_CHANGED,
  FLOATING_SELECTION_CHANGED,
  ACTIVE_LAYER_CHANGED,
  ACTIVE_CHANNEL_CHANGED,
Michael Natterer's avatar
Michael Natterer committed
103
  ACTIVE_VECTORS_CHANGED,
104 105 106 107
  COMPONENT_VISIBILITY_CHANGED,
  COMPONENT_ACTIVE_CHANGED,
  MASK_CHANGED,
  RESOLUTION_CHANGED,
108
  SIZE_CHANGED_DETAILED,
109
  UNIT_CHANGED,
110
  QUICK_MASK_CHANGED,
111
  SELECTION_INVALIDATE,
112 113
  CLEAN,
  DIRTY,
114
  SAVING,
115
  SAVED,
116
  EXPORTED,
117 118 119
  GUIDE_ADDED,
  GUIDE_REMOVED,
  GUIDE_MOVED,
120 121
  SAMPLE_POINT_ADDED,
  SAMPLE_POINT_REMOVED,
122
  SAMPLE_POINT_MOVED,
123 124
  PARASITE_ATTACHED,
  PARASITE_DETACHED,
125 126 127 128 129
  COLORMAP_CHANGED,
  UNDO_EVENT,
  LAST_SIGNAL
};

130 131 132 133 134 135 136
enum
{
  PROP_0,
  PROP_GIMP,
  PROP_ID,
  PROP_WIDTH,
  PROP_HEIGHT,
137
  PROP_BASE_TYPE,
138
  PROP_PRECISION,
139
  PROP_METADATA,
Jehan's avatar
Jehan committed
140 141
  PROP_BUFFER,
  PROP_SYMMETRY
142 143
};

144 145 146

/*  local function prototypes  */

147
static void     gimp_color_managed_iface_init    (GimpColorManagedInterface *iface);
148
static void     gimp_projectable_iface_init      (GimpProjectableInterface  *iface);
149
static void     gimp_pickable_iface_init         (GimpPickableInterface     *iface);
150

151
static void     gimp_image_constructed           (GObject           *object);
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
static void     gimp_image_set_property          (GObject           *object,
                                                  guint              property_id,
                                                  const GValue      *value,
                                                  GParamSpec        *pspec);
static void     gimp_image_get_property          (GObject           *object,
                                                  guint              property_id,
                                                  GValue            *value,
                                                  GParamSpec        *pspec);
static void     gimp_image_dispose               (GObject           *object);
static void     gimp_image_finalize              (GObject           *object);

static void     gimp_image_name_changed          (GimpObject        *object);
static gint64   gimp_image_get_memsize           (GimpObject        *object,
                                                  gint64            *gui_size);

static gboolean gimp_image_get_size              (GimpViewable      *viewable,
                                                  gint              *width,
                                                  gint              *height);
static void     gimp_image_size_changed          (GimpViewable      *viewable);
static gchar  * gimp_image_get_description       (GimpViewable      *viewable,
                                                  gchar            **tooltip);
173 174

static void     gimp_image_real_mode_changed     (GimpImage         *image);
175
static void     gimp_image_real_precision_changed(GimpImage         *image);
176
static void     gimp_image_real_resolution_changed(GimpImage        *image);
177
static void     gimp_image_real_size_changed_detailed
178 179 180 181 182
                                                 (GimpImage         *image,
                                                  gint               previous_origin_x,
                                                  gint               previous_origin_y,
                                                  gint               previous_width,
                                                  gint               previous_height);
183
static void     gimp_image_real_unit_changed     (GimpImage         *image);
184 185
static void     gimp_image_real_colormap_changed (GimpImage         *image,
                                                  gint               color_index);
186

187 188
static const guint8 *
        gimp_image_color_managed_get_icc_profile (GimpColorManaged  *managed,
189
                                                  gsize             *len);
190
static GimpColorProfile *
191
      gimp_image_color_managed_get_color_profile (GimpColorManaged  *managed);
192 193
static void
        gimp_image_color_managed_profile_changed (GimpColorManaged  *managed);
194 195

static void        gimp_image_projectable_flush  (GimpProjectable   *projectable,
196
                                                  gboolean           invalidate_preview);
197 198 199
static GeglNode   * gimp_image_get_graph         (GimpProjectable   *projectable);
static GimpImage  * gimp_image_get_image         (GimpProjectable   *projectable);
static const Babl * gimp_image_get_proj_format   (GimpProjectable   *projectable);
200

201 202 203 204 205 206 207 208 209 210
static void         gimp_image_pickable_flush    (GimpPickable      *pickable);
static GeglBuffer * gimp_image_get_buffer        (GimpPickable      *pickable);
static gboolean     gimp_image_get_pixel_at      (GimpPickable      *pickable,
                                                  gint               x,
                                                  gint               y,
                                                  const Babl        *format,
                                                  gpointer           pixel);
static gdouble      gimp_image_get_opacity_at    (GimpPickable      *pickable,
                                                  gint               x,
                                                  gint               y);
211 212 213 214
static void         gimp_image_get_pixel_average (GimpPickable      *pickable,
                                                  const GeglRectangle *rect,
                                                  const Babl        *format,
                                                  gpointer           pixel);
215 216 217 218
static void         gimp_image_pixel_to_srgb     (GimpPickable      *pickable,
                                                  const Babl        *format,
                                                  gpointer           pixel,
                                                  GimpRGB           *color);
219 220 221 222
static void         gimp_image_srgb_to_pixel     (GimpPickable      *pickable,
                                                  const GimpRGB     *color,
                                                  const Babl        *format,
                                                  gpointer           pixel);
223

224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
static void     gimp_image_mask_update           (GimpDrawable      *drawable,
                                                  gint               x,
                                                  gint               y,
                                                  gint               width,
                                                  gint               height,
                                                  GimpImage         *image);
static void     gimp_image_layer_alpha_changed   (GimpDrawable      *drawable,
                                                  GimpImage         *image);
static void     gimp_image_channel_add           (GimpContainer     *container,
                                                  GimpChannel       *channel,
                                                  GimpImage         *image);
static void     gimp_image_channel_remove        (GimpContainer     *container,
                                                  GimpChannel       *channel,
                                                  GimpImage         *image);
static void     gimp_image_channel_name_changed  (GimpChannel       *channel,
                                                  GimpImage         *image);
static void     gimp_image_channel_color_changed (GimpChannel       *channel,
                                                  GimpImage         *image);
242 243 244 245 246 247 248 249 250
static void     gimp_image_active_layer_notify   (GimpItemTree      *tree,
                                                  const GParamSpec  *pspec,
                                                  GimpImage         *image);
static void     gimp_image_active_channel_notify (GimpItemTree      *tree,
                                                  const GParamSpec  *pspec,
                                                  GimpImage         *image);
static void     gimp_image_active_vectors_notify (GimpItemTree      *tree,
                                                  const GParamSpec  *pspec,
                                                  GimpImage         *image);
251

252

253
G_DEFINE_TYPE_WITH_CODE (GimpImage, gimp_image, GIMP_TYPE_VIEWABLE,
254
                         G_ADD_PRIVATE (GimpImage)
255
                         G_IMPLEMENT_INTERFACE (GIMP_TYPE_COLOR_MANAGED,
256 257
                                                gimp_color_managed_iface_init)
                         G_IMPLEMENT_INTERFACE (GIMP_TYPE_PROJECTABLE,
258 259 260
                                                gimp_projectable_iface_init)
                         G_IMPLEMENT_INTERFACE (GIMP_TYPE_PICKABLE,
                                                gimp_pickable_iface_init))
261

262 263 264
#define parent_class gimp_image_parent_class

static guint gimp_image_signals[LAST_SIGNAL] = { 0 };
265

266

267 268 269
static void
gimp_image_class_init (GimpImageClass *klass)
{
270 271 272
  GObjectClass      *object_class      = G_OBJECT_CLASS (klass);
  GimpObjectClass   *gimp_object_class = GIMP_OBJECT_CLASS (klass);
  GimpViewableClass *viewable_class    = GIMP_VIEWABLE_CLASS (klass);
273

274
  gimp_image_signals[MODE_CHANGED] =
275
    g_signal_new ("mode-changed",
276 277 278 279 280 281
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, mode_changed),
                  NULL, NULL,
                  gimp_marshal_VOID__VOID,
                  G_TYPE_NONE, 0);
282

283 284 285 286 287 288 289 290 291
  gimp_image_signals[PRECISION_CHANGED] =
    g_signal_new ("precision-changed",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, precision_changed),
                  NULL, NULL,
                  gimp_marshal_VOID__VOID,
                  G_TYPE_NONE, 0);

292
  gimp_image_signals[ALPHA_CHANGED] =
293
    g_signal_new ("alpha-changed",
294 295 296 297 298 299
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, alpha_changed),
                  NULL, NULL,
                  gimp_marshal_VOID__VOID,
                  G_TYPE_NONE, 0);
300

301
  gimp_image_signals[FLOATING_SELECTION_CHANGED] =
302
    g_signal_new ("floating-selection-changed",
303 304 305 306 307 308
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, floating_selection_changed),
                  NULL, NULL,
                  gimp_marshal_VOID__VOID,
                  G_TYPE_NONE, 0);
309

310
  gimp_image_signals[ACTIVE_LAYER_CHANGED] =
311
    g_signal_new ("active-layer-changed",
312 313 314 315 316 317
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, active_layer_changed),
                  NULL, NULL,
                  gimp_marshal_VOID__VOID,
                  G_TYPE_NONE, 0);
318 319

  gimp_image_signals[ACTIVE_CHANNEL_CHANGED] =
320
    g_signal_new ("active-channel-changed",
321 322 323 324 325 326
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, active_channel_changed),
                  NULL, NULL,
                  gimp_marshal_VOID__VOID,
                  G_TYPE_NONE, 0);
327

Michael Natterer's avatar
Michael Natterer committed
328
  gimp_image_signals[ACTIVE_VECTORS_CHANGED] =
329
    g_signal_new ("active-vectors-changed",
330 331 332 333 334 335
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, active_vectors_changed),
                  NULL, NULL,
                  gimp_marshal_VOID__VOID,
                  G_TYPE_NONE, 0);
Michael Natterer's avatar
Michael Natterer committed
336

337
  gimp_image_signals[COMPONENT_VISIBILITY_CHANGED] =
338
    g_signal_new ("component-visibility-changed",
339 340 341 342 343 344 345
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, component_visibility_changed),
                  NULL, NULL,
                  gimp_marshal_VOID__ENUM,
                  G_TYPE_NONE, 1,
                  GIMP_TYPE_CHANNEL_TYPE);
346 347

  gimp_image_signals[COMPONENT_ACTIVE_CHANGED] =
348
    g_signal_new ("component-active-changed",
349 350 351 352 353 354 355
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, component_active_changed),
                  NULL, NULL,
                  gimp_marshal_VOID__ENUM,
                  G_TYPE_NONE, 1,
                  GIMP_TYPE_CHANNEL_TYPE);
356

357
  gimp_image_signals[MASK_CHANGED] =
358
    g_signal_new ("mask-changed",
359 360 361 362 363 364
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, mask_changed),
                  NULL, NULL,
                  gimp_marshal_VOID__VOID,
                  G_TYPE_NONE, 0);
365

366
  gimp_image_signals[RESOLUTION_CHANGED] =
367
    g_signal_new ("resolution-changed",
368 369 370 371 372 373
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, resolution_changed),
                  NULL, NULL,
                  gimp_marshal_VOID__VOID,
                  G_TYPE_NONE, 0);
374

375 376 377 378 379 380
  gimp_image_signals[SIZE_CHANGED_DETAILED] =
    g_signal_new ("size-changed-detailed",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, size_changed_detailed),
                  NULL, NULL,
381 382 383 384
                  gimp_marshal_VOID__INT_INT_INT_INT,
                  G_TYPE_NONE, 4,
                  G_TYPE_INT,
                  G_TYPE_INT,
385 386
                  G_TYPE_INT,
                  G_TYPE_INT);
387

388
  gimp_image_signals[UNIT_CHANGED] =
389
    g_signal_new ("unit-changed",
390 391 392 393 394 395
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, unit_changed),
                  NULL, NULL,
                  gimp_marshal_VOID__VOID,
                  G_TYPE_NONE, 0);
396

397 398
  gimp_image_signals[QUICK_MASK_CHANGED] =
    g_signal_new ("quick-mask-changed",
399 400
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
401
                  G_STRUCT_OFFSET (GimpImageClass, quick_mask_changed),
402 403 404
                  NULL, NULL,
                  gimp_marshal_VOID__VOID,
                  G_TYPE_NONE, 0);
405

406 407
  gimp_image_signals[SELECTION_INVALIDATE] =
    g_signal_new ("selection-invalidate",
408 409
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
410
                  G_STRUCT_OFFSET (GimpImageClass, selection_invalidate),
411
                  NULL, NULL,
412 413
                  gimp_marshal_VOID__VOID,
                  G_TYPE_NONE, 0);
414

415
  gimp_image_signals[CLEAN] =
416
    g_signal_new ("clean",
417 418 419 420
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, clean),
                  NULL, NULL,
421 422 423
                  gimp_marshal_VOID__FLAGS,
                  G_TYPE_NONE, 1,
                  GIMP_TYPE_DIRTY_MASK);
424

425
  gimp_image_signals[DIRTY] =
426
    g_signal_new ("dirty",
427 428 429 430
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, dirty),
                  NULL, NULL,
431 432 433
                  gimp_marshal_VOID__FLAGS,
                  G_TYPE_NONE, 1,
                  GIMP_TYPE_DIRTY_MASK);
434

435 436 437 438 439 440 441 442 443
  gimp_image_signals[SAVING] =
    g_signal_new ("saving",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, saving),
                  NULL, NULL,
                  gimp_marshal_VOID__VOID,
                  G_TYPE_NONE, 0);

444 445 446 447 448 449
  gimp_image_signals[SAVED] =
    g_signal_new ("saved",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, saved),
                  NULL, NULL,
450
                  gimp_marshal_VOID__OBJECT,
451
                  G_TYPE_NONE, 1,
452
                  G_TYPE_FILE);
453

454 455 456 457 458 459
  gimp_image_signals[EXPORTED] =
    g_signal_new ("exported",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, exported),
                  NULL, NULL,
460
                  gimp_marshal_VOID__OBJECT,
461
                  G_TYPE_NONE, 1,
462
                  G_TYPE_FILE);
463

464 465
  gimp_image_signals[GUIDE_ADDED] =
    g_signal_new ("guide-added",
466 467
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
468
                  G_STRUCT_OFFSET (GimpImageClass, guide_added),
469 470 471
                  NULL, NULL,
                  gimp_marshal_VOID__OBJECT,
                  G_TYPE_NONE, 1,
472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492
                  GIMP_TYPE_GUIDE);

  gimp_image_signals[GUIDE_REMOVED] =
    g_signal_new ("guide-removed",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, guide_removed),
                  NULL, NULL,
                  gimp_marshal_VOID__OBJECT,
                  G_TYPE_NONE, 1,
                  GIMP_TYPE_GUIDE);

  gimp_image_signals[GUIDE_MOVED] =
    g_signal_new ("guide-moved",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, guide_moved),
                  NULL, NULL,
                  gimp_marshal_VOID__OBJECT,
                  G_TYPE_NONE, 1,
                  GIMP_TYPE_GUIDE);
493

494
  gimp_image_signals[SAMPLE_POINT_ADDED] =
495
    g_signal_new ("sample-point-added",
496 497 498 499
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, sample_point_added),
                  NULL, NULL,
500
                  gimp_marshal_VOID__OBJECT,
501
                  G_TYPE_NONE, 1,
502
                  GIMP_TYPE_SAMPLE_POINT);
503 504

  gimp_image_signals[SAMPLE_POINT_REMOVED] =
505
    g_signal_new ("sample-point-removed",
506 507 508 509
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, sample_point_removed),
                  NULL, NULL,
510
                  gimp_marshal_VOID__OBJECT,
511
                  G_TYPE_NONE, 1,
512
                  GIMP_TYPE_SAMPLE_POINT);
513

514 515 516 517 518 519
  gimp_image_signals[SAMPLE_POINT_MOVED] =
    g_signal_new ("sample-point-moved",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, sample_point_moved),
                  NULL, NULL,
520
                  gimp_marshal_VOID__OBJECT,
521
                  G_TYPE_NONE, 1,
522
                  GIMP_TYPE_SAMPLE_POINT);
523

524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543
  gimp_image_signals[PARASITE_ATTACHED] =
    g_signal_new ("parasite-attached",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, parasite_attached),
                  NULL, NULL,
                  g_cclosure_marshal_VOID__STRING,
                  G_TYPE_NONE, 1,
                  G_TYPE_STRING);

  gimp_image_signals[PARASITE_DETACHED] =
    g_signal_new ("parasite-detached",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, parasite_detached),
                  NULL, NULL,
                  g_cclosure_marshal_VOID__STRING,
                  G_TYPE_NONE, 1,
                  G_TYPE_STRING);

544
  gimp_image_signals[COLORMAP_CHANGED] =
545
    g_signal_new ("colormap-changed",
546 547 548 549 550 551 552
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, colormap_changed),
                  NULL, NULL,
                  gimp_marshal_VOID__INT,
                  G_TYPE_NONE, 1,
                  G_TYPE_INT);
553

554
  gimp_image_signals[UNDO_EVENT] =
555
    g_signal_new ("undo-event",
556 557 558 559 560 561 562
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, undo_event),
                  NULL, NULL,
                  gimp_marshal_VOID__ENUM_OBJECT,
                  G_TYPE_NONE, 2,
                  GIMP_TYPE_UNDO_EVENT,
563
                  GIMP_TYPE_UNDO);
564

565
  object_class->constructed           = gimp_image_constructed;
566 567
  object_class->set_property          = gimp_image_set_property;
  object_class->get_property          = gimp_image_get_property;
568 569
  object_class->dispose               = gimp_image_dispose;
  object_class->finalize              = gimp_image_finalize;
570

571
  gimp_object_class->name_changed     = gimp_image_name_changed;
572
  gimp_object_class->get_memsize      = gimp_image_get_memsize;
573

574
  viewable_class->default_icon_name   = "gimp-image";
575
  viewable_class->get_size            = gimp_image_get_size;
576
  viewable_class->size_changed        = gimp_image_size_changed;
577
  viewable_class->get_preview_size    = gimp_image_get_preview_size;
578
  viewable_class->get_popup_size      = gimp_image_get_popup_size;
579
  viewable_class->get_new_preview     = gimp_image_get_new_preview;
580
  viewable_class->get_new_pixbuf      = gimp_image_get_new_pixbuf;
581
  viewable_class->get_description     = gimp_image_get_description;
582

583
  klass->mode_changed                 = gimp_image_real_mode_changed;
584
  klass->precision_changed            = gimp_image_real_precision_changed;
585
  klass->alpha_changed                = NULL;
586
  klass->floating_selection_changed   = NULL;
587 588
  klass->active_layer_changed         = NULL;
  klass->active_channel_changed       = NULL;
Michael Natterer's avatar
Michael Natterer committed
589
  klass->active_vectors_changed       = NULL;
590 591
  klass->component_visibility_changed = NULL;
  klass->component_active_changed     = NULL;
592
  klass->mask_changed                 = NULL;
593
  klass->resolution_changed           = gimp_image_real_resolution_changed;
594
  klass->size_changed_detailed        = gimp_image_real_size_changed_detailed;
595
  klass->unit_changed                 = gimp_image_real_unit_changed;
596
  klass->quick_mask_changed           = NULL;
597
  klass->selection_invalidate         = NULL;
598

599 600
  klass->clean                        = NULL;
  klass->dirty                        = NULL;
601
  klass->saving                       = NULL;
602
  klass->saved                        = NULL;
603
  klass->exported                     = NULL;
604 605 606
  klass->guide_added                  = NULL;
  klass->guide_removed                = NULL;
  klass->guide_moved                  = NULL;
607 608
  klass->sample_point_added           = NULL;
  klass->sample_point_removed         = NULL;
609
  klass->sample_point_moved           = NULL;
610 611
  klass->parasite_attached            = NULL;
  klass->parasite_detached            = NULL;
612
  klass->colormap_changed             = gimp_image_real_colormap_changed;
613
  klass->undo_event                   = NULL;
614

615 616 617
  g_object_class_install_property (object_class, PROP_GIMP,
                                   g_param_spec_object ("gimp", NULL, NULL,
                                                        GIMP_TYPE_GIMP,
618
                                                        GIMP_PARAM_READWRITE |
619 620 621 622 623
                                                        G_PARAM_CONSTRUCT_ONLY));

  g_object_class_install_property (object_class, PROP_ID,
                                   g_param_spec_int ("id", NULL, NULL,
                                                     0, G_MAXINT, 0,
624
                                                     GIMP_PARAM_READABLE));
625 626 627 628

  g_object_class_install_property (object_class, PROP_WIDTH,
                                   g_param_spec_int ("width", NULL, NULL,
                                                     1, GIMP_MAX_IMAGE_SIZE, 1,
629
                                                     GIMP_PARAM_READWRITE |
630 631 632 633 634
                                                     G_PARAM_CONSTRUCT));

  g_object_class_install_property (object_class, PROP_HEIGHT,
                                   g_param_spec_int ("height", NULL, NULL,
                                                     1, GIMP_MAX_IMAGE_SIZE, 1,
635
                                                     GIMP_PARAM_READWRITE |
636 637 638 639 640 641
                                                     G_PARAM_CONSTRUCT));

  g_object_class_install_property (object_class, PROP_BASE_TYPE,
                                   g_param_spec_enum ("base-type", NULL, NULL,
                                                      GIMP_TYPE_IMAGE_BASE_TYPE,
                                                      GIMP_RGB,
642
                                                      GIMP_PARAM_READWRITE |
643 644
                                                      G_PARAM_CONSTRUCT));

645 646 647
  g_object_class_install_property (object_class, PROP_PRECISION,
                                   g_param_spec_enum ("precision", NULL, NULL,
                                                      GIMP_TYPE_PRECISION,
648
                                                      GIMP_PRECISION_U8_NON_LINEAR,
649 650 651
                                                      GIMP_PARAM_READWRITE |
                                                      G_PARAM_CONSTRUCT));

652 653 654 655 656
  g_object_class_install_property (object_class, PROP_METADATA,
                                   g_param_spec_object ("metadata", NULL, NULL,
                                                        GEXIV2_TYPE_METADATA,
                                                        GIMP_PARAM_READABLE));

657 658
  g_object_class_override_property (object_class, PROP_BUFFER, "buffer");

Jehan's avatar
Jehan committed
659
  g_object_class_install_property (object_class, PROP_SYMMETRY,
660 661 662 663 664
                                   g_param_spec_gtype ("symmetry",
                                                       NULL, _("Symmetry"),
                                                       GIMP_TYPE_SYMMETRY,
                                                       GIMP_PARAM_READWRITE |
                                                       G_PARAM_CONSTRUCT));
665 666
}

667 668 669
static void
gimp_color_managed_iface_init (GimpColorManagedInterface *iface)
{
670 671
  iface->get_icc_profile   = gimp_image_color_managed_get_icc_profile;
  iface->get_color_profile = gimp_image_color_managed_get_color_profile;
672
  iface->profile_changed   = gimp_image_color_managed_profile_changed;
673 674
}

675 676 677
static void
gimp_projectable_iface_init (GimpProjectableInterface *iface)
{
678 679
  iface->flush              = gimp_image_projectable_flush;
  iface->get_image          = gimp_image_get_image;
680
  iface->get_format         = gimp_image_get_proj_format;
681
  iface->get_size           = (void (*) (GimpProjectable*, gint*, gint*)) gimp_image_get_size;
682
  iface->get_graph          = gimp_image_get_graph;
683
  iface->invalidate_preview = (void (*) (GimpProjectable*)) gimp_viewable_invalidate_preview;
684 685
}

686 687 688 689 690 691 692 693 694 695
static void
gimp_pickable_iface_init (GimpPickableInterface *iface)
{
  iface->flush                 = gimp_image_pickable_flush;
  iface->get_image             = (GimpImage  * (*) (GimpPickable *pickable)) gimp_image_get_image;
  iface->get_format            = (const Babl * (*) (GimpPickable *pickable)) gimp_image_get_proj_format;
  iface->get_format_with_alpha = (const Babl * (*) (GimpPickable *pickable)) gimp_image_get_proj_format;
  iface->get_buffer            = gimp_image_get_buffer;
  iface->get_pixel_at          = gimp_image_get_pixel_at;
  iface->get_opacity_at        = gimp_image_get_opacity_at;
696
  iface->get_pixel_average     = gimp_image_get_pixel_average;
697
  iface->pixel_to_srgb         = gimp_image_pixel_to_srgb;
698
  iface->srgb_to_pixel         = gimp_image_srgb_to_pixel;
699 700
}

701
static void
702
gimp_image_init (GimpImage *image)
703
{
704
  GimpImagePrivate *private = gimp_image_get_instance_private (image);
705
  gint              i;
706

707 708
  image->priv = private;

709
  private->ID                  = 0;
710

711 712
  private->load_proc           = NULL;
  private->save_proc           = NULL;
713

714 715 716 717 718 719
  private->width               = 0;
  private->height              = 0;
  private->xresolution         = 1.0;
  private->yresolution         = 1.0;
  private->resolution_unit     = GIMP_UNIT_INCH;
  private->base_type           = GIMP_RGB;
720
  private->precision           = GIMP_PRECISION_U8_NON_LINEAR;
721
  private->new_layer_mode      = -1;
722

723 724
  private->colormap            = NULL;
  private->n_colors            = 0;
725
  private->palette             = NULL;
726

727 728
  private->metadata            = NULL;

729 730 731
  private->dirty               = 1;
  private->dirty_time          = 0;
  private->undo_freeze_count   = 0;
732

733
  private->export_dirty        = 1;
734

735 736
  private->instance_count      = 0;
  private->disp_count          = 0;
737

738
  private->tattoo_state        = 0;
739

740
  private->projection          = gimp_projection_new (GIMP_PROJECTABLE (image));
741

Jehan's avatar
Jehan committed
742
  private->symmetries          = NULL;
743
  private->active_symmetry     = NULL;
Jehan's avatar
Jehan committed
744

745 746 747
  private->guides              = NULL;
  private->grid                = NULL;
  private->sample_points       = NULL;
748

749
  private->layers              = gimp_item_tree_new (image,
Ell's avatar
Ell committed
750
                                                     GIMP_TYPE_LAYER_STACK,
751
                                                     GIMP_TYPE_LAYER);
752 753
  private->channels            = gimp_item_tree_new (image,
                                                     GIMP_TYPE_DRAWABLE_STACK,
754
                                                     GIMP_TYPE_CHANNEL);
755 756
  private->vectors             = gimp_item_tree_new (image,
                                                     GIMP_TYPE_ITEM_STACK,
757
                                                     GIMP_TYPE_VECTORS);
758
  private->layer_stack         = NULL;
759

760 761 762 763 764 765 766 767 768 769
  g_signal_connect (private->layers, "notify::active-item",
                    G_CALLBACK (gimp_image_active_layer_notify),
                    image);
  g_signal_connect (private->channels, "notify::active-item",
                    G_CALLBACK (gimp_image_active_channel_notify),
                    image);
  g_signal_connect (private->vectors, "notify::active-item",
                    G_CALLBACK (gimp_image_active_vectors_notify),
                    image);

770
  g_signal_connect_swapped (private->layers->container, "update",
771
                            G_CALLBACK (gimp_image_invalidate),
772 773
                            image);

774
  private->layer_alpha_handler =
775
    gimp_container_add_handler (private->layers->container, "alpha-changed",
776
                                G_CALLBACK (gimp_image_layer_alpha_changed),
777
                                image);
778

779
  g_signal_connect_swapped (private->channels->container, "update",
780
                            G_CALLBACK (gimp_image_invalidate),
781 782
                            image);

783
  private->channel_name_changed_handler =
784
    gimp_container_add_handler (private->channels->container, "name-changed",
785
                                G_CALLBACK (gimp_image_channel_name_changed),
786
                                image);
787
  private->channel_color_changed_handler =
788
    gimp_container_add_handler (private->channels->container, "color-changed",
789
                                G_CALLBACK (gimp_image_channel_color_changed),
790
                                image);
791

792
  g_signal_connect (private->channels->container, "add",
793
                    G_CALLBACK (gimp_image_channel_add),
794
                    image);
795
  g_signal_connect (private->channels->container, "remove",
796
                    G_CALLBACK (gimp_image_channel_remove),
797
                    image);
798

799 800
  private->floating_sel        = NULL;
  private->selection_mask      = NULL;
801

802
  private->parasites           = gimp_parasite_list_new ();
803

804 805
  for (i = 0; i < MAX_CHANNELS; i++)
    {
806 807
      private->visible[i] = TRUE;
      private->active[i]  = TRUE;
808 809
    }

810 811 812
  private->quick_mask_state    = FALSE;
  private->quick_mask_inverted = FALSE;
  gimp_rgba_set (&private->quick_mask_color, 1.0, 0.0, 0.0, 0.5);
813

814 815 816 817
  private->undo_stack          = gimp_undo_stack_new (image);
  private->redo_stack          = gimp_undo_stack_new (image);
  private->group_count         = 0;
  private->pushing_undo_group  = GIMP_UNDO_GROUP_NONE;
818

819 820 821 822
  private->flush_accum.alpha_changed              = FALSE;
  private->flush_accum.mask_changed               = FALSE;
  private->flush_accum.floating_selection_changed = FALSE;
  private->flush_accum.preview_invalidated        = FALSE;
823 824
}

825 826
static void
gimp_image_constructed (GObject *object)
827
{
828 829
  GimpImage        *image   = GIMP_IMAGE (object);
  GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image);
830
  GimpChannel      *selection;
831
  GimpCoreConfig   *config;
832
  GimpTemplate     *template;
833

834
  G_OBJECT_CLASS (parent_class)->constructed (object);
835

836
  gimp_assert (GIMP_IS_GIMP (image->gimp));
837

838
  config = image->gimp->config;
839

Martin Nordholts's avatar
Martin Nordholts committed
840
  private->ID = gimp_id_table_insert (image->gimp->image_table, image);
841

842 843 844 845 846
  template = config->default_image;

  private->xresolution     = gimp_template_get_resolution_x (template);
  private->yresolution     = gimp_template_get_resolution_y (template);
  private->resolution_unit = gimp_template_get_resolution_unit (template);
847

848
  private->grid = gimp_config_duplicate (GIMP_CONFIG (config->default_grid));
849

850 851
  private->quick_mask_color = config->quick_mask_color;

852 853
  if (private->base_type == GIMP_INDEXED)
    gimp_image_colormap_init (image);
854

855 856 857 858
  selection = gimp_selection_new (image,
                                  gimp_image_get_width  (image),
                                  gimp_image_get_height (image));
  gimp_image_take_mask (image, selection);
859 860

  g_signal_connect_object (config, "notify::transparency-type",
861
                           G_CALLBACK (gimp_item_stack_invalidate_previews),
862
                           private->layers->container, G_CONNECT_SWAPPED);
863
  g_signal_connect_object (config, "notify::transparency-size",
864
                           G_CALLBACK (gimp_item_stack_invalidate_previews),
865
                           private->layers->container, G_CONNECT_SWAPPED);
866 867
  g_signal_connect_object (config, "notify::layer-previews",
                           G_CALLBACK (gimp_viewable_size_changed),
868
                           image, G_CONNECT_SWAPPED);
869 870 871
  g_signal_connect_object (config, "notify::group-layer-previews",
                           G_CALLBACK (gimp_viewable_size_changed),
                           image, G_CONNECT_SWAPPED);
872

873
  gimp_container_add (image->gimp->images, GIMP_OBJECT (image));
874 875 876 877 878 879 880 881
}

static void
gimp_image_set_property (GObject      *object,
                         guint         property_id,
                         const GValue *value,
                         GParamSpec   *pspec)
{
882 883
  GimpImage        *image   = GIMP_IMAGE (object);
  GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image);
884 885 886 887

  switch (property_id)
    {
    case PROP_GIMP:
888
      image->gimp = g_value_get_object (value);
889
      break;
890

891
    case PROP_WIDTH:
892
      private->width = g_value_get_int (value);
893 894
      break;
    case PROP_HEIGHT:
895
      private->height = g_value_get_int (value);
896
      break;
897

898
    case PROP_BASE_TYPE:
899
      private->base_type = g_value_get_enum (value);
900
      _gimp_image_free_color_transforms (image);
901
      break;
902

903 904
    case PROP_PRECISION:
      private->precision = g_value_get_enum (value);
905
      _gimp_image_free_color_transforms (image);
906
      break;
907

Jehan's avatar
Jehan committed
908 909
    case PROP_SYMMETRY:
      {
910 911
        GList *iter;
        GType  type = g_value_get_gtype (value);
Jehan's avatar
Jehan committed
912

913 914
        if (private->active_symmetry)
          g_object_set (private->active_symmetry,
Jehan's avatar
Jehan committed
915 916
                        "active", FALSE,
                        NULL);
917
        private->active_symmetry = NULL;
Jehan's avatar
Jehan committed
918

919
        for (iter = private->symmetries; iter; iter = g_list_next (iter))
Jehan's avatar
Jehan committed
920
          {
921
            GimpSymmetry *sym = iter->data;
922

923
            if (type == G_TYPE_FROM_INSTANCE (sym))
924
              private->active_symmetry = iter->data;
925 926
          }

927 928
        if (! private->active_symmetry &&
            g_type_is_a (type, GIMP_TYPE_SYMMETRY))
929
          {
930
            GimpSymmetry *sym = gimp_image_symmetry_new (image, type);
931 932

            gimp_image_symmetry_add (image, sym);
933 934
            g_object_unref (sym);

935
            private->active_symmetry = sym;
Jehan's avatar
Jehan committed
936
          }
937

938 939 940 941
        if (private->active_symmetry)
          g_object_set (private->active_symmetry,
                        "active", TRUE,
                        NULL);
Jehan's avatar
Jehan committed
942 943
      }
      break;
944 945 946 947

    case PROP_ID:
    case PROP_METADATA:
    case PROP_BUFFER:
948 949 950 951 952 953 954 955 956 957 958 959
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}

static void
gimp_image_get_property (GObject    *object,
                         guint       property_id,
                         GValue     *value,
                         GParamSpec *pspec)
{
960 961
  GimpImage        *image   = GIMP_IMAGE (object);
  GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image);
962 963 964 965

  switch (property_id)
    {
    case PROP_GIMP:
966
      g_value_set_object (value, image->gimp);
967 968
      break;
    case PROP_ID:
969
      g_value_set_int (value, private->ID);
970 971
      break;
    case PROP_WIDTH:
972
      g_value_set_int (value, private->width);
973 974
      break;
    case PROP_HEIGHT:
975
      g_value_set_int (value, private->height);
976 977
      break;
    case PROP_BASE_TYPE:
978
      g_value_set_enum (value, private->base_type);
979
      break;
980 981 982
    case PROP_PRECISION:
      g_value_set_enum (value, private->precision);
      break;
983 984 985
    case PROP_METADATA:
      g_value_set_object (value, gimp_image_get_metadata (image));
      break;
986 987 988
    case PROP_BUFFER:
      g_value_set_object (value, gimp_image_get_buffer (GIMP_PICKABLE (image)));
      break;
Jehan's avatar
Jehan committed
989
    case PROP_SYMMETRY:
990
      g_value_set_gtype (value,
991 992 993
                         private->active_symmetry ?
                         G_TYPE_FROM_INSTANCE (private->active_symmetry) :
                         G_TYPE_NONE);
Jehan's avatar
Jehan committed
994
      break;
995 996 997 998 999 1000
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}

1001
static void
1002 1003
gimp_image_dispose (GObject *object)
{
1004 1005
  GimpImage        *image   = GIMP_IMAGE (object);
  GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image);
1006

1007 1008 1009
  if (private->colormap)
    gimp_image_colormap_dispose (image);

1010
  gimp_image_undo_free (image);
1011

1012
  g_signal_handlers_disconnect_by_func (private->layers->container,
1013
                                        gimp_image_invalidate,
1014 1015
                                        image);

1016
  gimp_container_remove_handler (private->layers->container,
1017
                                 private->layer_alpha_handler);
1018

1019
  g_signal_handlers_disconnect_by_func (private->channels->container,
1020
                                        gimp_image_invalidate,
1021 1022
                                        image);

1023
  gimp_container_remove_handler (private->channels->container,
1024
                                 private->channel_name_changed_handler);
1025
  gimp_container_remove_handler (private->channels->container,
1026
                                 private->channel_color_changed_handler);
1027

1028
  g_signal_handlers_disconnect_by_func (private->channels->container,
1029
                                        gimp_image_channel_add,
1030
                                        image);
1031
  g_signal_handlers_disconnect_by_func (private->channels->container,
1032
                                        gimp_image_channel_remove,
1033
                                        image);
1034

1035 1036 1037 1038 1039 1040
  gimp_container_foreach (private->layers->container,
                          (GFunc) gimp_item_removed, NULL);
  gimp_container_foreach (private->channels->container,
                          (GFunc) gimp_item_removed, NULL);
  gimp_container_foreach (private->vectors->container,
                          (GFunc) gimp_item_removed, NULL);
1041

1042 1043 1044 1045 1046
  G_OBJECT_CLASS (parent_class)->dispose (object);
}

static void
gimp_image_finalize (GObject *object)
Sven Neumann's avatar
Sven Neumann committed
1047
{
1048 1049
  GimpImage        *image   = GIMP_IMAGE (object);
  GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image);
1050

1051 1052 1053
  g_clear_object (&private->projection);
  g_clear_object (&private->graph);
  private->visible_mask = NULL;
1054

1055
  if (private->colormap)
1056
    gimp_image_colormap_free (image);
1057

1058
  _gimp_image_free_color_profile (image);
1059

1060 1061 1062 1063 1064 1065 1066 1067 1068
  g_clear_object (&private->metadata);
  g_clear_object (&private->file);
  g_clear_object (&private->imported_file);
  g_clear_object (&private->exported_file);
  g_clear_object (&private->save_a_copy_file);
  g_clear_object (&private->untitled_file);
  g_clear_object (&private->layers);
  g_clear_object (&private->channels);
  g_clear_object (&private->vectors);
1069

1070
  if (private->layer_stack)
1071
    {
1072 1073
      g_slist_free (private->layer_stack);
      private->layer_stack = NULL;
1074
    }
1075

1076 1077
  g_clear_object (&private->selection_mask);
  g_clear_object (&private->parasites);
1078

1079
  if (private->guides)
1080
    {
1081
      g_list_free_full (private->guides, (GDestroyNotify) g_object_unref);
1082
      private->guides = NULL;
1083
    }
1084

Jehan's avatar
Jehan committed
1085 1086 1087 1088 1089