gimpimage.c 120 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 <http://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 <gegl.h>
25
#include <gdk-pixbuf/gdk-pixbuf.h>
Sven Neumann's avatar
Sven Neumann committed
26

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

Michael Natterer's avatar
Michael Natterer committed
32 33
#include "core-types.h"

34
#include "config/gimpcoreconfig.h"
35

36
#include "gegl/gimp-babl.h"
37

38
#include "gimp.h"
39
#include "gimp-parasites.h"
40
#include "gimp-utils.h"
41
#include "gimpcontext.h"
42
#include "gimpdrawablestack.h"
43
#include "gimpgrid.h"
44
#include "gimperror.h"
45
#include "gimpguide.h"
Martin Nordholts's avatar
Martin Nordholts committed
46
#include "gimpidtable.h"
47
#include "gimpimage.h"
48
#include "gimpimage-colormap.h"
49
#include "gimpimage-guides.h"
50
#include "gimpimage-sample-points.h"
51
#include "gimpimage-preview.h"
52
#include "gimpimage-private.h"
53
#include "gimpimage-quick-mask.h"
54
#include "gimpimage-undo.h"
55
#include "gimpimage-undo-push.h"
56
#include "gimpitemtree.h"
57
#include "gimplayer.h"
Michael Natterer's avatar
Michael Natterer committed
58
#include "gimplayer-floating-sel.h"
59
#include "gimplayermask.h"
60
#include "gimpmarshal.h"
61
#include "gimpparasitelist.h"
62
#include "gimppickable.h"
63
#include "gimpprojectable.h"
Michael Natterer's avatar
Michael Natterer committed
64
#include "gimpprojection.h"
65
#include "gimpsamplepoint.h"
66
#include "gimpselection.h"
67
#include "gimptempbuf.h"
68
#include "gimptemplate.h"
69
#include "gimpundostack.h"
70

71 72
#include "file/file-utils.h"

Michael Natterer's avatar
Michael Natterer committed
73 74
#include "vectors/gimpvectors.h"

75
#include "gimp-intl.h"
76

77

78
#ifdef DEBUG
79
#define TRC(x) g_printerr x
80 81 82 83
#else
#define TRC(x)
#endif

84 85 86 87 88
/* Data keys for GimpImage */
#define GIMP_FILE_EXPORT_URI_KEY        "gimp-file-export-uri"
#define GIMP_FILE_SAVE_A_COPY_URI_KEY   "gimp-file-save-a-copy-uri"
#define GIMP_FILE_IMPORT_SOURCE_URI_KEY "gimp-file-import-source-uri"

89

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

124 125 126 127 128 129 130
enum
{
  PROP_0,
  PROP_GIMP,
  PROP_ID,
  PROP_WIDTH,
  PROP_HEIGHT,
131 132
  PROP_BASE_TYPE,
  PROP_PRECISION
133 134
};

135 136 137

/*  local function prototypes  */

138
static void     gimp_color_managed_iface_init    (GimpColorManagedInterface *iface);
139
static void     gimp_projectable_iface_init      (GimpProjectableInterface  *iface);
140

141
static void     gimp_image_constructed           (GObject           *object);
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
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);
163 164

static void     gimp_image_real_mode_changed     (GimpImage         *image);
165
static void     gimp_image_real_precision_changed(GimpImage         *image);
166
static void     gimp_image_real_size_changed_detailed
167 168 169 170 171 172 173
                                                 (GimpImage         *image,
                                                  gint               previous_origin_x,
                                                  gint               previous_origin_y,
                                                  gint               previous_width,
                                                  gint               previous_height);
static void     gimp_image_real_colormap_changed (GimpImage         *image,
                                                  gint               color_index);
174 175 176 177 178

static const guint8 * gimp_image_get_icc_profile (GimpColorManaged  *managed,
                                                  gsize             *len);

static void        gimp_image_projectable_flush  (GimpProjectable   *projectable,
179
                                                  gboolean           invalidate_preview);
