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 (&copy))
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, &copy);
2151         }
2152       else if (gimp_parasite_is_persistent (&copy) &&
2153                ! gimp_parasite_compare (&copy,
2154                                         gimp_item_parasite_find
2155                                         (item, gimp_parasite_name (&copy))))
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, &copy);
2163 
2164   if (gimp_parasite_has_flag (&copy, GIMP_PARASITE_ATTACH_PARENT))
2165     {
2166       gimp_parasite_shift_parent (&copy);
2167       gimp_image_parasite_attach (private->image, &copy, TRUE);
2168     }
2169   else if (gimp_parasite_has_flag (&copy, GIMP_PARASITE_ATTACH_GRANDPARENT))
2170     {
2171       gimp_parasite_shift_parent (&copy);
2172       gimp_parasite_shift_parent (&copy);
2173       gimp_parasite_attach (private->image->gimp, &copy);
2174     }
2175 
2176   if (gimp_item_is_attached (item) &&
2177       gimp_parasite_is_undoable (&copy))
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