1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
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 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * 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 #include "config.h"
19
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include <gdk-pixbuf/gdk-pixbuf.h>
24 #include <gegl.h>
25
26 #include "libgimpbase/gimpbase.h"
27 #include "libgimpmath/gimpmath.h"
28
29 #include "core-types.h"
30
31 #include "gimp.h"
32 #include "gimp-parasites.h"
33 #include "gimpchannel.h"
34 #include "gimpcontainer.h"
35 #include "gimpidtable.h"
36 #include "gimpimage.h"
37 #include "gimpimage-undo.h"
38 #include "gimpimage-undo-push.h"
39 #include "gimpitem.h"
40 #include "gimpitem-linked.h"
41 #include "gimpitem-preview.h"
42 #include "gimpitemtree.h"
43 #include "gimplist.h"
44 #include "gimpmarshal.h"
45 #include "gimpparasitelist.h"
46 #include "gimpprogress.h"
47 #include "gimpstrokeoptions.h"
48
49 #include "paint/gimppaintoptions.h"
50
51 #include "gimp-intl.h"
52
53
54 enum
55 {
56 REMOVED,
57 VISIBILITY_CHANGED,
58 LINKED_CHANGED,
59 COLOR_TAG_CHANGED,
60 LOCK_CONTENT_CHANGED,
61 LOCK_POSITION_CHANGED,
62 LAST_SIGNAL
63 };
64
65 enum
66 {
67 PROP_0,
68 PROP_IMAGE,
69 PROP_ID,
70 PROP_WIDTH,
71 PROP_HEIGHT,
72 PROP_OFFSET_X,
73 PROP_OFFSET_Y,
74 PROP_VISIBLE,
75 PROP_LINKED,
76 PROP_COLOR_TAG,
77 PROP_LOCK_CONTENT,
78 PROP_LOCK_POSITION
79 };
80
81
82 typedef struct _GimpItemPrivate GimpItemPrivate;
83
84 struct _GimpItemPrivate
85 {
86 gint ID; /* provides a unique ID */
87 guint32 tattoo; /* provides a permanent ID */
88
89 GimpImage *image; /* item owner */
90
91 GimpParasiteList *parasites; /* Plug-in parasite data */
92
93 gint width, height; /* size in pixels */
94 gint offset_x, offset_y; /* pixel offset in image */
95
96 guint visible : 1; /* item visibility */
97 guint bind_visible_to_active : 1; /* visibility bound to active */
98
99 guint linked : 1; /* control linkage */
100 guint lock_content : 1; /* content editability */
101 guint lock_position : 1; /* content movability */
102
103 guint removed : 1; /* removed from the image? */
104
105 GimpColorTag color_tag; /* color tag */
106
107 GList *offset_nodes; /* offset nodes to manage */
108 };
109
110 #define GET_PRIVATE(item) ((GimpItemPrivate *) gimp_item_get_instance_private ((GimpItem *) (item)))
111
112
113 /* local function prototypes */
114
115 static void gimp_item_constructed (GObject *object);
116 static void gimp_item_finalize (GObject *object);
117 static void gimp_item_set_property (GObject *object,
118 guint property_id,
119 const GValue *value,
120 GParamSpec *pspec);
121 static void gimp_item_get_property (GObject *object,
122 guint property_id,
123 GValue *value,
124 GParamSpec *pspec);
125
126 static gint64 gimp_item_get_memsize (GimpObject *object,
127 gint64 *gui_size);
128
129 static gboolean gimp_item_real_is_content_locked (GimpItem *item);
130 static gboolean gimp_item_real_is_position_locked (GimpItem *item);
131 static gboolean gimp_item_real_bounds (GimpItem *item,
132 gdouble *x,
133 gdouble *y,
134 gdouble *width,
135 gdouble *height);
136 static GimpItem * gimp_item_real_duplicate (GimpItem *item,
137 GType new_type);
138 static void gimp_item_real_convert (GimpItem *item,
139 GimpImage *dest_image,
140 GType old_type);
141 static gboolean gimp_item_real_rename (GimpItem *item,
142 const gchar *new_name,
143 const gchar *undo_desc,
144 GError **error);
145 static void gimp_item_real_start_transform (GimpItem *item,
146 gboolean push_undo);
147 static void gimp_item_real_end_transform (GimpItem *item,
148 gboolean push_undo);
149 static void gimp_item_real_translate (GimpItem *item,
150 gdouble offset_x,
151 gdouble offset_y,
152 gboolean push_undo);
153 static void gimp_item_real_scale (GimpItem *item,
154 gint new_width,
155 gint new_height,
156 gint new_offset_x,
157 gint new_offset_y,
158 GimpInterpolationType interpolation,
159 GimpProgress *progress);
160 static void gimp_item_real_resize (GimpItem *item,
161 GimpContext *context,
162 GimpFillType fill_type,
163 gint new_width,
164 gint new_height,
165 gint offset_x,
166 gint offset_y);
167 static GimpTransformResize
168 gimp_item_real_get_clip (GimpItem *item,
169 GimpTransformResize clip_result);
170
171
172
173 G_DEFINE_TYPE_WITH_PRIVATE (GimpItem, gimp_item, GIMP_TYPE_FILTER)
174
175 #define parent_class gimp_item_parent_class
176
177 static guint gimp_item_signals[LAST_SIGNAL] = { 0 };
178
179
180 static void
gimp_item_class_init(GimpItemClass * klass)181 gimp_item_class_init (GimpItemClass *klass)
182 {
183 GObjectClass *object_class = G_OBJECT_CLASS (klass);
184 GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);
185 GimpViewableClass *viewable_class = GIMP_VIEWABLE_CLASS (klass);
186
187 gimp_item_signals[REMOVED] =
188 g_signal_new ("removed",
189 G_TYPE_FROM_CLASS (klass),
190 G_SIGNAL_RUN_FIRST,
191 G_STRUCT_OFFSET (GimpItemClass, removed),
192 NULL, NULL,
193 gimp_marshal_VOID__VOID,
194 G_TYPE_NONE, 0);
195
196 gimp_item_signals[VISIBILITY_CHANGED] =
197 g_signal_new ("visibility-changed",
198 G_TYPE_FROM_CLASS (klass),
199 G_SIGNAL_RUN_FIRST,
200 G_STRUCT_OFFSET (GimpItemClass, visibility_changed),
201 NULL, NULL,
202 gimp_marshal_VOID__VOID,
203 G_TYPE_NONE, 0);
204
205 gimp_item_signals[LINKED_CHANGED] =
206 g_signal_new ("linked-changed",
207 G_TYPE_FROM_CLASS (klass),
208 G_SIGNAL_RUN_FIRST,
209 G_STRUCT_OFFSET (GimpItemClass, linked_changed),
210 NULL, NULL,
211 gimp_marshal_VOID__VOID,
212 G_TYPE_NONE, 0);
213
214 gimp_item_signals[COLOR_TAG_CHANGED] =
215 g_signal_new ("color-tag-changed",
216 G_TYPE_FROM_CLASS (klass),
217 G_SIGNAL_RUN_FIRST,
218 G_STRUCT_OFFSET (GimpItemClass, color_tag_changed),
219 NULL, NULL,
220 gimp_marshal_VOID__VOID,
221 G_TYPE_NONE, 0);
222
223 gimp_item_signals[LOCK_CONTENT_CHANGED] =
224 g_signal_new ("lock-content-changed",
225 G_TYPE_FROM_CLASS (klass),
226 G_SIGNAL_RUN_FIRST,
227 G_STRUCT_OFFSET (GimpItemClass, lock_content_changed),
228 NULL, NULL,
229 gimp_marshal_VOID__VOID,
230 G_TYPE_NONE, 0);
231
232 gimp_item_signals[LOCK_POSITION_CHANGED] =
233 g_signal_new ("lock-position-changed",
234 G_TYPE_FROM_CLASS (klass),
235 G_SIGNAL_RUN_FIRST,
236 G_STRUCT_OFFSET (GimpItemClass, lock_position_changed),
237 NULL, NULL,
238 gimp_marshal_VOID__VOID,
239 G_TYPE_NONE, 0);
240
241 object_class->constructed = gimp_item_constructed;
242 object_class->finalize = gimp_item_finalize;
243 object_class->set_property = gimp_item_set_property;
244 object_class->get_property = gimp_item_get_property;
245
246 gimp_object_class->get_memsize = gimp_item_get_memsize;
247
248 viewable_class->name_editable = TRUE;
249 viewable_class->get_preview_size = gimp_item_get_preview_size;
250 viewable_class->get_popup_size = gimp_item_get_popup_size;
251
252 klass->removed = NULL;
253 klass->visibility_changed = NULL;
254 klass->linked_changed = NULL;
255 klass->color_tag_changed = NULL;
256 klass->lock_content_changed = NULL;
257 klass->lock_position_changed = NULL;
258
259 klass->unset_removed = NULL;
260 klass->is_attached = NULL;
261 klass->is_content_locked = gimp_item_real_is_content_locked;
262 klass->is_position_locked = gimp_item_real_is_position_locked;
263 klass->get_tree = NULL;
264 klass->bounds = gimp_item_real_bounds;
265 klass->duplicate = gimp_item_real_duplicate;
266 klass->convert = gimp_item_real_convert;
267 klass->rename = gimp_item_real_rename;
268 klass->start_move = NULL;
269 klass->end_move = NULL;
270 klass->start_transform = gimp_item_real_start_transform;
271 klass->end_transform = gimp_item_real_end_transform;
272 klass->translate = gimp_item_real_translate;
273 klass->scale = gimp_item_real_scale;
274 klass->resize = gimp_item_real_resize;
275 klass->flip = NULL;
276 klass->rotate = NULL;
277 klass->transform = NULL;
278 klass->get_clip = gimp_item_real_get_clip;
279 klass->fill = NULL;
280 klass->stroke = NULL;
281 klass->to_selection = NULL;
282
283 klass->default_name = NULL;
284 klass->rename_desc = NULL;
285 klass->translate_desc = NULL;
286 klass->scale_desc = NULL;
287 klass->resize_desc = NULL;
288 klass->flip_desc = NULL;
289 klass->rotate_desc = NULL;
290 klass->transform_desc = NULL;
291 klass->fill_desc = NULL;
292 klass->stroke_desc = NULL;
293
294 g_object_class_install_property (object_class, PROP_IMAGE,
295 g_param_spec_object ("image", NULL, NULL,
296 GIMP_TYPE_IMAGE,
297 GIMP_PARAM_READWRITE |
298 G_PARAM_CONSTRUCT));
299 g_object_class_install_property (object_class, PROP_ID,
300 g_param_spec_int ("id", NULL, NULL,
301 0, G_MAXINT, 0,
302 GIMP_PARAM_READABLE));
303
304 g_object_class_install_property (object_class, PROP_WIDTH,
305 g_param_spec_int ("width", NULL, NULL,
306 1, GIMP_MAX_IMAGE_SIZE, 1,
307 GIMP_PARAM_READABLE));
308
309 g_object_class_install_property (object_class, PROP_HEIGHT,
310 g_param_spec_int ("height", NULL, NULL,
311 1, GIMP_MAX_IMAGE_SIZE, 1,
312 GIMP_PARAM_READABLE));
313
314 g_object_class_install_property (object_class, PROP_OFFSET_X,
315 g_param_spec_int ("offset-x", NULL, NULL,
316 -GIMP_MAX_IMAGE_SIZE,
317 GIMP_MAX_IMAGE_SIZE, 0,
318 GIMP_PARAM_READABLE));
319
320 g_object_class_install_property (object_class, PROP_OFFSET_Y,
321 g_param_spec_int ("offset-y", NULL, NULL,
322 -GIMP_MAX_IMAGE_SIZE,
323 GIMP_MAX_IMAGE_SIZE, 0,
324 GIMP_PARAM_READABLE));
325
326 g_object_class_install_property (object_class, PROP_VISIBLE,
327 g_param_spec_boolean ("visible", NULL, NULL,
328 TRUE,
329 GIMP_PARAM_READABLE));
330
331 g_object_class_install_property (object_class, PROP_LINKED,
332 g_param_spec_boolean ("linked", NULL, NULL,
333 FALSE,
334 GIMP_PARAM_READABLE));
335
336 g_object_class_install_property (object_class, PROP_COLOR_TAG,
337 g_param_spec_enum ("color-tag", NULL, NULL,
338 GIMP_TYPE_COLOR_TAG,
339 GIMP_COLOR_TAG_NONE,
340 GIMP_PARAM_READABLE));
341
342 g_object_class_install_property (object_class, PROP_LOCK_CONTENT,
343 g_param_spec_boolean ("lock-content",
344 NULL, NULL,
345 FALSE,
346 GIMP_PARAM_READABLE));
347
348 g_object_class_install_property (object_class, PROP_LOCK_POSITION,
349 g_param_spec_boolean ("lock-position",
350 NULL, NULL,
351 FALSE,
352 GIMP_PARAM_READABLE));
353 }
354
355 static void
gimp_item_init(GimpItem * item)356 gimp_item_init (GimpItem *item)
357 {
358 GimpItemPrivate *private = GET_PRIVATE (item);
359
360 g_object_force_floating (G_OBJECT (item));
361
362 private->parasites = gimp_parasite_list_new ();
363 private->visible = TRUE;
364 private->bind_visible_to_active = TRUE;
365 }
366
367 static void
gimp_item_constructed(GObject * object)368 gimp_item_constructed (GObject *object)
369 {
370 GimpItemPrivate *private = GET_PRIVATE (object);
371
372 G_OBJECT_CLASS (parent_class)->constructed (object);
373
374 gimp_assert (GIMP_IS_IMAGE (private->image));
375 gimp_assert (private->ID != 0);
376 }
377
378 static void
gimp_item_finalize(GObject * object)379 gimp_item_finalize (GObject *object)
380 {
381 GimpItemPrivate *private = GET_PRIVATE (object);
382
383 if (private->offset_nodes)
384 {
385 g_list_free_full (private->offset_nodes,
386 (GDestroyNotify) g_object_unref);
387 private->offset_nodes = NULL;
388 }
389
390 if (private->image && private->image->gimp)
391 {
392 gimp_id_table_remove (private->image->gimp->item_table, private->ID);
393 private->image = NULL;
394 }
395
396 g_clear_object (&private->parasites);
397
398 G_OBJECT_CLASS (parent_class)->finalize (object);
399 }
400
401 static void
gimp_item_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)402 gimp_item_set_property (GObject *object,
403 guint property_id,
404 const GValue *value,
405 GParamSpec *pspec)
406 {
407 GimpItem *item = GIMP_ITEM (object);
408
409 switch (property_id)
410 {
411 case PROP_IMAGE:
412 gimp_item_set_image (item, g_value_get_object (value));
413 break;
414
415 default:
416 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
417 break;
418 }
419 }
420
421 static void
gimp_item_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)422 gimp_item_get_property (GObject *object,
423 guint property_id,
424 GValue *value,
425 GParamSpec *pspec)
426 {
427 GimpItemPrivate *private = GET_PRIVATE (object);
428
429 switch (property_id)
430 {
431 case PROP_IMAGE:
432 g_value_set_object (value, private->image);
433 break;
434 case PROP_ID:
435 g_value_set_int (value, private->ID);
436 break;
437 case PROP_WIDTH:
438 g_value_set_int (value, private->width);
439 break;
440 case PROP_HEIGHT:
441 g_value_set_int (value, private->height);
442 break;
443 case PROP_OFFSET_X:
444 g_value_set_int (value, private->offset_x);
445 break;
446 case PROP_OFFSET_Y:
447 g_value_set_int (value, private->offset_y);
448 break;
449 case PROP_VISIBLE:
450 g_value_set_boolean (value, private->visible);
451 break;
452 case PROP_LINKED:
453 g_value_set_boolean (value, private->linked);
454 break;
455 case PROP_COLOR_TAG:
456 g_value_set_enum (value, private->color_tag);
457 break;
458 case PROP_LOCK_CONTENT:
459 g_value_set_boolean (value, private->lock_content);
460 break;
461 case PROP_LOCK_POSITION:
462 g_value_set_boolean (value, private->lock_position);
463 break;
464
465 default:
466 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
467 break;
468 }
469 }
470
471 static gint64
gimp_item_get_memsize(GimpObject * object,gint64 * gui_size)472 gimp_item_get_memsize (GimpObject *object,
473 gint64 *gui_size)
474 {
475 GimpItemPrivate *private = GET_PRIVATE (object);
476 gint64 memsize = 0;
477
478 memsize += gimp_object_get_memsize (GIMP_OBJECT (private->parasites),
479 gui_size);
480
481 return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
482 gui_size);
483 }
484
485 static gboolean
gimp_item_real_is_content_locked(GimpItem * item)486 gimp_item_real_is_content_locked (GimpItem *item)
487 {
488 GimpItem *parent = gimp_item_get_parent (item);
489
490 if (parent && gimp_item_is_content_locked (parent))
491 return TRUE;
492
493 return GET_PRIVATE (item)->lock_content;
494 }
495
496 static gboolean
gimp_item_real_is_position_locked(GimpItem * item)497 gimp_item_real_is_position_locked (GimpItem *item)
498 {
499 if (gimp_item_get_linked (item))
500 if (gimp_item_linked_is_locked (item))
501 return TRUE;
502
503 return GET_PRIVATE (item)->lock_position;
504 }
505
506 static gboolean
gimp_item_real_bounds(GimpItem * item,gdouble * x,gdouble * y,gdouble * width,gdouble * height)507 gimp_item_real_bounds (GimpItem *item,
508 gdouble *x,
509 gdouble *y,
510 gdouble *width,
511 gdouble *height)
512 {
513 GimpItemPrivate *private = GET_PRIVATE (item);
514
515 *x = 0;
516 *y = 0;
517 *width = private->width;
518 *height = private->height;
519
520 return TRUE;
521 }
522
523 static GimpItem *
gimp_item_real_duplicate(GimpItem * item,GType new_type)524 gimp_item_real_duplicate (GimpItem *item,
525 GType new_type)
526 {
527 GimpItemPrivate *private;
528 GimpItem *new_item;
529 gchar *new_name;
530
531 g_return_val_if_fail (GIMP_IS_ITEM (item), NULL);
532
533 private = GET_PRIVATE (item);
534
535 g_return_val_if_fail (GIMP_IS_IMAGE (private->image), NULL);
536 g_return_val_if_fail (g_type_is_a (new_type, GIMP_TYPE_ITEM), NULL);
537
538 /* formulate the new name */
539 {
540 const gchar *name;
541 gint len;
542
543 name = gimp_object_get_name (item);
544
545 g_return_val_if_fail (name != NULL, NULL);
546
547 len = strlen (_("copy"));
548
549 if ((strlen (name) >= len &&
550 strcmp (&name[strlen (name) - len], _("copy")) == 0) ||
551 g_regex_match_simple ("#([0-9]+)\\s*$", name, 0, 0))
552 {
553 /* don't have redundant "copy"s */
554 new_name = g_strdup (name);
555 }
556 else
557 {
558 new_name = g_strdup_printf (_("%s copy"), name);
559 }
560 }
561
562 new_item = gimp_item_new (new_type,
563 gimp_item_get_image (item), new_name,
564 private->offset_x, private->offset_y,
565 gimp_item_get_width (item),
566 gimp_item_get_height (item));
567
568 g_free (new_name);
569
570 gimp_viewable_set_expanded (GIMP_VIEWABLE (new_item),
571 gimp_viewable_get_expanded (GIMP_VIEWABLE (item)));
572
573 g_object_unref (GET_PRIVATE (new_item)->parasites);
574 GET_PRIVATE (new_item)->parasites = gimp_parasite_list_copy (private->parasites);
575
576 gimp_item_set_visible (new_item, gimp_item_get_visible (item), FALSE);
577 gimp_item_set_linked (new_item, gimp_item_get_linked (item), FALSE);
578 gimp_item_set_color_tag (new_item, gimp_item_get_color_tag (item), FALSE);
579
580 if (gimp_item_can_lock_content (new_item))
581 gimp_item_set_lock_content (new_item, gimp_item_get_lock_content (item),
582 FALSE);
583
584 if (gimp_item_can_lock_position (new_item))
585 gimp_item_set_lock_position (new_item, gimp_item_get_lock_position (item),
586 FALSE);
587
588 return new_item;
589 }
590
591 static void
gimp_item_real_convert(GimpItem * item,GimpImage * dest_image,GType old_type)592 gimp_item_real_convert (GimpItem *item,
593 GimpImage *dest_image,
594 GType old_type)
595 {
596 gimp_item_set_image (item, dest_image);
597 }
598
599 static gboolean
gimp_item_real_rename(GimpItem * item,const gchar * new_name,const gchar * undo_desc,GError ** error)600 gimp_item_real_rename (GimpItem *item,
601 const gchar *new_name,
602 const gchar *undo_desc,
603 GError **error)
604 {
605 if (gimp_item_is_attached (item))
606 gimp_item_tree_rename_item (gimp_item_get_tree (item), item,
607 new_name, TRUE, undo_desc);
608 else
609 gimp_object_set_name (GIMP_OBJECT (item), new_name);
610
611 return TRUE;
612 }
613
614 static void
gimp_item_real_translate(GimpItem * item,gdouble offset_x,gdouble offset_y,gboolean push_undo)615 gimp_item_real_translate (GimpItem *item,
616 gdouble offset_x,
617 gdouble offset_y,
618 gboolean push_undo)
619 {
620 GimpItemPrivate *private = GET_PRIVATE (item);
621
622 gimp_item_set_offset (item,
623 private->offset_x + SIGNED_ROUND (offset_x),
624 private->offset_y + SIGNED_ROUND (offset_y));
625 }
626
627 static void
gimp_item_real_start_transform(GimpItem * item,gboolean push_undo)628 gimp_item_real_start_transform (GimpItem *item,
629 gboolean push_undo)
630 {
631 gimp_item_start_move (item, push_undo);
632 }
633
634 static void
gimp_item_real_end_transform(GimpItem * item,gboolean push_undo)635 gimp_item_real_end_transform (GimpItem *item,
636 gboolean push_undo)
637 {
638 gimp_item_end_move (item, push_undo);
639 }
640
641 static void
gimp_item_real_scale(GimpItem * item,gint new_width,gint new_height,gint new_offset_x,gint new_offset_y,GimpInterpolationType interpolation,GimpProgress * progress)642 gimp_item_real_scale (GimpItem *item,
643 gint new_width,
644 gint new_height,
645 gint new_offset_x,
646 gint new_offset_y,
647 GimpInterpolationType interpolation,
648 GimpProgress *progress)
649 {
650 GimpItemPrivate *private = GET_PRIVATE (item);
651
652 if (private->width != new_width)
653 {
654 private->width = new_width;
655 g_object_notify (G_OBJECT (item), "width");
656 }
657
658 if (private->height != new_height)
659 {
660 private->height = new_height;
661 g_object_notify (G_OBJECT (item), "height");
662 }
663
664 gimp_item_set_offset (item, new_offset_x, new_offset_y);
665 }
666
667 static void
gimp_item_real_resize(GimpItem * item,GimpContext * context,GimpFillType fill_type,gint new_width,gint new_height,gint offset_x,gint offset_y)668 gimp_item_real_resize (GimpItem *item,
669 GimpContext *context,
670 GimpFillType fill_type,
671 gint new_width,
672 gint new_height,
673 gint offset_x,
674 gint offset_y)
675 {
676 GimpItemPrivate *private = GET_PRIVATE (item);
677
678 if (private->width != new_width)
679 {
680 private->width = new_width;
681 g_object_notify (G_OBJECT (item), "width");
682 }
683
684 if (private->height != new_height)
685 {
686 private->height = new_height;
687 g_object_notify (G_OBJECT (item), "height");
688 }
689
690 gimp_item_set_offset (item,
691 private->offset_x - offset_x,
692 private->offset_y - offset_y);
693 }
694
695 static GimpTransformResize
gimp_item_real_get_clip(GimpItem * item,GimpTransformResize clip_result)696 gimp_item_real_get_clip (GimpItem *item,
697 GimpTransformResize clip_result)
698 {
699 if (gimp_item_get_lock_position (item))
700 return GIMP_TRANSFORM_RESIZE_CLIP;
701 else
702 return clip_result;
703 }
704
705
706 /* public functions */
707
708 /**
709 * gimp_item_new:
710 * @type: The new item's type.
711 * @image: The new item's #GimpImage.
712 * @name: The name to assign the item.
713 * @offset_x: The X offset to assign the item.
714 * @offset_y: The Y offset to assign the item.
715 * @width: The width to assign the item.
716 * @height: The height to assign the item.
717 *
718 * Return value: The newly created item.
719 */
720 GimpItem *
gimp_item_new(GType type,GimpImage * image,const gchar * name,gint offset_x,gint offset_y,gint width,gint height)721 gimp_item_new (GType type,
722 GimpImage *image,
723 const gchar *name,
724 gint offset_x,
725 gint offset_y,
726 gint width,
727 gint height)
728 {
729 GimpItem *item;
730 GimpItemPrivate *private;
731
732 g_return_val_if_fail (g_type_is_a (type, GIMP_TYPE_ITEM), NULL);
733 g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
734 g_return_val_if_fail (width > 0 && height > 0, NULL);
735
736 item = g_object_new (type,
737 "image", image,
738 NULL);
739
740 private = GET_PRIVATE (item);
741
742 private->width = width;
743 private->height = height;
744 gimp_item_set_offset (item, offset_x, offset_y);
745
746 if (name && strlen (name))
747 gimp_object_set_name (GIMP_OBJECT (item), name);
748 else
749 gimp_object_set_static_name (GIMP_OBJECT (item),
750 GIMP_ITEM_GET_CLASS (item)->default_name);
751
752 return item;
753 }
754
755 /**
756 * gimp_item_remove:
757 * @item: the #GimpItem to remove.
758 *
759 * This function sets the 'removed' flag on @item to #TRUE, and emits
760 * a 'removed' signal on the item.
761 */
762 void
gimp_item_removed(GimpItem * item)763 gimp_item_removed (GimpItem *item)
764 {
765 GimpContainer *children;
766
767 g_return_if_fail (GIMP_IS_ITEM (item));
768
769 GET_PRIVATE (item)->removed = TRUE;
770
771 children = gimp_viewable_get_children (GIMP_VIEWABLE (item));
772
773 if (children)
774 gimp_container_foreach (children, (GFunc) gimp_item_removed, NULL);
775
776 g_signal_emit (item, gimp_item_signals[REMOVED], 0);
777 }
778
779 /**
780 * gimp_item_is_removed:
781 * @item: the #GimpItem to check.
782 *
783 * Returns: %TRUE if the 'removed' flag is set for @item, %FALSE otherwise.
784 */
785 gboolean
gimp_item_is_removed(GimpItem * item)786 gimp_item_is_removed (GimpItem *item)
787 {
788 g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
789
790 return GET_PRIVATE (item)->removed;
791 }
792
793 /**
794 * gimp_item_unset_removed:
795 * @item: a #GimpItem which was on the undo stack
796 *
797 * Unsets an item's "removed" state. This function is called when an
798 * item was on the undo stack and is added back to its parent
799 * container during and undo or redo. It must never be called from
800 * anywhere else.
801 **/
802 void
gimp_item_unset_removed(GimpItem * item)803 gimp_item_unset_removed (GimpItem *item)
804 {
805 GimpContainer *children;
806
807 g_return_if_fail (GIMP_IS_ITEM (item));
808 g_return_if_fail (gimp_item_is_removed (item));
809
810 GET_PRIVATE (item)->removed = FALSE;
811
812 children = gimp_viewable_get_children (GIMP_VIEWABLE (item));
813
814 if (children)
815 gimp_container_foreach (children, (GFunc) gimp_item_unset_removed, NULL);
816
817 if (GIMP_ITEM_GET_CLASS (item)->unset_removed)
818 GIMP_ITEM_GET_CLASS (item)->unset_removed (item);
819 }
820
821 /**
822 * gimp_item_is_attached:
823 * @item: The #GimpItem to check.
824 *
825 * Returns: %TRUE if the item is attached to an image, %FALSE otherwise.
826 */
827 gboolean
gimp_item_is_attached(GimpItem * item)828 gimp_item_is_attached (GimpItem *item)
829 {
830 GimpItem *parent;
831
832 g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
833
834 parent = gimp_item_get_parent (item);
835
836 if (parent)
837 return gimp_item_is_attached (parent);
838
839 return GIMP_ITEM_GET_CLASS (item)->is_attached (item);
840 }
841
842 GimpItem *
gimp_item_get_parent(GimpItem * item)843 gimp_item_get_parent (GimpItem *item)
844 {
845 g_return_val_if_fail (GIMP_IS_ITEM (item), NULL);
846
847 return GIMP_ITEM (gimp_viewable_get_parent (GIMP_VIEWABLE (item)));
848 }
849
850 GimpItemTree *
gimp_item_get_tree(GimpItem * item)851 gimp_item_get_tree (GimpItem *item)
852 {
853 g_return_val_if_fail (GIMP_IS_ITEM (item), NULL);
854
855 if (GIMP_ITEM_GET_CLASS (item)->get_tree)
856 return GIMP_ITEM_GET_CLASS (item)->get_tree (item);
857
858 return NULL;
859 }
860
861 GimpContainer *
gimp_item_get_container(GimpItem * item)862 gimp_item_get_container (GimpItem *item)
863 {
864 GimpItem *parent;
865 GimpItemTree *tree;
866
867 g_return_val_if_fail (GIMP_IS_ITEM (item), NULL);
868
869 parent = gimp_item_get_parent (item);
870
871 if (parent)
872 return gimp_viewable_get_children (GIMP_VIEWABLE (parent));
873
874 tree = gimp_item_get_tree (item);
875
876 if (tree)
877 return tree->container;
878
879 return NULL;
880 }
881
882 GList *
gimp_item_get_container_iter(GimpItem * item)883 gimp_item_get_container_iter (GimpItem *item)
884 {
885 GimpContainer *container;
886
887 g_return_val_if_fail (GIMP_IS_ITEM (item), NULL);
888
889 container = gimp_item_get_container (item);
890
891 if (container)
892 return GIMP_LIST (container)->queue->head;
893
894 return NULL;
895 }
896
897 gint
gimp_item_get_index(GimpItem * item)898 gimp_item_get_index (GimpItem *item)
899 {
900 GimpContainer *container;
901
902 g_return_val_if_fail (GIMP_IS_ITEM (item), -1);
903
904 container = gimp_item_get_container (item);
905
906 if (container)
907 return gimp_container_get_child_index (container, GIMP_OBJECT (item));
908
909 return -1;
910 }
911
912 GList *
gimp_item_get_path(GimpItem * item)913 gimp_item_get_path (GimpItem *item)
914 {
915 GimpContainer *container;
916 GList *path = NULL;
917
918 g_return_val_if_fail (GIMP_IS_ITEM (item), NULL);
919 g_return_val_if_fail (gimp_item_is_attached (item), NULL);
920
921 container = gimp_item_get_container (item);
922
923 while (container)
924 {
925 guint32 index = gimp_container_get_child_index (container,
926 GIMP_OBJECT (item));
927
928 path = g_list_prepend (path, GUINT_TO_POINTER (index));
929
930 item = gimp_item_get_parent (item);
931
932 if (item)
933 container = gimp_item_get_container (item);
934 else
935 container = NULL;
936 }
937
938 return path;
939 }
940
941 gboolean
gimp_item_bounds(GimpItem * item,gint * x,gint * y,gint * width,gint * height)942 gimp_item_bounds (GimpItem *item,
943 gint *x,
944 gint *y,
945 gint *width,
946 gint *height)
947 {
948 gdouble tmp_x, tmp_y, tmp_width, tmp_height;
949 gboolean retval;
950
951 g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
952
953 retval = GIMP_ITEM_GET_CLASS (item)->bounds (item,
954 &tmp_x, &tmp_y,
955 &tmp_width, &tmp_height);
956
957 if (x) *x = floor (tmp_x);
958 if (y) *y = floor (tmp_y);
959 if (width) *width = ceil (tmp_x + tmp_width) - floor (tmp_x);
960 if (height) *height = ceil (tmp_y + tmp_height) - floor (tmp_y);
961
962 return retval;
963 }
964
965 gboolean
gimp_item_bounds_f(GimpItem * item,gdouble * x,gdouble * y,gdouble * width,gdouble * height)966 gimp_item_bounds_f (GimpItem *item,
967 gdouble *x,
968 gdouble *y,
969 gdouble *width,
970 gdouble *height)
971 {
972 gdouble tmp_x, tmp_y, tmp_width, tmp_height;
973 gboolean retval;
974
975 g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
976
977 retval = GIMP_ITEM_GET_CLASS (item)->bounds (item,
978 &tmp_x, &tmp_y,
979 &tmp_width, &tmp_height);
980
981 if (x) *x = tmp_x;
982 if (y) *y = tmp_y;
983 if (width) *width = tmp_width;
984 if (height) *height = tmp_height;
985
986 return retval;
987 }
988
989 /**
990 * gimp_item_duplicate:
991 * @item: The #GimpItem to duplicate.
992 * @new_type: The type to make the new item.
993 *
994 * Returns: the newly created item.
995 */
996 GimpItem *
gimp_item_duplicate(GimpItem * item,GType new_type)997 gimp_item_duplicate (GimpItem *item,
998 GType new_type)
999 {
1000 GimpItemPrivate *private;
1001
1002 g_return_val_if_fail (GIMP_IS_ITEM (item), NULL);
1003
1004 private = GET_PRIVATE (item);
1005
1006 g_return_val_if_fail (GIMP_IS_IMAGE (private->image), NULL);
1007 g_return_val_if_fail (g_type_is_a (new_type, GIMP_TYPE_ITEM), NULL);
1008
1009 return GIMP_ITEM_GET_CLASS (item)->duplicate (item, new_type);
1010 }
1011
1012 /**
1013 * gimp_item_convert:
1014 * @item: The #GimpItem to convert.
1015 * @dest_image: The #GimpImage in which to place the converted item.
1016 * @new_type: The type to convert the item to.
1017 *
1018 * Returns: the new item that results from the conversion.
1019 */
1020 GimpItem *
gimp_item_convert(GimpItem * item,GimpImage * dest_image,GType new_type)1021 gimp_item_convert (GimpItem *item,
1022 GimpImage *dest_image,
1023 GType new_type)
1024 {
1025 GimpItem *new_item;
1026 GType old_type;
1027
1028 g_return_val_if_fail (GIMP_IS_ITEM (item), NULL);
1029 g_return_val_if_fail (GIMP_IS_IMAGE (GET_PRIVATE (item)->image), NULL);
1030 g_return_val_if_fail (GIMP_IS_IMAGE (dest_image), NULL);
1031 g_return_val_if_fail (g_type_is_a (new_type, GIMP_TYPE_ITEM), NULL);
1032
1033 old_type = G_TYPE_FROM_INSTANCE (item);
1034
1035 new_item = gimp_item_duplicate (item, new_type);
1036
1037 if (new_item)
1038 GIMP_ITEM_GET_CLASS (new_item)->convert (new_item, dest_image, old_type);
1039
1040 return new_item;
1041 }
1042
1043 /**
1044 * gimp_item_rename:
1045 * @item: The #GimpItem to rename.
1046 * @new_name: The new name to give the item.
1047 * @error: Return location for error message.
1048 *
1049 * This function assigns a new name to the item, if the desired name is
1050 * different from the name it already has, and pushes an entry onto the
1051 * undo stack for the item's image. If @new_name is NULL or empty, the
1052 * default name for the item's class is used. If the name is changed,
1053 * the GimpObject::name-changed signal is emitted for the item.
1054 *
1055 * Returns: %TRUE if the @item could be renamed, %FALSE otherwise.
1056 */
1057 gboolean
gimp_item_rename(GimpItem * item,const gchar * new_name,GError ** error)1058 gimp_item_rename (GimpItem *item,
1059 const gchar *new_name,
1060 GError **error)
1061 {
1062 GimpItemClass *item_class;
1063
1064 g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
1065 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1066
1067 item_class = GIMP_ITEM_GET_CLASS (item);
1068
1069 if (! new_name || ! *new_name)
1070 new_name = item_class->default_name;
1071
1072 if (strcmp (new_name, gimp_object_get_name (item)))
1073 return item_class->rename (item, new_name, item_class->rename_desc, error);
1074
1075 return TRUE;
1076 }
1077
1078 /**
1079 * gimp_item_get_width:
1080 * @item: The #GimpItem to check.
1081 *
1082 * Returns: The width of the item.
1083 */
1084 gint
gimp_item_get_width(GimpItem * item)1085 gimp_item_get_width (GimpItem *item)
1086 {
1087 g_return_val_if_fail (GIMP_IS_ITEM (item), -1);
1088
1089 return GET_PRIVATE (item)->width;
1090 }
1091
1092 /**
1093 * gimp_item_get_height:
1094 * @item: The #GimpItem to check.
1095 *
1096 * Returns: The height of the item.
1097 */
1098 gint
gimp_item_get_height(GimpItem * item)1099 gimp_item_get_height (GimpItem *item)
1100 {
1101 g_return_val_if_fail (GIMP_IS_ITEM (item), -1);
1102
1103 return GET_PRIVATE (item)->height;
1104 }
1105
1106 void
gimp_item_set_size(GimpItem * item,gint width,gint height)1107 gimp_item_set_size (GimpItem *item,
1108 gint width,
1109 gint height)
1110 {
1111 GimpItemPrivate *private;
1112
1113 g_return_if_fail (GIMP_IS_ITEM (item));
1114
1115 private = GET_PRIVATE (item);
1116
1117 if (private->width != width ||
1118 private->height != height)
1119 {
1120 g_object_freeze_notify (G_OBJECT (item));
1121
1122 if (private->width != width)
1123 {
1124 private->width = width;
1125 g_object_notify (G_OBJECT (item), "width");
1126 }
1127
1128 if (private->height != height)
1129 {
1130 private->height = height;
1131 g_object_notify (G_OBJECT (item), "height");
1132 }
1133
1134 g_object_thaw_notify (G_OBJECT (item));
1135
1136 gimp_viewable_size_changed (GIMP_VIEWABLE (item));
1137 }
1138 }
1139
1140 /**
1141 * gimp_item_get_offset:
1142 * @item: The #GimpItem to check.
1143 * @offset_x: Return location for the item's X offset.
1144 * @offset_y: Return location for the item's Y offset.
1145 *
1146 * Reveals the X and Y offsets of the item.
1147 */
1148 void
gimp_item_get_offset(GimpItem * item,gint * offset_x,gint * offset_y)1149 gimp_item_get_offset (GimpItem *item,
1150 gint *offset_x,
1151 gint *offset_y)
1152 {
1153 GimpItemPrivate *private;
1154
1155 g_return_if_fail (GIMP_IS_ITEM (item));
1156
1157 private = GET_PRIVATE (item);
1158
1159 if (offset_x) *offset_x = private->offset_x;
1160 if (offset_y) *offset_y = private->offset_y;
1161 }
1162
1163 void
gimp_item_set_offset(GimpItem * item,gint offset_x,gint offset_y)1164 gimp_item_set_offset (GimpItem *item,
1165 gint offset_x,
1166 gint offset_y)
1167 {
1168 GimpItemPrivate *private;
1169 GList *list;
1170
1171 g_return_if_fail (GIMP_IS_ITEM (item));
1172
1173 private = GET_PRIVATE (item);
1174
1175 g_object_freeze_notify (G_OBJECT (item));
1176
1177 if (private->offset_x != offset_x)
1178 {
1179 private->offset_x = offset_x;
1180 g_object_notify (G_OBJECT (item), "offset-x");
1181 }
1182
1183 if (private->offset_y != offset_y)
1184 {
1185 private->offset_y = offset_y;
1186 g_object_notify (G_OBJECT (item), "offset-y");
1187 }
1188
1189 for (list = private->offset_nodes; list; list = g_list_next (list))
1190 {
1191 GeglNode *node = list->data;
1192
1193 gegl_node_set (node,
1194 "x", (gdouble) private->offset_x,
1195 "y", (gdouble) private->offset_y,
1196 NULL);
1197 }
1198
1199 g_object_thaw_notify (G_OBJECT (item));
1200 }
1201
1202 gint
gimp_item_get_offset_x(GimpItem * item)1203 gimp_item_get_offset_x (GimpItem *item)
1204 {
1205 g_return_val_if_fail (GIMP_IS_ITEM (item), 0);
1206
1207 return GET_PRIVATE (item)->offset_x;
1208 }
1209
1210 gint
gimp_item_get_offset_y(GimpItem * item)1211 gimp_item_get_offset_y (GimpItem *item)
1212 {
1213 g_return_val_if_fail (GIMP_IS_ITEM (item), 0);
1214
1215 return GET_PRIVATE (item)->offset_y;
1216 }
1217
1218 void
gimp_item_start_move(GimpItem * item,gboolean push_undo)1219 gimp_item_start_move (GimpItem *item,
1220 gboolean push_undo)
1221 {
1222 g_return_if_fail (GIMP_IS_ITEM (item));
1223
1224 if (GIMP_ITEM_GET_CLASS (item)->start_move)
1225 GIMP_ITEM_GET_CLASS (item)->start_move (item, push_undo);
1226 }
1227
1228 void
gimp_item_end_move(GimpItem * item,gboolean push_undo)1229 gimp_item_end_move (GimpItem *item,
1230 gboolean push_undo)
1231 {
1232 g_return_if_fail (GIMP_IS_ITEM (item));
1233
1234 if (GIMP_ITEM_GET_CLASS (item)->end_move)
1235 GIMP_ITEM_GET_CLASS (item)->end_move (item, push_undo);
1236 }
1237
1238 void
gimp_item_start_transform(GimpItem * item,gboolean push_undo)1239 gimp_item_start_transform (GimpItem *item,
1240 gboolean push_undo)
1241 {
1242 g_return_if_fail (GIMP_IS_ITEM (item));
1243
1244 if (GIMP_ITEM_GET_CLASS (item)->start_transform)
1245 GIMP_ITEM_GET_CLASS (item)->start_transform (item, push_undo);
1246 }
1247
1248 void
gimp_item_end_transform(GimpItem * item,gboolean push_undo)1249 gimp_item_end_transform (GimpItem *item,
1250 gboolean push_undo)
1251 {
1252 g_return_if_fail (GIMP_IS_ITEM (item));
1253
1254 if (GIMP_ITEM_GET_CLASS (item)->end_transform)
1255 GIMP_ITEM_GET_CLASS (item)->end_transform (item, push_undo);
1256 }
1257
1258 /**
1259 * gimp_item_translate:
1260 * @item: The #GimpItem to move.
1261 * @offset_x: Increment to the X offset of the item.
1262 * @offset_y: Increment to the Y offset of the item.
1263 * @push_undo: If #TRUE, create an entry in the image's undo stack
1264 * for this action.
1265 *
1266 * Adds the specified increments to the X and Y offsets for the item.
1267 */
1268 void
gimp_item_translate(GimpItem * item,gdouble offset_x,gdouble offset_y,gboolean push_undo)1269 gimp_item_translate (GimpItem *item,
1270 gdouble offset_x,
1271 gdouble offset_y,
1272 gboolean push_undo)
1273 {
1274 GimpItemClass *item_class;
1275 GimpImage *image;
1276
1277 g_return_if_fail (GIMP_IS_ITEM (item));
1278
1279 item_class = GIMP_ITEM_GET_CLASS (item);
1280 image = gimp_item_get_image (item);
1281
1282 if (! gimp_item_is_attached (item))
1283 push_undo = FALSE;
1284
1285 if (push_undo)
1286 gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_ITEM_DISPLACE,
1287 item_class->translate_desc);
1288
1289 gimp_item_start_transform (item, push_undo);
1290
1291 item_class->translate (item, offset_x, offset_y, push_undo);
1292
1293 gimp_item_end_transform (item, push_undo);
1294
1295 if (push_undo)
1296 gimp_image_undo_group_end (image);
1297 }
1298
1299 /**
1300 * gimp_item_check_scaling:
1301 * @item: Item to check
1302 * @new_width: proposed width of item, in pixels
1303 * @new_height: proposed height of item, in pixels
1304 *
1305 * Scales item dimensions, then snaps them to pixel centers
1306 *
1307 * Returns: #FALSE if any dimension reduces to zero as a result
1308 * of this; otherwise, returns #TRUE.
1309 **/
1310 gboolean
gimp_item_check_scaling(GimpItem * item,gint new_width,gint new_height)1311 gimp_item_check_scaling (GimpItem *item,
1312 gint new_width,
1313 gint new_height)
1314 {
1315 GimpItemPrivate *private;
1316 GimpImage *image;
1317 gdouble img_scale_w;
1318 gdouble img_scale_h;
1319 gint new_item_offset_x;
1320 gint new_item_offset_y;
1321 gint new_item_width;
1322 gint new_item_height;
1323
1324 g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
1325
1326 private = GET_PRIVATE (item);
1327 image = gimp_item_get_image (item);
1328
1329 img_scale_w = ((gdouble) new_width /
1330 (gdouble) gimp_image_get_width (image));
1331 img_scale_h = ((gdouble) new_height /
1332 (gdouble) gimp_image_get_height (image));
1333 new_item_offset_x = SIGNED_ROUND (img_scale_w * private->offset_x);
1334 new_item_offset_y = SIGNED_ROUND (img_scale_h * private->offset_y);
1335 new_item_width = SIGNED_ROUND (img_scale_w * (private->offset_x +
1336 gimp_item_get_width (item))) -
1337 new_item_offset_x;
1338 new_item_height = SIGNED_ROUND (img_scale_h * (private->offset_y +
1339 gimp_item_get_height (item))) -
1340 new_item_offset_y;
1341
1342 return (new_item_width > 0 && new_item_height > 0);
1343 }
1344
1345 void
gimp_item_scale(GimpItem * item,gint new_width,gint new_height,gint new_offset_x,gint new_offset_y,GimpInterpolationType interpolation,GimpProgress * progress)1346 gimp_item_scale (GimpItem *item,
1347 gint new_width,
1348 gint new_height,
1349 gint new_offset_x,
1350 gint new_offset_y,
1351 GimpInterpolationType interpolation,
1352 GimpProgress *progress)
1353 {
1354 GimpItemClass *item_class;
1355 GimpImage *image;
1356 gboolean push_undo;
1357
1358 g_return_if_fail (GIMP_IS_ITEM (item));
1359 g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));
1360
1361 if (new_width < 1 || new_height < 1)
1362 return;
1363
1364 item_class = GIMP_ITEM_GET_CLASS (item);
1365 image = gimp_item_get_image (item);
1366
1367 push_undo = gimp_item_is_attached (item);
1368
1369 if (push_undo)
1370 gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_ITEM_SCALE,
1371 item_class->scale_desc);
1372
1373 gimp_item_start_transform (item, push_undo);
1374
1375 g_object_freeze_notify (G_OBJECT (item));
1376
1377 item_class->scale (item, new_width, new_height, new_offset_x, new_offset_y,
1378 interpolation, progress);
1379
1380 g_object_thaw_notify (G_OBJECT (item));
1381
1382 gimp_item_end_transform (item, push_undo);
1383
1384 if (push_undo)
1385 gimp_image_undo_group_end (image);
1386 }
1387
1388 /**
1389 * gimp_item_scale_by_factors:
1390 * @item: Item to be transformed by explicit width and height factors.
1391 * @w_factor: scale factor to apply to width and horizontal offset
1392 * @h_factor: scale factor to apply to height and vertical offset
1393 * @interpolation:
1394 * @progress:
1395 *
1396 * Scales item dimensions and offsets by uniform width and
1397 * height factors.
1398 *
1399 * Use gimp_item_scale_by_factors() in circumstances when the same
1400 * width and height scaling factors are to be uniformly applied to a
1401 * set of items. In this context, the item's dimensions and offsets
1402 * from the sides of the containing image all change by these
1403 * predetermined factors. By fiat, the fixed point of the transform is
1404 * the upper left hand corner of the image. Returns #FALSE if a
1405 * requested scale factor is zero or if a scaling zero's out a item
1406 * dimension; returns #TRUE otherwise.
1407 *
1408 * Use gimp_item_scale() in circumstances where new item width
1409 * and height dimensions are predetermined instead.
1410 *
1411 * Side effects: Undo set created for item. Old item imagery
1412 * scaled & painted to new item tiles.
1413 *
1414 * Returns: #TRUE, if the scaled item has positive dimensions
1415 * #FALSE if the scaled item has at least one zero dimension
1416 **/
1417 gboolean
gimp_item_scale_by_factors(GimpItem * item,gdouble w_factor,gdouble h_factor,GimpInterpolationType interpolation,GimpProgress * progress)1418 gimp_item_scale_by_factors (GimpItem *item,
1419 gdouble w_factor,
1420 gdouble h_factor,
1421 GimpInterpolationType interpolation,
1422 GimpProgress *progress)
1423 {
1424 return gimp_item_scale_by_factors_with_origin (item,
1425 w_factor, h_factor,
1426 0, 0, 0, 0,
1427 interpolation, progress);
1428 }
1429
1430 /**
1431 * gimp_item_scale_by_factors:
1432 * @item: Item to be transformed by explicit width and height factors.
1433 * @w_factor: scale factor to apply to width and horizontal offset
1434 * @h_factor: scale factor to apply to height and vertical offset
1435 * @origin_x: x-coordinate of the transformation input origin
1436 * @origin_y: y-coordinate of the transformation input origin
1437 * @new_origin_x: x-coordinate of the transformation output origin
1438 * @new_origin_y: y-coordinate of the transformation output origin
1439 * @interpolation:
1440 * @progress:
1441 *
1442 * Same as gimp_item_scale_by_factors(), but with the option to specify
1443 * custom input and output points of origin for the transformation.
1444 *
1445 * Returns: #TRUE, if the scaled item has positive dimensions
1446 * #FALSE if the scaled item has at least one zero dimension
1447 **/
1448 gboolean
gimp_item_scale_by_factors_with_origin(GimpItem * item,gdouble w_factor,gdouble h_factor,gint origin_x,gint origin_y,gint new_origin_x,gint new_origin_y,GimpInterpolationType interpolation,GimpProgress * progress)1449 gimp_item_scale_by_factors_with_origin (GimpItem *item,
1450 gdouble w_factor,
1451 gdouble h_factor,
1452 gint origin_x,
1453 gint origin_y,
1454 gint new_origin_x,
1455 gint new_origin_y,
1456 GimpInterpolationType interpolation,
1457 GimpProgress *progress)
1458 {
1459 GimpItemPrivate *private;
1460 GimpContainer *children;
1461 gint new_width, new_height;
1462 gint new_offset_x, new_offset_y;
1463
1464 g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
1465 g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), FALSE);
1466
1467 private = GET_PRIVATE (item);
1468
1469 if (w_factor <= 0.0 || h_factor <= 0.0)
1470 {
1471 g_warning ("%s: requested width or height scale is non-positive",
1472 G_STRFUNC);
1473 return FALSE;
1474 }
1475
1476 children = gimp_viewable_get_children (GIMP_VIEWABLE (item));
1477
1478 /* avoid discarding empty layer groups */
1479 if (children && gimp_container_is_empty (children))
1480 return TRUE;
1481
1482 new_offset_x = SIGNED_ROUND (w_factor * (private->offset_x - origin_x));
1483 new_offset_y = SIGNED_ROUND (h_factor * (private->offset_y - origin_y));
1484 new_width = SIGNED_ROUND (w_factor * (private->offset_x - origin_x +
1485 gimp_item_get_width (item))) -
1486 new_offset_x;
1487 new_height = SIGNED_ROUND (h_factor * (private->offset_y - origin_y +
1488 gimp_item_get_height (item))) -
1489 new_offset_y;
1490
1491 new_offset_x += new_origin_x;
1492 new_offset_y += new_origin_y;
1493
1494 if (new_width > 0 && new_height > 0)
1495 {
1496 gimp_item_scale (item,
1497 new_width, new_height,
1498 new_offset_x, new_offset_y,
1499 interpolation, progress);
1500 return TRUE;
1501 }
1502
1503 return FALSE;
1504 }
1505
1506 /**
1507 * gimp_item_scale_by_origin:
1508 * @item: The item to be transformed by width & height scale factors
1509 * @new_width: The width that item will acquire
1510 * @new_height: The height that the item will acquire
1511 * @interpolation:
1512 * @progress:
1513 * @local_origin: sets fixed point of the scaling transform. See below.
1514 *
1515 * Sets item dimensions to new_width and
1516 * new_height. Derives vertical and horizontal scaling
1517 * transforms from new width and height. If local_origin is
1518 * #TRUE, the fixed point of the scaling transform coincides
1519 * with the item's center point. Otherwise, the fixed
1520 * point is taken to be [-GimpItem::offset_x, -GimpItem::->offset_y].
1521 *
1522 * Since this function derives scale factors from new and
1523 * current item dimensions, these factors will vary from
1524 * item to item because of aliasing artifacts; factor
1525 * variations among items can be quite large where item
1526 * dimensions approach pixel dimensions. Use
1527 * gimp_item_scale_by_factors() where constant scales are to
1528 * be uniformly applied to a number of items.
1529 *
1530 * Side effects: undo set created for item.
1531 * Old item imagery scaled
1532 * & painted to new item tiles
1533 **/
1534 void
gimp_item_scale_by_origin(GimpItem * item,gint new_width,gint new_height,GimpInterpolationType interpolation,GimpProgress * progress,gboolean local_origin)1535 gimp_item_scale_by_origin (GimpItem *item,
1536 gint new_width,
1537 gint new_height,
1538 GimpInterpolationType interpolation,
1539 GimpProgress *progress,
1540 gboolean local_origin)
1541 {
1542 GimpItemPrivate *private;
1543 gint new_offset_x, new_offset_y;
1544
1545 g_return_if_fail (GIMP_IS_ITEM (item));
1546 g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));
1547
1548 private = GET_PRIVATE (item);
1549
1550 if (new_width == 0 || new_height == 0)
1551 {
1552 g_warning ("%s: requested width or height equals zero", G_STRFUNC);
1553 return;
1554 }
1555
1556 if (local_origin)
1557 {
1558 new_offset_x = (private->offset_x +
1559 ((gimp_item_get_width (item) - new_width) / 2.0));
1560 new_offset_y = (private->offset_y +
1561 ((gimp_item_get_height (item) - new_height) / 2.0));
1562 }
1563 else
1564 {
1565 new_offset_x = (gint) (((gdouble) new_width *
1566 (gdouble) private->offset_x /
1567 (gdouble) gimp_item_get_width (item)));
1568
1569 new_offset_y = (gint) (((gdouble) new_height *
1570 (gdouble) private->offset_y /
1571 (gdouble) gimp_item_get_height (item)));
1572 }
1573
1574 gimp_item_scale (item,
1575 new_width, new_height,
1576 new_offset_x, new_offset_y,
1577 interpolation, progress);
1578 }
1579
1580 void
gimp_item_resize(GimpItem * item,GimpContext * context,GimpFillType fill_type,gint new_width,gint new_height,gint offset_x,gint offset_y)1581 gimp_item_resize (GimpItem *item,
1582 GimpContext *context,
1583 GimpFillType fill_type,
1584 gint new_width,
1585 gint new_height,
1586 gint offset_x,
1587 gint offset_y)
1588 {
1589 GimpItemClass *item_class;
1590 GimpImage *image;
1591 gboolean push_undo;
1592
1593 g_return_if_fail (GIMP_IS_ITEM (item));
1594 g_return_if_fail (GIMP_IS_CONTEXT (context));
1595
1596 if (new_width < 1 || new_height < 1)
1597 return;
1598
1599 item_class = GIMP_ITEM_GET_CLASS (item);
1600 image = gimp_item_get_image (item);
1601
1602 push_undo = gimp_item_is_attached (item);
1603
1604 if (push_undo)
1605 gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_ITEM_RESIZE,
1606 item_class->resize_desc);
1607
1608 /* note that we call gimp_item_start_move(), and not
1609 * gimp_item_start_transform(). whether or not a resize operation should be
1610 * considered a transform operation, or a move operation, depends on the
1611 * intended use of these functions by subclasses. atm, we only use
1612 * gimp_item_{start,end}_transform() to suspend mask resizing in group
1613 * layers, which should not happen when reisizing a group, hence the call to
1614 * gimp_item_start_move().
1615 *
1616 * see the comment in gimp_group_layer_resize() for more information.
1617 */
1618 gimp_item_start_move (item, push_undo);
1619
1620 g_object_freeze_notify (G_OBJECT (item));
1621
1622 item_class->resize (item, context, fill_type,
1623 new_width, new_height, offset_x, offset_y);
1624
1625 g_object_thaw_notify (G_OBJECT (item));
1626
1627 gimp_item_end_move (item, push_undo);
1628
1629 if (push_undo)
1630 gimp_image_undo_group_end (image);
1631 }
1632
1633 void
gimp_item_flip(GimpItem * item,GimpContext * context,GimpOrientationType flip_type,gdouble axis,gboolean clip_result)1634 gimp_item_flip (GimpItem *item,
1635 GimpContext *context,
1636 GimpOrientationType flip_type,
1637 gdouble axis,
1638 gboolean clip_result)
1639 {
1640 GimpItemClass *item_class;
1641 GimpImage *image;
1642 gboolean push_undo;
1643
1644 g_return_if_fail (GIMP_IS_ITEM (item));
1645 g_return_if_fail (gimp_item_is_attached (item));
1646 g_return_if_fail (GIMP_IS_CONTEXT (context));
1647
1648 item_class = GIMP_ITEM_GET_CLASS (item);
1649 image = gimp_item_get_image (item);
1650
1651 push_undo = gimp_item_is_attached (item);
1652
1653 if (push_undo)
1654 gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_TRANSFORM,
1655 item_class->flip_desc);
1656
1657 gimp_item_start_transform (item, push_undo);
1658
1659 g_object_freeze_notify (G_OBJECT (item));
1660
1661 item_class->flip (item, context, flip_type, axis, clip_result);
1662
1663 g_object_thaw_notify (G_OBJECT (item));
1664
1665 gimp_item_end_transform (item, push_undo);
1666
1667 if (push_undo)
1668 gimp_image_undo_group_end (image);
1669 }
1670
1671 void
gimp_item_rotate(GimpItem * item,GimpContext * context,GimpRotationType rotate_type,gdouble center_x,gdouble center_y,gboolean clip_result)1672 gimp_item_rotate (GimpItem *item,
1673 GimpContext *context,
1674 GimpRotationType rotate_type,
1675 gdouble center_x,
1676 gdouble center_y,
1677 gboolean clip_result)
1678 {
1679 GimpItemClass *item_class;
1680 GimpImage *image;
1681 gboolean push_undo;
1682
1683 g_return_if_fail (GIMP_IS_ITEM (item));
1684 g_return_if_fail (gimp_item_is_attached (item));
1685 g_return_if_fail (GIMP_IS_CONTEXT (context));
1686
1687 item_class = GIMP_ITEM_GET_CLASS (item);
1688 image = gimp_item_get_image (item);
1689
1690 push_undo = gimp_item_is_attached (item);
1691
1692 if (push_undo)
1693 gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_TRANSFORM,
1694 item_class->rotate_desc);
1695
1696 gimp_item_start_transform (item, push_undo);
1697
1698 g_object_freeze_notify (G_OBJECT (item));
1699
1700 item_class->rotate (item, context, rotate_type, center_x, center_y,
1701 clip_result);
1702
1703 g_object_thaw_notify (G_OBJECT (item));
1704
1705 gimp_item_end_transform (item, push_undo);
1706
1707 if (push_undo)
1708 gimp_image_undo_group_end (image);
1709 }
1710
1711 void
gimp_item_transform(GimpItem * item,GimpContext * context,const GimpMatrix3 * matrix,GimpTransformDirection direction,GimpInterpolationType interpolation,GimpTransformResize clip_result,GimpProgress * progress)1712 gimp_item_transform (GimpItem *item,
1713 GimpContext *context,
1714 const GimpMatrix3 *matrix,
1715 GimpTransformDirection direction,
1716 GimpInterpolationType interpolation,
1717 GimpTransformResize clip_result,
1718 GimpProgress *progress)
1719 {
1720 GimpItemClass *item_class;
1721 GimpImage *image;
1722 gboolean push_undo;
1723
1724 g_return_if_fail (GIMP_IS_ITEM (item));
1725 g_return_if_fail (gimp_item_is_attached (item));
1726 g_return_if_fail (GIMP_IS_CONTEXT (context));
1727 g_return_if_fail (matrix != NULL);
1728 g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));
1729
1730 item_class = GIMP_ITEM_GET_CLASS (item);
1731 image = gimp_item_get_image (item);
1732
1733 push_undo = gimp_item_is_attached (item);
1734
1735 if (push_undo)
1736 gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_TRANSFORM,
1737 item_class->transform_desc);
1738
1739 gimp_item_start_transform (item, push_undo);
1740
1741 g_object_freeze_notify (G_OBJECT (item));
1742
1743 item_class->transform (item, context, matrix, direction, interpolation,
1744 clip_result, progress);
1745
1746 g_object_thaw_notify (G_OBJECT (item));
1747
1748 gimp_item_end_transform (item, push_undo);
1749
1750 if (push_undo)
1751 gimp_image_undo_group_end (image);
1752 }
1753
1754 GimpTransformResize
gimp_item_get_clip(GimpItem * item,GimpTransformResize clip_result)1755 gimp_item_get_clip (GimpItem *item,
1756 GimpTransformResize clip_result)
1757 {
1758 g_return_val_if_fail (GIMP_IS_ITEM (item), GIMP_TRANSFORM_RESIZE_ADJUST);
1759
1760 return GIMP_ITEM_GET_CLASS (item)->get_clip (item, clip_result);
1761 }
1762
1763 gboolean
gimp_item_fill(GimpItem * item,GimpDrawable * drawable,GimpFillOptions * fill_options,gboolean push_undo,GimpProgress * progress,GError ** error)1764 gimp_item_fill (GimpItem *item,
1765 GimpDrawable *drawable,
1766 GimpFillOptions *fill_options,
1767 gboolean push_undo,
1768 GimpProgress *progress,
1769 GError **error)
1770 {
1771 GimpItemClass *item_class;
1772 gboolean retval = FALSE;
1773
1774 g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
1775 g_return_val_if_fail (gimp_item_is_attached (item), FALSE);
1776 g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
1777 g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), FALSE);
1778 g_return_val_if_fail (GIMP_IS_FILL_OPTIONS (fill_options), FALSE);
1779 g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), FALSE);
1780 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1781
1782 item_class = GIMP_ITEM_GET_CLASS (item);
1783
1784 if (item_class->fill)
1785 {
1786 GimpImage *image = gimp_item_get_image (item);
1787
1788 if (push_undo)
1789 gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_PAINT,
1790 item_class->fill_desc);
1791
1792 retval = item_class->fill (item, drawable, fill_options, push_undo,
1793 progress, error);
1794
1795 if (push_undo)
1796 gimp_image_undo_group_end (image);
1797 }
1798
1799 return retval;
1800 }
1801
1802 gboolean
gimp_item_stroke(GimpItem * item,GimpDrawable * drawable,GimpContext * context,GimpStrokeOptions * stroke_options,GimpPaintOptions * paint_options,gboolean push_undo,GimpProgress * progress,GError ** error)1803 gimp_item_stroke (GimpItem *item,
1804 GimpDrawable *drawable,
1805 GimpContext *context,
1806 GimpStrokeOptions *stroke_options,
1807 GimpPaintOptions *paint_options,
1808 gboolean push_undo,
1809 GimpProgress *progress,
1810 GError **error)
1811 {
1812 GimpItemClass *item_class;
1813 gboolean retval = FALSE;
1814
1815 g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
1816 g_return_val_if_fail (gimp_item_is_attached (item), FALSE);
1817 g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
1818 g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), FALSE);
1819 g_return_val_if_fail (GIMP_IS_CONTEXT (context), FALSE);
1820 g_return_val_if_fail (GIMP_IS_STROKE_OPTIONS (stroke_options), FALSE);
1821 g_return_val_if_fail (paint_options == NULL ||
1822 GIMP_IS_PAINT_OPTIONS (paint_options), FALSE);
1823 g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), FALSE);
1824 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1825
1826 item_class = GIMP_ITEM_GET_CLASS (item);
1827
1828 if (item_class->stroke)
1829 {
1830 GimpImage *image = gimp_item_get_image (item);
1831
1832 gimp_stroke_options_prepare (stroke_options, context, paint_options);
1833
1834 if (push_undo)
1835 gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_PAINT,
1836 item_class->stroke_desc);
1837
1838 retval = item_class->stroke (item, drawable, stroke_options, push_undo,
1839 progress, error);
1840
1841 if (push_undo)
1842 gimp_image_undo_group_end (image);
1843
1844 gimp_stroke_options_finish (stroke_options);
1845 }
1846
1847 return retval;
1848 }
1849
1850 void
gimp_item_to_selection(GimpItem * item,GimpChannelOps op,gboolean antialias,gboolean feather,gdouble feather_radius_x,gdouble feather_radius_y)1851 gimp_item_to_selection (GimpItem *item,
1852 GimpChannelOps op,
1853 gboolean antialias,
1854 gboolean feather,
1855 gdouble feather_radius_x,
1856 gdouble feather_radius_y)
1857 {
1858 GimpItemClass *item_class;
1859
1860 g_return_if_fail (GIMP_IS_ITEM (item));
1861 g_return_if_fail (gimp_item_is_attached (item));
1862
1863 item_class = GIMP_ITEM_GET_CLASS (item);
1864
1865 if (item_class->to_selection)
1866 item_class->to_selection (item, op, antialias,
1867 feather, feather_radius_x, feather_radius_y);
1868 }
1869
1870 void
gimp_item_add_offset_node(GimpItem * item,GeglNode * node)1871 gimp_item_add_offset_node (GimpItem *item,
1872 GeglNode *node)
1873 {
1874 GimpItemPrivate *private;
1875
1876 g_return_if_fail (GIMP_IS_ITEM (item));
1877 g_return_if_fail (GEGL_IS_NODE (node));
1878
1879 private = GET_PRIVATE (item);
1880
1881 g_return_if_fail (g_list_find (private->offset_nodes, node) == NULL);
1882
1883 gegl_node_set (node,
1884 "x", (gdouble) private->offset_x,
1885 "y", (gdouble) private->offset_y,
1886 NULL);
1887
1888 private->offset_nodes = g_list_append (private->offset_nodes,
1889 g_object_ref (node));
1890 }
1891
1892 void
gimp_item_remove_offset_node(GimpItem * item,GeglNode * node)1893 gimp_item_remove_offset_node (GimpItem *item,
1894 GeglNode *node)
1895 {
1896 GimpItemPrivate *private;
1897
1898 g_return_if_fail (GIMP_IS_ITEM (item));
1899 g_return_if_fail (GEGL_IS_NODE (node));
1900
1901 private = GET_PRIVATE (item);
1902
1903 g_return_if_fail (g_list_find (private->offset_nodes, node) != NULL);
1904
1905 private->offset_nodes = g_list_remove (private->offset_nodes, node);
1906 g_object_unref (node);
1907 }
1908
1909 gint
gimp_item_get_ID(GimpItem * item)1910 gimp_item_get_ID (GimpItem *item)
1911 {
1912 g_return_val_if_fail (GIMP_IS_ITEM (item), -1);
1913
1914 return GET_PRIVATE (item)->ID;
1915 }
1916
1917 GimpItem *
gimp_item_get_by_ID(Gimp * gimp,gint item_id)1918 gimp_item_get_by_ID (Gimp *gimp,
1919 gint item_id)
1920 {
1921 g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
1922
1923 if (gimp->item_table == NULL)
1924 return NULL;
1925
1926 return (GimpItem *) gimp_id_table_lookup (gimp->item_table, item_id);
1927 }
1928
1929 GimpTattoo
gimp_item_get_tattoo(GimpItem * item)1930 gimp_item_get_tattoo (GimpItem *item)
1931 {
1932 g_return_val_if_fail (GIMP_IS_ITEM (item), 0);
1933
1934 return GET_PRIVATE (item)->tattoo;
1935 }
1936
1937 void
gimp_item_set_tattoo(GimpItem * item,GimpTattoo tattoo)1938 gimp_item_set_tattoo (GimpItem *item,
1939 GimpTattoo tattoo)
1940 {
1941 g_return_if_fail (GIMP_IS_ITEM (item));
1942
1943 GET_PRIVATE (item)->tattoo = tattoo;
1944 }
1945
1946 GimpImage *
gimp_item_get_image(GimpItem * item)1947 gimp_item_get_image (GimpItem *item)
1948 {
1949 g_return_val_if_fail (GIMP_IS_ITEM (item), NULL);
1950
1951 return GET_PRIVATE (item)->image;
1952 }
1953
1954 void
gimp_item_set_image(GimpItem * item,GimpImage * image)1955 gimp_item_set_image (GimpItem *item,
1956 GimpImage *image)
1957 {
1958 GimpItemPrivate *private;
1959
1960 g_return_if_fail (GIMP_IS_ITEM (item));
1961 g_return_if_fail (! gimp_item_is_attached (item));
1962 g_return_if_fail (! gimp_item_is_removed (item));
1963 g_return_if_fail (GIMP_IS_IMAGE (image));
1964
1965 private = GET_PRIVATE (item);
1966
1967 if (image == private->image)
1968 return;
1969
1970 g_object_freeze_notify (G_OBJECT (item));
1971
1972 if (private->ID == 0)
1973 {
1974 private->ID = gimp_id_table_insert (image->gimp->item_table, item);
1975
1976 g_object_notify (G_OBJECT (item), "id");
1977 }
1978
1979 if (private->tattoo == 0 || private->image != image)
1980 {
1981 private->tattoo = gimp_image_get_new_tattoo (image);
1982 }
1983
1984 private->image = image;
1985 g_object_notify (G_OBJECT (item), "image");
1986
1987 g_object_thaw_notify (G_OBJECT (item));
1988 }
1989
1990 /**
1991 * gimp_item_replace_item:
1992 * @item: a newly allocated #GimpItem
1993 * @replace: the #GimpItem to be replaced by @item
1994 *
1995 * This function shouly only be called right after @item has been
1996 * newly allocated.
1997 *
1998 * Replaces @replace by @item, as far as possible within the #GimpItem
1999 * class. The new @item takes over @replace's ID, tattoo, offset, size
2000 * etc. and all these properties are set to %NULL on @replace.
2001 *
2002 * This function *only* exists to allow subclasses to do evil hacks
2003 * like in XCF text layer loading. Don't ever use this function if you
2004 * are not sure.
2005 *
2006 * After this function returns, @replace has become completely
2007 * unusable, should only be used to steal everything it has (like its
2008 * drawable properties if it's a drawable), and then be destroyed.
2009 **/
2010 void
gimp_item_replace_item(GimpItem * item,GimpItem * replace)2011 gimp_item_replace_item (GimpItem *item,
2012 GimpItem *replace)
2013 {
2014 GimpItemPrivate *private;
2015 gint offset_x;
2016 gint offset_y;
2017
2018 g_return_if_fail (GIMP_IS_ITEM (item));
2019 g_return_if_fail (! gimp_item_is_attached (item));
2020 g_return_if_fail (! gimp_item_is_removed (item));
2021 g_return_if_fail (GIMP_IS_ITEM (replace));
2022
2023 private = GET_PRIVATE (item);
2024
2025 gimp_object_set_name (GIMP_OBJECT (item), gimp_object_get_name (replace));
2026
2027 if (private->ID)
2028 gimp_id_table_remove (gimp_item_get_image (item)->gimp->item_table,
2029 gimp_item_get_ID (item));
2030
2031 private->ID = gimp_item_get_ID (replace);
2032 gimp_id_table_replace (gimp_item_get_image (item)->gimp->item_table,
2033 gimp_item_get_ID (item),
2034 item);
2035
2036 /* Set image before tattoo so that the explicitly set tattoo overrides
2037 * the one implicitly set when setting the image
2038 */
2039 gimp_item_set_image (item, gimp_item_get_image (replace));
2040 GET_PRIVATE (replace)->image = NULL;
2041
2042 gimp_item_set_tattoo (item, gimp_item_get_tattoo (replace));
2043 gimp_item_set_tattoo (replace, 0);
2044
2045 g_object_unref (private->parasites);
2046 private->parasites = GET_PRIVATE (replace)->parasites;
2047 GET_PRIVATE (replace)->parasites = NULL;
2048
2049 gimp_item_get_offset (replace, &offset_x, &offset_y);
2050 gimp_item_set_offset (item, offset_x, offset_y);
2051
2052 gimp_item_set_size (item,
2053 gimp_item_get_width (replace),
2054 gimp_item_get_height (replace));
2055
2056 gimp_item_set_visible (item, gimp_item_get_visible (replace), FALSE);
2057 gimp_item_set_linked (item, gimp_item_get_linked (replace), FALSE);
2058 gimp_item_set_color_tag (item, gimp_item_get_color_tag (replace), FALSE);
2059 gimp_item_set_lock_content (item, gimp_item_get_lock_content (replace), FALSE);
2060 gimp_item_set_lock_position (item, gimp_item_get_lock_position (replace), FALSE);
2061 }
2062
2063 /**
2064 * gimp_item_set_parasites:
2065 * @item: a #GimpItem
2066 * @parasites: a #GimpParasiteList
2067 *
2068 * Set an @item's #GimpParasiteList. It's usually never needed to
2069 * fiddle with an item's parasite list directly. This function exists
2070 * for special purposes only, like when creating items from unusual
2071 * sources.
2072 **/
2073 void
gimp_item_set_parasites(GimpItem * item,GimpParasiteList * parasites)2074 gimp_item_set_parasites (GimpItem *item,
2075 GimpParasiteList *parasites)
2076 {
2077 GimpItemPrivate *private;
2078
2079 g_return_if_fail (GIMP_IS_ITEM (item));
2080 g_return_if_fail (GIMP_IS_PARASITE_LIST (parasites));
2081
2082 private = GET_PRIVATE (item);
2083
2084 g_set_object (&private->parasites, parasites);
2085 }
2086
2087 /**
2088 * gimp_item_get_parasites:
2089 * @item: a #GimpItem
2090 *
2091 * Get an @item's #GimpParasiteList. It's usually never needed to
2092 * fiddle with an item's parasite list directly. This function exists
2093 * for special purposes only, like when saving an item to XCF.
2094 *
2095 * Return value: The @item's #GimpParasiteList.
2096 **/
2097 GimpParasiteList *
gimp_item_get_parasites(GimpItem * item)2098 gimp_item_get_parasites (GimpItem *item)
2099 {
2100 g_return_val_if_fail (GIMP_IS_ITEM (item), NULL);
2101
2102 return GET_PRIVATE (item)->parasites;
2103 }
2104
2105 gboolean
gimp_item_parasite_validate(GimpItem * item,const GimpParasite * parasite,GError ** error)2106 gimp_item_parasite_validate (GimpItem *item,
2107 const GimpParasite *parasite,
2108 GError **error)
2109 {
2110 g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
2111 g_return_val_if_fail (parasite != NULL, FALSE);
2112 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2113
2114 return TRUE;
2115 }
2116
2117 void
gimp_item_parasite_attach(GimpItem * item,const GimpParasite * parasite,gboolean push_undo)2118 gimp_item_parasite_attach (GimpItem *item,
2119 const GimpParasite *parasite,
2120 gboolean push_undo)
2121 {
2122 GimpItemPrivate *private;
2123 GimpParasite copy;
2124
2125 g_return_if_fail (GIMP_IS_ITEM (item));
2126 g_return_if_fail (parasite != NULL);
2127
2128 private = GET_PRIVATE (item);
2129
2130 /* make a temporary copy of the GimpParasite struct because
2131 * gimp_parasite_shift_parent() changes it
2132 */
2133 copy = *parasite;
2134
2135 if (! gimp_item_is_attached (item))
2136 push_undo = FALSE;
2137
2138 if (push_undo)
2139 {
2140 /* only set the dirty bit manually if we can be saved and the new
2141 * parasite differs from the current one and we aren't undoable
2142 */
2143 if (gimp_parasite_is_undoable (©))
2144 {
2145 /* do a group in case we have attach_parent set */
2146 gimp_image_undo_group_start (private->image,
2147 GIMP_UNDO_GROUP_PARASITE_ATTACH,
2148 C_("undo-type", "Attach Parasite"));
2149
2150 gimp_image_undo_push_item_parasite (private->image, NULL, item, ©);
2151 }
2152 else if (gimp_parasite_is_persistent (©) &&
2153 ! gimp_parasite_compare (©,
2154 gimp_item_parasite_find
2155 (item, gimp_parasite_name (©))))
2156 {
2157 gimp_image_undo_push_cantundo (private->image,
2158 C_("undo-type", "Attach Parasite to Item"));
2159 }
2160 }
2161
2162 gimp_parasite_list_add (private->parasites, ©);
2163
2164 if (gimp_parasite_has_flag (©, GIMP_PARASITE_ATTACH_PARENT))
2165 {
2166 gimp_parasite_shift_parent (©);
2167 gimp_image_parasite_attach (private->image, ©, TRUE);
2168 }
2169 else if (gimp_parasite_has_flag (©, GIMP_PARASITE_ATTACH_GRANDPARENT))
2170 {
2171 gimp_parasite_shift_parent (©);
2172 gimp_parasite_shift_parent (©);
2173 gimp_parasite_attach (private->image->gimp, ©);
2174 }
2175
2176 if (gimp_item_is_attached (item) &&
2177 gimp_parasite_is_undoable (©))
2178 {
2179 gimp_image_undo_group_end (private->image);
2180 }
2181 }
2182
2183 void
gimp_item_parasite_detach(GimpItem * item,const gchar * name,gboolean push_undo)2184 gimp_item_parasite_detach (GimpItem *item,
2185 const gchar *name,
2186 gboolean push_undo)
2187 {
2188 GimpItemPrivate *private;
2189 const GimpParasite *parasite;
2190
2191 g_return_if_fail (GIMP_IS_ITEM (item));
2192 g_return_if_fail (name != NULL);
2193
2194 private = GET_PRIVATE (item);
2195
2196 parasite = gimp_parasite_list_find (private->parasites, name);
2197
2198 if (! parasite)
2199 return;
2200
2201 if (! gimp_item_is_attached (item))
2202 push_undo = FALSE;
2203
2204 if (push_undo)
2205 {
2206 if (gimp_parasite_is_undoable (parasite))
2207 {
2208 gimp_image_undo_push_item_parasite_remove (private->image,
2209 C_("undo-type", "Remove Parasite from Item"),
2210 item,
2211 gimp_parasite_name (parasite));
2212 }
2213 else if (gimp_parasite_is_persistent (parasite))
2214 {
2215 gimp_image_undo_push_cantundo (private->image,
2216 C_("undo-type", "Remove Parasite from Item"));
2217 }
2218 }
2219
2220 gimp_parasite_list_remove (private->parasites, name);
2221 }
2222
2223 const GimpParasite *
gimp_item_parasite_find(GimpItem * item,const gchar * name)2224 gimp_item_parasite_find (GimpItem *item,
2225 const gchar *name)
2226 {
2227 g_return_val_if_fail (GIMP_IS_ITEM (item), NULL);
2228
2229 return gimp_parasite_list_find (GET_PRIVATE (item)->parasites, name);
2230 }
2231
2232 static void
gimp_item_parasite_list_foreach_func(gchar * name,GimpParasite * parasite,gchar *** cur)2233 gimp_item_parasite_list_foreach_func (gchar *name,
2234 GimpParasite *parasite,
2235 gchar ***cur)
2236 {
2237 *(*cur)++ = (gchar *) g_strdup (name);
2238 }
2239
2240 gchar **
gimp_item_parasite_list(GimpItem * item,gint * count)2241 gimp_item_parasite_list (GimpItem *item,
2242 gint *count)
2243 {
2244 GimpItemPrivate *private;
2245 gchar **list;
2246 gchar **cur;
2247
2248 g_return_val_if_fail (GIMP_IS_ITEM (item), NULL);
2249 g_return_val_if_fail (count != NULL, NULL);
2250
2251 private = GET_PRIVATE (item);
2252
2253 *count = gimp_parasite_list_length (private->parasites);
2254
2255 cur = list = g_new (gchar *, *count);
2256
2257 gimp_parasite_list_foreach (private->parasites,
2258 (GHFunc) gimp_item_parasite_list_foreach_func,
2259 &cur);
2260
2261 return list;
2262 }
2263
2264 void
gimp_item_set_visible(GimpItem * item,gboolean visible,gboolean push_undo)2265 gimp_item_set_visible (GimpItem *item,
2266 gboolean visible,
2267 gboolean push_undo)
2268 {
2269 g_return_if_fail (GIMP_IS_ITEM (item));
2270
2271 visible = visible ? TRUE : FALSE;
2272
2273 if (gimp_item_get_visible (item) != visible)
2274 {
2275 if (push_undo && gimp_item_is_attached (item))
2276 {
2277 GimpImage *image = gimp_item_get_image (item);
2278
2279 if (image)
2280 gimp_image_undo_push_item_visibility (image, NULL, item);
2281 }
2282
2283 GET_PRIVATE (item)->visible = visible;
2284
2285 if (GET_PRIVATE (item)->bind_visible_to_active)
2286 gimp_filter_set_active (GIMP_FILTER (item), visible);
2287
2288 g_signal_emit (item, gimp_item_signals[VISIBILITY_CHANGED], 0);
2289
2290 g_object_notify (G_OBJECT (item), "visible");
2291 }
2292 }
2293
2294 gboolean
gimp_item_get_visible(GimpItem * item)2295 gimp_item_get_visible (GimpItem *item)
2296 {
2297 g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
2298
2299 return GET_PRIVATE (item)->visible;
2300 }
2301
2302 gboolean
gimp_item_is_visible(GimpItem * item)2303 gimp_item_is_visible (GimpItem *item)
2304 {
2305 g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
2306
2307 if (gimp_item_get_visible (item))
2308 {
2309 GimpItem *parent;
2310
2311 parent = GIMP_ITEM (gimp_viewable_get_parent (GIMP_VIEWABLE (item)));
2312
2313 if (parent)
2314 return gimp_item_is_visible (parent);
2315
2316 return TRUE;
2317 }
2318
2319 return FALSE;
2320 }
2321
2322 void
gimp_item_bind_visible_to_active(GimpItem * item,gboolean bind)2323 gimp_item_bind_visible_to_active (GimpItem *item,
2324 gboolean bind)
2325 {
2326 g_return_if_fail (GIMP_IS_ITEM (item));
2327
2328 GET_PRIVATE (item)->bind_visible_to_active = bind;
2329
2330 if (bind)
2331 gimp_filter_set_active (GIMP_FILTER (item), gimp_item_get_visible (item));
2332 }
2333
2334 void
gimp_item_set_linked(GimpItem * item,gboolean linked,gboolean push_undo)2335 gimp_item_set_linked (GimpItem *item,
2336 gboolean linked,
2337 gboolean push_undo)
2338 {
2339 g_return_if_fail (GIMP_IS_ITEM (item));
2340
2341 linked = linked ? TRUE : FALSE;
2342
2343 if (gimp_item_get_linked (item) != linked)
2344 {
2345 GimpImage *image = gimp_item_get_image (item);
2346 gboolean is_attached = gimp_item_is_attached (item);
2347
2348 if (push_undo && is_attached && image)
2349 gimp_image_undo_push_item_linked (image, NULL, item);
2350
2351 GET_PRIVATE (item)->linked = linked;
2352
2353 g_signal_emit (item, gimp_item_signals[LINKED_CHANGED], 0);
2354
2355 if (is_attached && image)
2356 gimp_image_linked_items_changed (image);
2357
2358 g_object_notify (G_OBJECT (item), "linked");
2359 }
2360 }
2361
2362 gboolean
gimp_item_get_linked(GimpItem * item)2363 gimp_item_get_linked (GimpItem *item)
2364 {
2365 g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
2366
2367 return GET_PRIVATE (item)->linked;
2368 }
2369
2370 void
gimp_item_set_color_tag(GimpItem * item,GimpColorTag color_tag,gboolean push_undo)2371 gimp_item_set_color_tag (GimpItem *item,
2372 GimpColorTag color_tag,
2373 gboolean push_undo)
2374 {
2375 g_return_if_fail (GIMP_IS_ITEM (item));
2376
2377 if (gimp_item_get_color_tag (item) != color_tag)
2378 {
2379 if (push_undo && gimp_item_is_attached (item))
2380 {
2381 GimpImage *image = gimp_item_get_image (item);
2382
2383 if (image)
2384 gimp_image_undo_push_item_color_tag (image, NULL, item);
2385 }
2386
2387 GET_PRIVATE (item)->color_tag = color_tag;
2388
2389 g_signal_emit (item, gimp_item_signals[COLOR_TAG_CHANGED], 0);
2390
2391 g_object_notify (G_OBJECT (item), "color-tag");
2392 }
2393 }
2394
2395 GimpColorTag
gimp_item_get_color_tag(GimpItem * item)2396 gimp_item_get_color_tag (GimpItem *item)
2397 {
2398 g_return_val_if_fail (GIMP_IS_ITEM (item), GIMP_COLOR_TAG_NONE);
2399
2400 return GET_PRIVATE (item)->color_tag;
2401 }
2402
2403 GimpColorTag
gimp_item_get_merged_color_tag(GimpItem * item)2404 gimp_item_get_merged_color_tag (GimpItem *item)
2405 {
2406 g_return_val_if_fail (GIMP_IS_ITEM (item), GIMP_COLOR_TAG_NONE);
2407
2408 if (gimp_item_get_color_tag (item) == GIMP_COLOR_TAG_NONE)
2409 {
2410 GimpItem *parent;
2411
2412 parent = GIMP_ITEM (gimp_viewable_get_parent (GIMP_VIEWABLE (item)));
2413
2414 if (parent)
2415 return gimp_item_get_merged_color_tag (parent);
2416 }
2417
2418 return gimp_item_get_color_tag (item);
2419 }
2420
2421 void
gimp_item_set_lock_content(GimpItem * item,gboolean lock_content,gboolean push_undo)2422 gimp_item_set_lock_content (GimpItem *item,
2423 gboolean lock_content,
2424 gboolean push_undo)
2425 {
2426 g_return_if_fail (GIMP_IS_ITEM (item));
2427 g_return_if_fail (gimp_item_can_lock_content (item));
2428
2429 lock_content = lock_content ? TRUE : FALSE;
2430
2431 if (gimp_item_get_lock_content (item) != lock_content)
2432 {
2433 if (push_undo && gimp_item_is_attached (item))
2434 {
2435 /* Right now I don't think this should be pushed. */
2436 #if 0
2437 GimpImage *image = gimp_item_get_image (item);
2438
2439 gimp_image_undo_push_item_lock_content (image, NULL, item);
2440 #endif
2441 }
2442
2443 GET_PRIVATE (item)->lock_content = lock_content;
2444
2445 g_signal_emit (item, gimp_item_signals[LOCK_CONTENT_CHANGED], 0);
2446
2447 g_object_notify (G_OBJECT (item), "lock-content");
2448 }
2449 }
2450
2451 gboolean
gimp_item_get_lock_content(GimpItem * item)2452 gimp_item_get_lock_content (GimpItem *item)
2453 {
2454 g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
2455
2456 return GET_PRIVATE (item)->lock_content;
2457 }
2458
2459 gboolean
gimp_item_can_lock_content(GimpItem * item)2460 gimp_item_can_lock_content (GimpItem *item)
2461 {
2462 g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
2463
2464 return TRUE;
2465 }
2466
2467 gboolean
gimp_item_is_content_locked(GimpItem * item)2468 gimp_item_is_content_locked (GimpItem *item)
2469 {
2470 g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
2471
2472 return GIMP_ITEM_GET_CLASS (item)->is_content_locked (item);
2473 }
2474
2475 void
gimp_item_set_lock_position(GimpItem * item,gboolean lock_position,gboolean push_undo)2476 gimp_item_set_lock_position (GimpItem *item,
2477 gboolean lock_position,
2478 gboolean push_undo)
2479 {
2480 g_return_if_fail (GIMP_IS_ITEM (item));
2481 g_return_if_fail (gimp_item_can_lock_position (item));
2482
2483 lock_position = lock_position ? TRUE : FALSE;
2484
2485 if (gimp_item_get_lock_position (item) != lock_position)
2486 {
2487 if (push_undo && gimp_item_is_attached (item))
2488 {
2489 GimpImage *image = gimp_item_get_image (item);
2490
2491 gimp_image_undo_push_item_lock_position (image, NULL, item);
2492 }
2493
2494 GET_PRIVATE (item)->lock_position = lock_position;
2495
2496 g_signal_emit (item, gimp_item_signals[LOCK_POSITION_CHANGED], 0);
2497
2498 g_object_notify (G_OBJECT (item), "lock-position");
2499 }
2500 }
2501
2502 gboolean
gimp_item_get_lock_position(GimpItem * item)2503 gimp_item_get_lock_position (GimpItem *item)
2504 {
2505 g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
2506
2507 return GET_PRIVATE (item)->lock_position;
2508 }
2509
2510 gboolean
gimp_item_can_lock_position(GimpItem * item)2511 gimp_item_can_lock_position (GimpItem *item)
2512 {
2513 g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
2514
2515 if (gimp_viewable_get_children (GIMP_VIEWABLE (item)))
2516 return FALSE;
2517
2518 return TRUE;
2519 }
2520
2521 gboolean
gimp_item_is_position_locked(GimpItem * item)2522 gimp_item_is_position_locked (GimpItem *item)
2523 {
2524 g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
2525
2526 return GIMP_ITEM_GET_CLASS (item)->is_position_locked (item);
2527 }
2528
2529 gboolean
gimp_item_mask_bounds(GimpItem * item,gint * x1,gint * y1,gint * x2,gint * y2)2530 gimp_item_mask_bounds (GimpItem *item,
2531 gint *x1,
2532 gint *y1,
2533 gint *x2,
2534 gint *y2)
2535 {
2536 GimpImage *image;
2537 GimpChannel *selection;
2538 gint x, y, width, height;
2539 gboolean retval;
2540
2541 g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
2542 g_return_val_if_fail (gimp_item_is_attached (item), FALSE);
2543
2544 image = gimp_item_get_image (item);
2545 selection = gimp_image_get_mask (image);
2546
2547 /* check for is_empty() before intersecting so we ignore the
2548 * selection if it is suspended (like when stroking)
2549 */
2550 if (GIMP_ITEM (selection) != item &&
2551 ! gimp_channel_is_empty (selection) &&
2552 gimp_item_bounds (GIMP_ITEM (selection), &x, &y, &width, &height))
2553 {
2554 gint off_x, off_y;
2555 gint x2, y2;
2556
2557 gimp_item_get_offset (item, &off_x, &off_y);
2558
2559 x2 = x + width;
2560 y2 = y + height;
2561
2562 x = CLAMP (x - off_x, 0, gimp_item_get_width (item));
2563 y = CLAMP (y - off_y, 0, gimp_item_get_height (item));
2564 x2 = CLAMP (x2 - off_x, 0, gimp_item_get_width (item));
2565 y2 = CLAMP (y2 - off_y, 0, gimp_item_get_height (item));
2566
2567 width = x2 - x;
2568 height = y2 - y;
2569
2570 retval = TRUE;
2571 }
2572 else
2573 {
2574 x = 0;
2575 y = 0;
2576 width = gimp_item_get_width (item);
2577 height = gimp_item_get_height (item);
2578
2579 retval = FALSE;
2580 }
2581
2582 if (x1) *x1 = x;
2583 if (y1) *y1 = y;
2584 if (x2) *x2 = x + width;
2585 if (y2) *y2 = y + height;
2586
2587 return retval;
2588 }
2589
2590 /**
2591 * gimp_item_mask_intersect:
2592 * @item: a #GimpItem
2593 * @x: return location for x
2594 * @y: return location for y
2595 * @width: return location for the width
2596 * @height: return location for the height
2597 *
2598 * Intersect the area of the @item and its image's selection mask.
2599 * The computed area is the bounding box of he selection within the
2600 * item.
2601 **/
2602 gboolean
gimp_item_mask_intersect(GimpItem * item,gint * x,gint * y,gint * width,gint * height)2603 gimp_item_mask_intersect (GimpItem *item,
2604 gint *x,
2605 gint *y,
2606 gint *width,
2607 gint *height)
2608 {
2609 GimpImage *image;
2610 GimpChannel *selection;
2611 gint tmp_x, tmp_y;
2612 gint tmp_width, tmp_height;
2613 gboolean retval;
2614
2615 g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
2616 g_return_val_if_fail (gimp_item_is_attached (item), FALSE);
2617
2618 image = gimp_item_get_image (item);
2619 selection = gimp_image_get_mask (image);
2620
2621 /* check for is_empty() before intersecting so we ignore the
2622 * selection if it is suspended (like when stroking)
2623 */
2624 if (GIMP_ITEM (selection) != item &&
2625 ! gimp_channel_is_empty (selection) &&
2626 gimp_item_bounds (GIMP_ITEM (selection),
2627 &tmp_x, &tmp_y, &tmp_width, &tmp_height))
2628 {
2629 gint off_x, off_y;
2630
2631 gimp_item_get_offset (item, &off_x, &off_y);
2632
2633 retval = gimp_rectangle_intersect (tmp_x - off_x, tmp_y - off_y,
2634 tmp_width, tmp_height,
2635 0, 0,
2636 gimp_item_get_width (item),
2637 gimp_item_get_height (item),
2638 &tmp_x, &tmp_y,
2639 &tmp_width, &tmp_height);
2640 }
2641 else
2642 {
2643 tmp_x = 0;
2644 tmp_y = 0;
2645 tmp_width = gimp_item_get_width (item);
2646 tmp_height = gimp_item_get_height (item);
2647
2648 retval = TRUE;
2649 }
2650
2651 if (x) *x = tmp_x;
2652 if (y) *y = tmp_y;
2653 if (width) *width = tmp_width;
2654 if (height) *height = tmp_height;
2655
2656 return retval;
2657 }
2658
2659 gboolean
gimp_item_is_in_set(GimpItem * item,GimpItemSet set)2660 gimp_item_is_in_set (GimpItem *item,
2661 GimpItemSet set)
2662 {
2663 GimpItemPrivate *private;
2664
2665 g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
2666
2667 private = GET_PRIVATE (item);
2668
2669 switch (set)
2670 {
2671 case GIMP_ITEM_SET_NONE:
2672 return FALSE;
2673
2674 case GIMP_ITEM_SET_ALL:
2675 return TRUE;
2676
2677 case GIMP_ITEM_SET_IMAGE_SIZED:
2678 return (gimp_item_get_width (item) == gimp_image_get_width (private->image) &&
2679 gimp_item_get_height (item) == gimp_image_get_height (private->image));
2680
2681 case GIMP_ITEM_SET_VISIBLE:
2682 return gimp_item_get_visible (item);
2683
2684 case GIMP_ITEM_SET_LINKED:
2685 return gimp_item_get_linked (item);
2686 }
2687
2688 return FALSE;
2689 }
2690