180 181 182
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);
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201

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);
202 203 204 205 206 207 208 209 210
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);
211

212

213 214
G_DEFINE_TYPE_WITH_CODE (GimpImage, gimp_image, GIMP_TYPE_VIEWABLE,
                         G_IMPLEMENT_INTERFACE (GIMP_TYPE_COLOR_MANAGED,
215 216 217
                                                gimp_color_managed_iface_init)
                         G_IMPLEMENT_INTERFACE (GIMP_TYPE_PROJECTABLE,
                                                gimp_projectable_iface_init))
218

219 220 221
#define parent_class gimp_image_parent_class

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

223

224 225 226
static void
gimp_image_class_init (GimpImageClass *klass)
{
227 228 229
  GObjectClass      *object_class      = G_OBJECT_CLASS (klass);
  GimpObjectClass   *gimp_object_class = GIMP_OBJECT_CLASS (klass);
  GimpViewableClass *viewable_class    = GIMP_VIEWABLE_CLASS (klass);
230

231
  gimp_image_signals[MODE_CHANGED] =
232
    g_signal_new ("mode-changed",
233 234 235 236 237 238
                  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);
239

240 241 242 243 244 245 246 247 248
  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);

249
  gimp_image_signals[ALPHA_CHANGED] =
250
    g_signal_new ("alpha-changed",
251 252 253 254 255 256
                  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);
257

258
  gimp_image_signals[FLOATING_SELECTION_CHANGED] =
259
    g_signal_new ("floating-selection-changed",
260 261 262 263 264 265
                  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);
266

267
  gimp_image_signals[ACTIVE_LAYER_CHANGED] =
268
    g_signal_new ("active-layer-changed",
269 270 271 272 273 274
                  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);
275 276

  gimp_image_signals[ACTIVE_CHANNEL_CHANGED] =
277
    g_signal_new ("active-channel-changed",
278 279 280 281 282 283
                  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);
284

Michael Natterer's avatar
Michael Natterer committed
285
  gimp_image_signals[ACTIVE_VECTORS_CHANGED] =
286
    g_signal_new ("active-vectors-changed",
287 288 289 290 291 292
                  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
293

294
  gimp_image_signals[COMPONENT_VISIBILITY_CHANGED] =
295
    g_signal_new ("component-visibility-changed",
296 297 298 299 300 301 302
                  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);
303 304

  gimp_image_signals[COMPONENT_ACTIVE_CHANGED] =
305
    g_signal_new ("component-active-changed",
306 307 308 309 310 311 312
                  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);
313

314
  gimp_image_signals[MASK_CHANGED] =
315
    g_signal_new ("mask-changed",
316 317 318 319 320 321
                  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);
322

323
  gimp_image_signals[RESOLUTION_CHANGED] =
324
    g_signal_new ("resolution-changed",
325 326 327 328 329 330
                  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);
331

332 333 334 335 336 337
  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,
338 339 340 341
                  gimp_marshal_VOID__INT_INT_INT_INT,
                  G_TYPE_NONE, 4,
                  G_TYPE_INT,
                  G_TYPE_INT,
342 343
                  G_TYPE_INT,
                  G_TYPE_INT);
344

345
  gimp_image_signals[UNIT_CHANGED] =
346
    g_signal_new ("unit-changed",
347 348 349 350 351 352
                  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);
353

354 355
  gimp_image_signals[QUICK_MASK_CHANGED] =
    g_signal_new ("quick-mask-changed",
356 357
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
358
                  G_STRUCT_OFFSET (GimpImageClass, quick_mask_changed),
359 360 361
                  NULL, NULL,
                  gimp_marshal_VOID__VOID,
                  G_TYPE_NONE, 0);
Michael Natterer's avatar
Michael Natterer committed
362

363 364
  gimp_image_signals[SELECTION_INVALIDATE] =
    g_signal_new ("selection-invalidate",
365 366
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
367
                  G_STRUCT_OFFSET (GimpImageClass, selection_invalidate),
368
                  NULL, NULL,
369 370
                  gimp_marshal_VOID__VOID,
                  G_TYPE_NONE, 0);
371

372
  gimp_image_signals[CLEAN] =
373
    g_signal_new ("clean",
374 375 376 377
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, clean),
                  NULL, NULL,
378 379 380
                  gimp_marshal_VOID__FLAGS,
                  G_TYPE_NONE, 1,
                  GIMP_TYPE_DIRTY_MASK);
381

382
  gimp_image_signals[DIRTY] =
383
    g_signal_new ("dirty",
384 385 386 387
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, dirty),
                  NULL, NULL,
388 389 390
                  gimp_marshal_VOID__FLAGS,
                  G_TYPE_NONE, 1,
                  GIMP_TYPE_DIRTY_MASK);
391

392 393 394 395 396 397 398 399 400 401
  gimp_image_signals[SAVED] =
    g_signal_new ("saved",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, saved),
                  NULL, NULL,
                  gimp_marshal_VOID__STRING,
                  G_TYPE_NONE, 1,
                  G_TYPE_STRING);

402 403 404 405 406 407 408 409 410 411
  gimp_image_signals[EXPORTED] =
    g_signal_new ("exported",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, exported),
                  NULL, NULL,
                  gimp_marshal_VOID__STRING,
                  G_TYPE_NONE, 1,
                  G_TYPE_STRING);

412 413
  gimp_image_signals[GUIDE_ADDED] =
    g_signal_new ("guide-added",
414 415
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
416
                  G_STRUCT_OFFSET (GimpImageClass, guide_added),
417 418 419
                  NULL, NULL,
                  gimp_marshal_VOID__OBJECT,
                  G_TYPE_NONE, 1,
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440
                  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);
441

442
  gimp_image_signals[SAMPLE_POINT_ADDED] =
443
    g_signal_new ("sample-point-added",
444 445 446 447 448 449 450 451 452
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, sample_point_added),
                  NULL, NULL,
                  gimp_marshal_VOID__POINTER,
                  G_TYPE_NONE, 1,
                  G_TYPE_POINTER);

  gimp_image_signals[SAMPLE_POINT_REMOVED] =
453
    g_signal_new ("sample-point-removed",
454 455 456 457 458 459 460 461
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpImageClass, sample_point_removed),
                  NULL, NULL,
                  gimp_marshal_VOID__POINTER,
                  G_TYPE_NONE, 1,
                  G_TYPE_POINTER);

462 463 464 465 466 467 468 469 470 471
  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,
                  gimp_marshal_VOID__POINTER,
                  G_TYPE_NONE, 1,
                  G_TYPE_POINTER);

472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491
  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);

492
  gimp_image_signals[COLORMAP_CHANGED] =
493
    g_signal_new ("colormap-changed",
494 495 496 497 498 499 500
                  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);
501

502
  gimp_image_signals[UNDO_EVENT] =
503
    g_signal_new ("undo-event",
504 505 506 507 508 509 510
                  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,
511
                  GIMP_TYPE_UNDO);
512

513
  object_class->constructed           = gimp_image_constructed;
514 515
  object_class->set_property          = gimp_image_set_property;
  object_class->get_property          = gimp_image_get_property;
516 517
  object_class->dispose               = gimp_image_dispose;
  object_class->finalize              = gimp_image_finalize;
518

519
  gimp_object_class->name_changed     = gimp_image_name_changed;
520
  gimp_object_class->get_memsize      = gimp_image_get_memsize;
521

522
  viewable_class->default_stock_id    = "gimp-image";
523
  viewable_class->get_size            = gimp_image_get_size;
524
  viewable_class->size_changed        = gimp_image_size_changed;
525
  viewable_class->get_preview_size    = gimp_image_get_preview_size;
526
  viewable_class->get_popup_size      = gimp_image_get_popup_size;
527
  viewable_class->get_new_preview     = gimp_image_get_new_preview;
528
  viewable_class->get_description     = gimp_image_get_description;
529

530
  klass->mode_changed                 = gimp_image_real_mode_changed;
531
  klass->precision_changed            = gimp_image_real_precision_changed;
532
  klass->alpha_changed                = NULL;
533
  klass->floating_selection_changed   = NULL;
534 535
  klass->active_layer_changed         = NULL;
  klass->active_channel_changed       = NULL;
Michael Natterer's avatar
Michael Natterer committed
536
  klass->active_vectors_changed       = NULL;
537 538
  klass->component_visibility_changed = NULL;
  klass->component_active_changed     = NULL;
539
  klass->mask_changed                 = NULL;
540 541 542 543
  klass->resolution_changed           = NULL;
  klass->size_changed_detailed        = gimp_image_real_size_changed_detailed;
  klass->unit_changed                 = NULL;
  klass->quick_mask_changed           = NULL;
544
  klass->selection_invalidate         = NULL;
545

546 547
  klass->clean                        = NULL;
  klass->dirty                        = NULL;
548
  klass->saved                        = NULL;
549
  klass->exported                     = NULL;
550 551 552
  klass->guide_added                  = NULL;
  klass->guide_removed                = NULL;
  klass->guide_moved                  = NULL;
553 554
  klass->sample_point_added           = NULL;
  klass->sample_point_removed         = NULL;
555
  klass->sample_point_moved           = NULL;
556 557
  klass->parasite_attached            = NULL;
  klass->parasite_detached            = NULL;
Michael Natterer's avatar
Michael Natterer committed
558
  klass->colormap_changed             = gimp_image_real_colormap_changed;
559
  klass->undo_event                   = NULL;
560

561 562 563
  g_object_class_install_property (object_class, PROP_GIMP,
                                   g_param_spec_object ("gimp", NULL, NULL,
                                                        GIMP_TYPE_GIMP,
564
                                                        GIMP_PARAM_READWRITE |
565 566 567 568 569
                                                        G_PARAM_CONSTRUCT_ONLY));

  g_object_class_install_property (object_class, PROP_ID,
                                   g_param_spec_int ("id", NULL, NULL,
                                                     0, G_MAXINT, 0,
570
                                                     GIMP_PARAM_READABLE));
571 572 573 574

  g_object_class_install_property (object_class, PROP_WIDTH,
                                   g_param_spec_int ("width", NULL, NULL,
                                                     1, GIMP_MAX_IMAGE_SIZE, 1,
575
                                                     GIMP_PARAM_READWRITE |
576 577 578 579 580
                                                     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,
581
                                                     GIMP_PARAM_READWRITE |
582 583 584 585 586 587
                                                     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,
588
                                                      GIMP_PARAM_READWRITE |
589 590
                                                      G_PARAM_CONSTRUCT));

591 592 593
  g_object_class_install_property (object_class, PROP_PRECISION,
                                   g_param_spec_enum ("precision", NULL, NULL,
                                                      GIMP_TYPE_PRECISION,
594
                                                      GIMP_PRECISION_U8_GAMMA,
595 596 597
                                                      GIMP_PARAM_READWRITE |
                                                      G_PARAM_CONSTRUCT));

598
  g_type_class_add_private (klass, sizeof (GimpImagePrivate));
599 600
}

601 602 603 604 605 606
static void
gimp_color_managed_iface_init (GimpColorManagedInterface *iface)
{
  iface->get_icc_profile = gimp_image_get_icc_profile;
}

607 608 609
static void
gimp_projectable_iface_init (GimpProjectableInterface *iface)
{
610 611
  iface->flush              = gimp_image_projectable_flush;
  iface->get_image          = gimp_image_get_image;
612
  iface->get_format         = gimp_image_get_proj_format;
613
  iface->get_size           = (void (*) (GimpProjectable*, gint*, gint*)) gimp_image_get_size;
614
  iface->get_graph          = gimp_image_get_graph;
615
  iface->invalidate_preview = (void (*) (GimpProjectable*)) gimp_viewable_invalidate_preview;
616 617
}

618
static void
619
gimp_image_init (GimpImage *image)
620
{
621 622
  GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image);
  gint              i;
623

624
  private->ID                  = 0;
625

626 627
  private->load_proc           = NULL;
  private->save_proc           = NULL;
628

629 630 631 632 633 634
  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;
635
  private->precision           = GIMP_PRECISION_U8_GAMMA;
636

637 638
  private->colormap            = NULL;
  private->n_colors            = 0;
639
  private->palette             = NULL;
640

641 642 643
  private->dirty               = 1;
  private->dirty_time          = 0;
  private->undo_freeze_count   = 0;
644

645
  private->export_dirty        = 1;
646

647 648
  private->instance_count      = 0;
  private->disp_count          = 0;
649

650
  private->tattoo_state        = 0;
651

652
  private->projection          = gimp_projection_new (GIMP_PROJECTABLE (image));
653

654 655 656
  private->guides              = NULL;
  private->grid                = NULL;
  private->sample_points       = NULL;
657

658 659
  private->layers              = gimp_item_tree_new (image,
                                                     GIMP_TYPE_DRAWABLE_STACK,
660
                                                     GIMP_TYPE_LAYER);
661 662
  private->channels            = gimp_item_tree_new (image,
                                                     GIMP_TYPE_DRAWABLE_STACK,
663
                                                     GIMP_TYPE_CHANNEL);
664 665
  private->vectors             = gimp_item_tree_new (image,
                                                     GIMP_TYPE_ITEM_STACK,
666
                                                     GIMP_TYPE_VECTORS);
667
  private->layer_stack         = NULL;
668

669 670 671 672 673 674 675 676 677 678
  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);

679
  g_signal_connect_swapped (private->layers->container, "update",
680
                            G_CALLBACK (gimp_image_invalidate),
681 682
                            image);

683
  private->layer_alpha_handler =
684
    gimp_container_add_handler (private->layers->container, "alpha-changed",
685
                                G_CALLBACK (gimp_image_layer_alpha_changed),
686
                                image);
687

688
  g_signal_connect_swapped (private->channels->container, "update",
689
                            G_CALLBACK (gimp_image_invalidate),
690 691
                            image);

692
  private->channel_name_changed_handler =
693
    gimp_container_add_handler (private->channels->container, "name-changed",
694
                                G_CALLBACK (gimp_image_channel_name_changed),
695
                                image);
696
  private->channel_color_changed_handler =
697
    gimp_container_add_handler (private->channels->container, "color-changed",
698
                                G_CALLBACK (gimp_image_channel_color_changed),
699
                                image);
700

701
  g_signal_connect (private->channels->container, "add",
702
                    G_CALLBACK (gimp_image_channel_add),
703
                    image);
704
  g_signal_connect (private->channels->container, "remove",
705
                    G_CALLBACK (gimp_image_channel_remove),
706
                    image);
707

708 709
  private->floating_sel        = NULL;
  private->selection_mask      = NULL;
710

711
  private->parasites           = gimp_parasite_list_new ();
712

713 714
  for (i = 0; i < MAX_CHANNELS; i++)
    {
715 716
      private->visible[i] = TRUE;
      private->active[i]  = TRUE;
717 718
    }

719 720 721
  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);
722

723 724 725 726
  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;
727

728 729 730 731
  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;
732 733
}

734 735
static void
gimp_image_constructed (GObject *object)
736
{
737 738
  GimpImage        *image   = GIMP_IMAGE (object);
  GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image);
739
  GimpChannel      *selection;
740
  GimpCoreConfig   *config;
741
  GimpTemplate     *template;
742

743
  G_OBJECT_CLASS (parent_class)->constructed (object);
744

745
  g_assert (GIMP_IS_GIMP (image->gimp));
746

747
  config = image->gimp->config;
748

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

751 752 753 754 755
  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);
756

757
  private->grid = gimp_config_duplicate (GIMP_CONFIG (config->default_grid));
758

759 760
  private->quick_mask_color = config->quick_mask_color;

761 762
  if (private->base_type == GIMP_INDEXED)
    gimp_image_colormap_init (image);
763

764 765 766 767
  selection = gimp_selection_new (image,
                                  gimp_image_get_width  (image),
                                  gimp_image_get_height (image));
  gimp_image_take_mask (image, selection);
768 769

  g_signal_connect_object (config, "notify::transparency-type",
770
                           G_CALLBACK (gimp_item_stack_invalidate_previews),
771
                           private->layers->container, G_CONNECT_SWAPPED);
772
  g_signal_connect_object (config, "notify::transparency-size",
773
                           G_CALLBACK (gimp_item_stack_invalidate_previews),
774
                           private->layers->container, G_CONNECT_SWAPPED);
775 776
  g_signal_connect_object (config, "notify::layer-previews",
                           G_CALLBACK (gimp_viewable_size_changed),
777
                           image, G_CONNECT_SWAPPED);
778

779
  gimp_container_add (image->gimp->images, GIMP_OBJECT (image));
780 781 782 783 784 785 786 787
}

static void
gimp_image_set_property (GObject      *object,
                         guint         property_id,
                         const GValue *value,
                         GParamSpec   *pspec)
{
788 789
  GimpImage        *image   = GIMP_IMAGE (object);
  GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image);
790 791 792 793

  switch (property_id)
    {
    case PROP_GIMP:
794
      image->gimp = g_value_get_object (value);
795 796 797 798 799
      break;
    case PROP_ID:
      g_assert_not_reached ();
      break;
    case PROP_WIDTH:
800
      private->width = g_value_get_int (value);
801 802
      break;
    case PROP_HEIGHT:
803
      private->height = g_value_get_int (value);
804 805
      break;
    case PROP_BASE_TYPE:
806
      private->base_type = g_value_get_enum (value);
807
      break;
808 809 810
    case PROP_PRECISION:
      private->precision = g_value_get_enum (value);
      break;
811 812 813 814 815 816 817 818 819 820 821 822
    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)
{
823 824
  GimpImage        *image   = GIMP_IMAGE (object);
  GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image);
825 826 827 828

  switch (property_id)
    {
    case PROP_GIMP:
829
      g_value_set_object (value, image->gimp);
830 831
      break;
    case PROP_ID:
832
      g_value_set_int (value, private->ID);
833 834
      break;
    case PROP_WIDTH:
835
      g_value_set_int (value, private->width);
836 837
      break;
    case PROP_HEIGHT:
838
      g_value_set_int (value, private->height);
839 840
      break;
    case PROP_BASE_TYPE:
841
      g_value_set_enum (value, private->base_type);
842
      break;
843 844 845
    case PROP_PRECISION:
      g_value_set_enum (value, private->precision);
      break;
846 847 848 849 850 851
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}

852
static void
853 854
gimp_image_dispose (GObject *object)
{
855 856
  GimpImage        *image   = GIMP_IMAGE (object);
  GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image);
857

858 859 860
  if (private->colormap)
    gimp_image_colormap_dispose (image);

861
  gimp_image_undo_free (image);
862

863
  g_signal_handlers_disconnect_by_func (private->layers->container,
864
                                        gimp_image_invalidate,
865 866
                                        image);

867
  gimp_container_remove_handler (private->layers->container,
868
                                 private->layer_alpha_handler);
869

870
  g_signal_handlers_disconnect_by_func (private->channels->container,
871
                                        gimp_image_invalidate,
872 873
                                        image);

874
  gimp_container_remove_handler (private->channels->container,
875
                                 private->channel_name_changed_handler);
876
  gimp_container_remove_handler (private->channels->container,
877
                                 private->channel_color_changed_handler);
878

879
  g_signal_handlers_disconnect_by_func (private->channels->container,
Michael Natterer's avatar