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 <cairo.h>
21 #include <gdk-pixbuf/gdk-pixbuf.h>
22 #include <gegl.h>
23 
24 #include "libgimpcolor/gimpcolor.h"
25 
26 #include "core-types.h"
27 
28 #include "gegl/gimp-babl.h"
29 #include "gegl/gimp-gegl-apply-operation.h"
30 #include "gegl/gimp-gegl-loops.h"
31 
32 #include "gimp.h"
33 #include "gimpcontext.h"
34 #include "gimpdrawable-edit.h"
35 #include "gimpdrawable-private.h"
36 #include "gimperror.h"
37 #include "gimpimage.h"
38 #include "gimpimage-undo.h"
39 #include "gimpimage-undo-push.h"
40 #include "gimplayer.h"
41 #include "gimplayer-new.h"
42 #include "gimplayermask.h"
43 #include "gimplayer-floating-selection.h"
44 #include "gimppickable.h"
45 #include "gimpselection.h"
46 
47 #include "gimp-intl.h"
48 
49 
50 static gboolean   gimp_selection_is_attached   (GimpItem            *item);
51 static GimpItemTree * gimp_selection_get_tree  (GimpItem            *item);
52 static void       gimp_selection_translate     (GimpItem            *item,
53                                                 gdouble              offset_x,
54                                                 gdouble              offset_y,
55                                                 gboolean             push_undo);
56 static void       gimp_selection_scale         (GimpItem            *item,
57                                                 gint                 new_width,
58                                                 gint                 new_height,
59                                                 gint                 new_offset_x,
60                                                 gint                 new_offset_y,
61                                                 GimpInterpolationType interp_type,
62                                                 GimpProgress        *progress);
63 static void       gimp_selection_resize        (GimpItem            *item,
64                                                 GimpContext         *context,
65                                                 GimpFillType         fill_type,
66                                                 gint                 new_width,
67                                                 gint                 new_height,
68                                                 gint                 offset_x,
69                                                 gint                 offset_y);
70 static void       gimp_selection_flip          (GimpItem            *item,
71                                                 GimpContext         *context,
72                                                 GimpOrientationType  flip_type,
73                                                 gdouble              axis,
74                                                 gboolean             clip_result);
75 static void       gimp_selection_rotate        (GimpItem            *item,
76                                                 GimpContext         *context,
77                                                 GimpRotationType     rotation_type,
78                                                 gdouble              center_x,
79                                                 gdouble              center_y,
80                                                 gboolean             clip_result);
81 static gboolean   gimp_selection_fill          (GimpItem            *item,
82                                                 GimpDrawable        *drawable,
83                                                 GimpFillOptions     *fill_options,
84                                                 gboolean             push_undo,
85                                                 GimpProgress        *progress,
86                                                 GError             **error);
87 static gboolean   gimp_selection_stroke        (GimpItem            *item,
88                                                 GimpDrawable        *drawable,
89                                                 GimpStrokeOptions   *stroke_options,
90                                                 gboolean             push_undo,
91                                                 GimpProgress        *progress,
92                                                 GError             **error);
93 static void       gimp_selection_convert_type  (GimpDrawable        *drawable,
94                                                 GimpImage           *dest_image,
95                                                 const Babl          *new_format,
96                                                 GimpColorProfile    *dest_profile,
97                                                 GeglDitherMethod     layer_dither_type,
98                                                 GeglDitherMethod     mask_dither_type,
99                                                 gboolean             push_undo,
100                                                 GimpProgress        *progress);
101 static void gimp_selection_invalidate_boundary (GimpDrawable        *drawable);
102 
103 static gboolean   gimp_selection_boundary      (GimpChannel         *channel,
104                                                 const GimpBoundSeg **segs_in,
105                                                 const GimpBoundSeg **segs_out,
106                                                 gint                *num_segs_in,
107                                                 gint                *num_segs_out,
108                                                 gint                 x1,
109                                                 gint                 y1,
110                                                 gint                 x2,
111                                                 gint                 y2);
112 static gboolean   gimp_selection_is_empty      (GimpChannel         *channel);
113 static void       gimp_selection_feather       (GimpChannel         *channel,
114                                                 gdouble              radius_x,
115                                                 gdouble              radius_y,
116                                                 gboolean             edge_lock,
117                                                 gboolean             push_undo);
118 static void       gimp_selection_sharpen       (GimpChannel         *channel,
119                                                 gboolean             push_undo);
120 static void       gimp_selection_clear         (GimpChannel         *channel,
121                                                 const gchar         *undo_desc,
122                                                 gboolean             push_undo);
123 static void       gimp_selection_all           (GimpChannel         *channel,
124                                                 gboolean             push_undo);
125 static void       gimp_selection_invert        (GimpChannel         *channel,
126                                                 gboolean             push_undo);
127 static void       gimp_selection_border        (GimpChannel         *channel,
128                                                 gint                 radius_x,
129                                                 gint                 radius_y,
130                                                 GimpChannelBorderStyle style,
131                                                 gboolean             edge_lock,
132                                                 gboolean             push_undo);
133 static void       gimp_selection_grow          (GimpChannel         *channel,
134                                                 gint                 radius_x,
135                                                 gint                 radius_y,
136                                                 gboolean             push_undo);
137 static void       gimp_selection_shrink        (GimpChannel         *channel,
138                                                 gint                 radius_x,
139                                                 gint                 radius_y,
140                                                 gboolean             edge_lock,
141                                                 gboolean             push_undo);
142 static void       gimp_selection_flood         (GimpChannel         *channel,
143                                                 gboolean             push_undo);
144 
145 
G_DEFINE_TYPE(GimpSelection,gimp_selection,GIMP_TYPE_CHANNEL)146 G_DEFINE_TYPE (GimpSelection, gimp_selection, GIMP_TYPE_CHANNEL)
147 
148 #define parent_class gimp_selection_parent_class
149 
150 
151 static void
152 gimp_selection_class_init (GimpSelectionClass *klass)
153 {
154   GimpViewableClass *viewable_class = GIMP_VIEWABLE_CLASS (klass);
155   GimpItemClass     *item_class     = GIMP_ITEM_CLASS (klass);
156   GimpDrawableClass *drawable_class = GIMP_DRAWABLE_CLASS (klass);
157   GimpChannelClass  *channel_class  = GIMP_CHANNEL_CLASS (klass);
158 
159   viewable_class->default_icon_name   = "gimp-selection";
160 
161   item_class->is_attached             = gimp_selection_is_attached;
162   item_class->get_tree                = gimp_selection_get_tree;
163   item_class->translate               = gimp_selection_translate;
164   item_class->scale                   = gimp_selection_scale;
165   item_class->resize                  = gimp_selection_resize;
166   item_class->flip                    = gimp_selection_flip;
167   item_class->rotate                  = gimp_selection_rotate;
168   item_class->fill                    = gimp_selection_fill;
169   item_class->stroke                  = gimp_selection_stroke;
170   item_class->default_name            = _("Selection Mask");
171   item_class->translate_desc          = C_("undo-type", "Move Selection");
172   item_class->fill_desc               = C_("undo-type", "Fill Selection");
173   item_class->stroke_desc             = C_("undo-type", "Stroke Selection");
174 
175   drawable_class->convert_type        = gimp_selection_convert_type;
176   drawable_class->invalidate_boundary = gimp_selection_invalidate_boundary;
177 
178   channel_class->boundary             = gimp_selection_boundary;
179   channel_class->is_empty             = gimp_selection_is_empty;
180   channel_class->feather              = gimp_selection_feather;
181   channel_class->sharpen              = gimp_selection_sharpen;
182   channel_class->clear                = gimp_selection_clear;
183   channel_class->all                  = gimp_selection_all;
184   channel_class->invert               = gimp_selection_invert;
185   channel_class->border               = gimp_selection_border;
186   channel_class->grow                 = gimp_selection_grow;
187   channel_class->shrink               = gimp_selection_shrink;
188   channel_class->flood                = gimp_selection_flood;
189 
190   channel_class->feather_desc         = C_("undo-type", "Feather Selection");
191   channel_class->sharpen_desc         = C_("undo-type", "Sharpen Selection");
192   channel_class->clear_desc           = C_("undo-type", "Select None");
193   channel_class->all_desc             = C_("undo-type", "Select All");
194   channel_class->invert_desc          = C_("undo-type", "Invert Selection");
195   channel_class->border_desc          = C_("undo-type", "Border Selection");
196   channel_class->grow_desc            = C_("undo-type", "Grow Selection");
197   channel_class->shrink_desc          = C_("undo-type", "Shrink Selection");
198   channel_class->flood_desc           = C_("undo-type", "Remove Holes");
199 }
200 
201 static void
gimp_selection_init(GimpSelection * selection)202 gimp_selection_init (GimpSelection *selection)
203 {
204 }
205 
206 static gboolean
gimp_selection_is_attached(GimpItem * item)207 gimp_selection_is_attached (GimpItem *item)
208 {
209   return (GIMP_IS_IMAGE (gimp_item_get_image (item)) &&
210           gimp_image_get_mask (gimp_item_get_image (item)) ==
211           GIMP_CHANNEL (item));
212 }
213 
214 static GimpItemTree *
gimp_selection_get_tree(GimpItem * item)215 gimp_selection_get_tree (GimpItem *item)
216 {
217   return NULL;
218 }
219 
220 static void
gimp_selection_translate(GimpItem * item,gdouble offset_x,gdouble offset_y,gboolean push_undo)221 gimp_selection_translate (GimpItem *item,
222                           gdouble   offset_x,
223                           gdouble   offset_y,
224                           gboolean  push_undo)
225 {
226   GIMP_ITEM_CLASS (parent_class)->translate (item, offset_x, offset_y,
227                                              push_undo);
228 }
229 
230 static void
gimp_selection_scale(GimpItem * item,gint new_width,gint new_height,gint new_offset_x,gint new_offset_y,GimpInterpolationType interp_type,GimpProgress * progress)231 gimp_selection_scale (GimpItem              *item,
232                       gint                   new_width,
233                       gint                   new_height,
234                       gint                   new_offset_x,
235                       gint                   new_offset_y,
236                       GimpInterpolationType  interp_type,
237                       GimpProgress          *progress)
238 {
239   GIMP_ITEM_CLASS (parent_class)->scale (item, new_width, new_height,
240                                          new_offset_x, new_offset_y,
241                                          interp_type, progress);
242 
243   gimp_item_set_offset (item, 0, 0);
244 }
245 
246 static void
gimp_selection_resize(GimpItem * item,GimpContext * context,GimpFillType fill_type,gint new_width,gint new_height,gint offset_x,gint offset_y)247 gimp_selection_resize (GimpItem     *item,
248                        GimpContext  *context,
249                        GimpFillType  fill_type,
250                        gint          new_width,
251                        gint          new_height,
252                        gint          offset_x,
253                        gint          offset_y)
254 {
255   GIMP_ITEM_CLASS (parent_class)->resize (item, context, GIMP_FILL_TRANSPARENT,
256                                           new_width, new_height,
257                                           offset_x, offset_y);
258 
259   gimp_item_set_offset (item, 0, 0);
260 }
261 
262 static void
gimp_selection_flip(GimpItem * item,GimpContext * context,GimpOrientationType flip_type,gdouble axis,gboolean clip_result)263 gimp_selection_flip (GimpItem            *item,
264                      GimpContext         *context,
265                      GimpOrientationType  flip_type,
266                      gdouble              axis,
267                      gboolean             clip_result)
268 {
269   GIMP_ITEM_CLASS (parent_class)->flip (item, context, flip_type, axis, TRUE);
270 }
271 
272 static void
gimp_selection_rotate(GimpItem * item,GimpContext * context,GimpRotationType rotation_type,gdouble center_x,gdouble center_y,gboolean clip_result)273 gimp_selection_rotate (GimpItem         *item,
274                        GimpContext      *context,
275                        GimpRotationType  rotation_type,
276                        gdouble           center_x,
277                        gdouble           center_y,
278                        gboolean          clip_result)
279 {
280   GIMP_ITEM_CLASS (parent_class)->rotate (item, context, rotation_type,
281                                           center_x, center_y,
282                                           clip_result);
283 }
284 
285 static gboolean
gimp_selection_fill(GimpItem * item,GimpDrawable * drawable,GimpFillOptions * fill_options,gboolean push_undo,GimpProgress * progress,GError ** error)286 gimp_selection_fill (GimpItem         *item,
287                      GimpDrawable     *drawable,
288                      GimpFillOptions  *fill_options,
289                      gboolean          push_undo,
290                      GimpProgress     *progress,
291                      GError          **error)
292 {
293   GimpSelection      *selection = GIMP_SELECTION (item);
294   const GimpBoundSeg *dummy_in;
295   const GimpBoundSeg *dummy_out;
296   gint                num_dummy_in;
297   gint                num_dummy_out;
298   gboolean            retval;
299 
300   if (! gimp_channel_boundary (GIMP_CHANNEL (selection),
301                                &dummy_in, &dummy_out,
302                                &num_dummy_in, &num_dummy_out,
303                                0, 0, 0, 0))
304     {
305       g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
306                            _("There is no selection to fill."));
307       return FALSE;
308     }
309 
310   gimp_selection_suspend (selection);
311 
312   retval = GIMP_ITEM_CLASS (parent_class)->fill (item, drawable,
313                                                  fill_options,
314                                                  push_undo, progress, error);
315 
316   gimp_selection_resume (selection);
317 
318   return retval;
319 }
320 
321 static gboolean
gimp_selection_stroke(GimpItem * item,GimpDrawable * drawable,GimpStrokeOptions * stroke_options,gboolean push_undo,GimpProgress * progress,GError ** error)322 gimp_selection_stroke (GimpItem           *item,
323                        GimpDrawable       *drawable,
324                        GimpStrokeOptions  *stroke_options,
325                        gboolean            push_undo,
326                        GimpProgress       *progress,
327                        GError            **error)
328 {
329   GimpSelection      *selection = GIMP_SELECTION (item);
330   const GimpBoundSeg *dummy_in;
331   const GimpBoundSeg *dummy_out;
332   gint                num_dummy_in;
333   gint                num_dummy_out;
334   gboolean            retval;
335 
336   if (! gimp_channel_boundary (GIMP_CHANNEL (selection),
337                                &dummy_in, &dummy_out,
338                                &num_dummy_in, &num_dummy_out,
339                                0, 0, 0, 0))
340     {
341       g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
342                            _("There is no selection to stroke."));
343       return FALSE;
344     }
345 
346   gimp_selection_suspend (selection);
347 
348   retval = GIMP_ITEM_CLASS (parent_class)->stroke (item, drawable,
349                                                    stroke_options,
350                                                    push_undo, progress, error);
351 
352   gimp_selection_resume (selection);
353 
354   return retval;
355 }
356 
357 static void
gimp_selection_convert_type(GimpDrawable * drawable,GimpImage * dest_image,const Babl * new_format,GimpColorProfile * dest_profile,GeglDitherMethod layer_dither_type,GeglDitherMethod mask_dither_type,gboolean push_undo,GimpProgress * progress)358 gimp_selection_convert_type (GimpDrawable      *drawable,
359                              GimpImage         *dest_image,
360                              const Babl        *new_format,
361                              GimpColorProfile  *dest_profile,
362                              GeglDitherMethod   layer_dither_type,
363                              GeglDitherMethod   mask_dither_type,
364                              gboolean           push_undo,
365                              GimpProgress      *progress)
366 {
367   new_format =
368     gimp_babl_mask_format (gimp_babl_format_get_precision (new_format));
369 
370   GIMP_DRAWABLE_CLASS (parent_class)->convert_type (drawable, dest_image,
371                                                     new_format,
372                                                     dest_profile,
373                                                     layer_dither_type,
374                                                     mask_dither_type,
375                                                     push_undo,
376                                                     progress);
377 }
378 
379 static void
gimp_selection_invalidate_boundary(GimpDrawable * drawable)380 gimp_selection_invalidate_boundary (GimpDrawable *drawable)
381 {
382   GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable));
383   GimpLayer *layer;
384 
385   /*  Turn the current selection off  */
386   gimp_image_selection_invalidate (image);
387 
388   GIMP_DRAWABLE_CLASS (parent_class)->invalidate_boundary (drawable);
389 
390   /*  If there is a floating selection, update it's area...
391    *  we need to do this since this selection mask can act as an additional
392    *  mask in the composition of the floating selection
393    */
394   layer = gimp_image_get_active_layer (image);
395 
396   if (layer && gimp_layer_is_floating_sel (layer))
397     {
398       gimp_drawable_update (GIMP_DRAWABLE (layer), 0, 0, -1, -1);
399     }
400 
401 #if 0
402   /*  invalidate the preview  */
403   drawable->private->preview_valid = FALSE;
404 #endif
405 }
406 
407 static gboolean
gimp_selection_boundary(GimpChannel * channel,const GimpBoundSeg ** segs_in,const GimpBoundSeg ** segs_out,gint * num_segs_in,gint * num_segs_out,gint unused1,gint unused2,gint unused3,gint unused4)408 gimp_selection_boundary (GimpChannel         *channel,
409                          const GimpBoundSeg **segs_in,
410                          const GimpBoundSeg **segs_out,
411                          gint                *num_segs_in,
412                          gint                *num_segs_out,
413                          gint                 unused1,
414                          gint                 unused2,
415                          gint                 unused3,
416                          gint                 unused4)
417 {
418   GimpImage    *image = gimp_item_get_image (GIMP_ITEM (channel));
419   GimpDrawable *drawable;
420   GimpLayer    *layer;
421 
422   if ((layer = gimp_image_get_floating_selection (image)))
423     {
424       /*  If there is a floating selection, then
425        *  we need to do some slightly different boundaries.
426        *  Instead of inside and outside boundaries being defined
427        *  by the extents of the layer, the inside boundary (the one
428        *  that actually marches and is black/white) is the boundary of
429        *  the floating selection.  The outside boundary (doesn't move,
430        *  is black/gray) is defined as the normal selection mask
431        */
432 
433       /*  Find the selection mask boundary  */
434       GIMP_CHANNEL_CLASS (parent_class)->boundary (channel,
435                                                    segs_in, segs_out,
436                                                    num_segs_in, num_segs_out,
437                                                    0, 0, 0, 0);
438 
439       /*  Find the floating selection boundary  */
440       *segs_in = floating_sel_boundary (layer, num_segs_in);
441 
442       return TRUE;
443     }
444   else if ((drawable = gimp_image_get_active_drawable (image)) &&
445            GIMP_IS_CHANNEL (drawable))
446     {
447       /*  Otherwise, return the boundary...if a channel is active  */
448 
449       return GIMP_CHANNEL_CLASS (parent_class)->boundary (channel,
450                                                           segs_in, segs_out,
451                                                           num_segs_in,
452                                                           num_segs_out,
453                                                           0, 0,
454                                                           gimp_image_get_width  (image),
455                                                           gimp_image_get_height (image));
456     }
457   else if ((layer = gimp_image_get_active_layer (image)))
458     {
459       /*  If a layer is active, we return multiple boundaries based
460        *  on the extents
461        */
462 
463       gint x1, y1;
464       gint x2, y2;
465       gint offset_x;
466       gint offset_y;
467 
468       gimp_item_get_offset (GIMP_ITEM (layer), &offset_x, &offset_y);
469 
470       x1 = CLAMP (offset_x, 0, gimp_image_get_width  (image));
471       y1 = CLAMP (offset_y, 0, gimp_image_get_height (image));
472       x2 = CLAMP (offset_x + gimp_item_get_width (GIMP_ITEM (layer)),
473                   0, gimp_image_get_width (image));
474       y2 = CLAMP (offset_y + gimp_item_get_height (GIMP_ITEM (layer)),
475                   0, gimp_image_get_height (image));
476 
477       return GIMP_CHANNEL_CLASS (parent_class)->boundary (channel,
478                                                           segs_in, segs_out,
479                                                           num_segs_in,
480                                                           num_segs_out,
481                                                           x1, y1, x2, y2);
482     }
483 
484   *segs_in      = NULL;
485   *segs_out     = NULL;
486   *num_segs_in  = 0;
487   *num_segs_out = 0;
488 
489   return FALSE;
490 }
491 
492 static gboolean
gimp_selection_is_empty(GimpChannel * channel)493 gimp_selection_is_empty (GimpChannel *channel)
494 {
495   GimpSelection *selection = GIMP_SELECTION (channel);
496 
497   /*  in order to allow stroking of selections, we need to pretend here
498    *  that the selection mask is empty so that it doesn't mask the paint
499    *  during the stroke operation.
500    */
501   if (selection->suspend_count > 0)
502     return TRUE;
503 
504   return GIMP_CHANNEL_CLASS (parent_class)->is_empty (channel);
505 }
506 
507 static void
gimp_selection_feather(GimpChannel * channel,gdouble radius_x,gdouble radius_y,gboolean edge_lock,gboolean push_undo)508 gimp_selection_feather (GimpChannel *channel,
509                         gdouble      radius_x,
510                         gdouble      radius_y,
511                         gboolean     edge_lock,
512                         gboolean     push_undo)
513 {
514   GIMP_CHANNEL_CLASS (parent_class)->feather (channel, radius_x, radius_y,
515                                               edge_lock, push_undo);
516 }
517 
518 static void
gimp_selection_sharpen(GimpChannel * channel,gboolean push_undo)519 gimp_selection_sharpen (GimpChannel *channel,
520                         gboolean     push_undo)
521 {
522   GIMP_CHANNEL_CLASS (parent_class)->sharpen (channel, push_undo);
523 }
524 
525 static void
gimp_selection_clear(GimpChannel * channel,const gchar * undo_desc,gboolean push_undo)526 gimp_selection_clear (GimpChannel *channel,
527                       const gchar *undo_desc,
528                       gboolean     push_undo)
529 {
530   GIMP_CHANNEL_CLASS (parent_class)->clear (channel, undo_desc, push_undo);
531 }
532 
533 static void
gimp_selection_all(GimpChannel * channel,gboolean push_undo)534 gimp_selection_all (GimpChannel *channel,
535                     gboolean     push_undo)
536 {
537   GIMP_CHANNEL_CLASS (parent_class)->all (channel, push_undo);
538 }
539 
540 static void
gimp_selection_invert(GimpChannel * channel,gboolean push_undo)541 gimp_selection_invert (GimpChannel *channel,
542                        gboolean     push_undo)
543 {
544   GIMP_CHANNEL_CLASS (parent_class)->invert (channel, push_undo);
545 }
546 
547 static void
gimp_selection_border(GimpChannel * channel,gint radius_x,gint radius_y,GimpChannelBorderStyle style,gboolean edge_lock,gboolean push_undo)548 gimp_selection_border (GimpChannel            *channel,
549                        gint                    radius_x,
550                        gint                    radius_y,
551                        GimpChannelBorderStyle  style,
552                        gboolean                edge_lock,
553                        gboolean                push_undo)
554 {
555   GIMP_CHANNEL_CLASS (parent_class)->border (channel,
556                                              radius_x, radius_y,
557                                              style, edge_lock,
558                                              push_undo);
559 }
560 
561 static void
gimp_selection_grow(GimpChannel * channel,gint radius_x,gint radius_y,gboolean push_undo)562 gimp_selection_grow (GimpChannel *channel,
563                      gint         radius_x,
564                      gint         radius_y,
565                      gboolean     push_undo)
566 {
567   GIMP_CHANNEL_CLASS (parent_class)->grow (channel,
568                                            radius_x, radius_y,
569                                            push_undo);
570 }
571 
572 static void
gimp_selection_shrink(GimpChannel * channel,gint radius_x,gint radius_y,gboolean edge_lock,gboolean push_undo)573 gimp_selection_shrink (GimpChannel *channel,
574                        gint         radius_x,
575                        gint         radius_y,
576                        gboolean     edge_lock,
577                        gboolean     push_undo)
578 {
579   GIMP_CHANNEL_CLASS (parent_class)->shrink (channel,
580                                              radius_x, radius_y, edge_lock,
581                                              push_undo);
582 }
583 
584 static void
gimp_selection_flood(GimpChannel * channel,gboolean push_undo)585 gimp_selection_flood (GimpChannel *channel,
586                       gboolean     push_undo)
587 {
588   GIMP_CHANNEL_CLASS (parent_class)->flood (channel, push_undo);
589 }
590 
591 
592 /*  public functions  */
593 
594 GimpChannel *
gimp_selection_new(GimpImage * image,gint width,gint height)595 gimp_selection_new (GimpImage *image,
596                     gint       width,
597                     gint       height)
598 {
599   GimpRGB      black = { 0.0, 0.0, 0.0, 0.5 };
600   GimpChannel *channel;
601 
602   g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
603   g_return_val_if_fail (width > 0 && height > 0, NULL);
604 
605   channel = GIMP_CHANNEL (gimp_drawable_new (GIMP_TYPE_SELECTION,
606                                              image, NULL,
607                                              0, 0, width, height,
608                                              gimp_image_get_mask_format (image)));
609 
610   gimp_channel_set_color (channel, &black, FALSE);
611   gimp_channel_set_show_masked (channel, TRUE);
612 
613   channel->x2 = width;
614   channel->y2 = height;
615 
616   return channel;
617 }
618 
619 gint
gimp_selection_suspend(GimpSelection * selection)620 gimp_selection_suspend (GimpSelection *selection)
621 {
622   g_return_val_if_fail (GIMP_IS_SELECTION (selection), 0);
623 
624   selection->suspend_count++;
625 
626   return selection->suspend_count;
627 }
628 
629 gint
gimp_selection_resume(GimpSelection * selection)630 gimp_selection_resume (GimpSelection *selection)
631 {
632   g_return_val_if_fail (GIMP_IS_SELECTION (selection), 0);
633   g_return_val_if_fail (selection->suspend_count > 0, 0);
634 
635   selection->suspend_count--;
636 
637   return selection->suspend_count;
638 }
639 
640 GeglBuffer *
gimp_selection_extract(GimpSelection * selection,GimpPickable * pickable,GimpContext * context,gboolean cut_image,gboolean keep_indexed,gboolean add_alpha,gint * offset_x,gint * offset_y,GError ** error)641 gimp_selection_extract (GimpSelection *selection,
642                         GimpPickable  *pickable,
643                         GimpContext   *context,
644                         gboolean       cut_image,
645                         gboolean       keep_indexed,
646                         gboolean       add_alpha,
647                         gint          *offset_x,
648                         gint          *offset_y,
649                         GError       **error)
650 {
651   GimpImage  *image;
652   GeglBuffer *src_buffer;
653   GeglBuffer *dest_buffer;
654   const Babl *src_format;
655   const Babl *dest_format;
656   gint        x1, y1, x2, y2;
657   gboolean    non_empty;
658   gint        off_x, off_y;
659 
660   g_return_val_if_fail (GIMP_IS_SELECTION (selection), NULL);
661   g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), NULL);
662   if (GIMP_IS_ITEM (pickable))
663     g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (pickable)), NULL);
664   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
665   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
666 
667   image = gimp_pickable_get_image (pickable);
668 
669   /*  If there are no bounds, then just extract the entire image
670    *  This may not be the correct behavior, but after getting rid
671    *  of floating selections, it's still tempting to "cut" or "copy"
672    *  a small layer and expect it to work, even though there is no
673    *  actual selection mask
674    */
675   if (GIMP_IS_DRAWABLE (pickable))
676     {
677       non_empty = gimp_item_mask_bounds (GIMP_ITEM (pickable),
678                                          &x1, &y1, &x2, &y2);
679 
680       gimp_item_get_offset (GIMP_ITEM (pickable), &off_x, &off_y);
681     }
682   else
683     {
684       non_empty = gimp_item_bounds (GIMP_ITEM (selection),
685                                     &x1, &y1, &x2, &y2);
686       x2 += x1;
687       y2 += y1;
688 
689       off_x = 0;
690       off_y = 0;
691 
692       /* can't cut from non-drawables, fall back to copy */
693       cut_image = FALSE;
694     }
695 
696   if (non_empty && ((x1 == x2) || (y1 == y2)))
697     {
698       g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
699                            _("Unable to cut or copy because the "
700                              "selected region is empty."));
701       return NULL;
702     }
703 
704   /*  If there is a selection, we must add alpha because the selection
705    *  could have any shape.
706    */
707   if (non_empty)
708     add_alpha = TRUE;
709 
710   src_format = gimp_pickable_get_format (pickable);
711 
712   /*  How many bytes in the temp buffer?  */
713   if (babl_format_is_palette (src_format) && ! keep_indexed)
714     {
715       dest_format = gimp_image_get_format (image, GIMP_RGB,
716                                            gimp_image_get_precision (image),
717                                            add_alpha ||
718                                            babl_format_has_alpha (src_format));
719     }
720   else
721     {
722       if (add_alpha)
723         dest_format = gimp_pickable_get_format_with_alpha (pickable);
724       else
725         dest_format = src_format;
726     }
727 
728   gimp_pickable_flush (pickable);
729 
730   src_buffer = gimp_pickable_get_buffer (pickable);
731 
732   /*  Allocate the temp buffer  */
733   dest_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, x2 - x1, y2 - y1),
734                                  dest_format);
735 
736   /*  First, copy the pixels, possibly doing INDEXED->RGB and adding alpha  */
737   gimp_gegl_buffer_copy (src_buffer,  GEGL_RECTANGLE (x1, y1, x2 - x1, y2 - y1),
738                          GEGL_ABYSS_NONE,
739                          dest_buffer, GEGL_RECTANGLE (0, 0, 0, 0));
740 
741   if (non_empty)
742     {
743       /*  If there is a selection, mask the dest_buffer with it  */
744 
745       GeglBuffer *mask_buffer;
746 
747       mask_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (selection));
748 
749       gimp_gegl_apply_opacity (dest_buffer, NULL, NULL, dest_buffer,
750                                mask_buffer,
751                                - (off_x + x1),
752                                - (off_y + y1),
753                                1.0);
754 
755       if (cut_image)
756         {
757           gimp_drawable_edit_clear (GIMP_DRAWABLE (pickable), context);
758         }
759     }
760   else if (cut_image)
761     {
762       /*  If we're cutting without selection, remove either the layer
763        *  (or floating selection), the layer mask, or the channel
764        */
765       if (GIMP_IS_LAYER (pickable))
766         {
767           gimp_image_remove_layer (image, GIMP_LAYER (pickable),
768                                    TRUE, NULL);
769         }
770       else if (GIMP_IS_LAYER_MASK (pickable))
771         {
772           gimp_layer_apply_mask (gimp_layer_mask_get_layer (GIMP_LAYER_MASK (pickable)),
773                                  GIMP_MASK_DISCARD, TRUE);
774         }
775       else if (GIMP_IS_CHANNEL (pickable))
776         {
777           gimp_image_remove_channel (image, GIMP_CHANNEL (pickable),
778                                      TRUE, NULL);
779         }
780     }
781 
782   *offset_x = x1 + off_x;
783   *offset_y = y1 + off_y;
784 
785   return dest_buffer;
786 }
787 
788 GimpLayer *
gimp_selection_float(GimpSelection * selection,GimpDrawable * drawable,GimpContext * context,gboolean cut_image,gint off_x,gint off_y,GError ** error)789 gimp_selection_float (GimpSelection *selection,
790                       GimpDrawable  *drawable,
791                       GimpContext   *context,
792                       gboolean       cut_image,
793                       gint           off_x,
794                       gint           off_y,
795                       GError       **error)
796 {
797   GimpImage        *image;
798   GimpLayer        *layer;
799   GeglBuffer       *buffer;
800   GimpColorProfile *profile;
801   gint              x1, y1;
802   gint              x2, y2;
803 
804   g_return_val_if_fail (GIMP_IS_SELECTION (selection), NULL);
805   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
806   g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), NULL);
807   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
808   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
809 
810   image = gimp_item_get_image (GIMP_ITEM (selection));
811 
812   /*  Make sure there is a region to float...  */
813   if (! gimp_item_mask_bounds (GIMP_ITEM (drawable), &x1, &y1, &x2, &y2) ||
814       (x1 == x2 || y1 == y2))
815     {
816       g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
817                            _("Cannot float selection because the selected "
818                              "region is empty."));
819       return NULL;
820     }
821 
822   /*  Start an undo group  */
823   gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_FS_FLOAT,
824                                C_("undo-type", "Float Selection"));
825 
826   /*  Cut or copy the selected region  */
827   buffer = gimp_selection_extract (selection, GIMP_PICKABLE (drawable), context,
828                                    cut_image, FALSE, TRUE,
829                                    &x1, &y1, NULL);
830 
831   profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (drawable));
832 
833   /*  Clear the selection  */
834   gimp_channel_clear (GIMP_CHANNEL (selection), NULL, TRUE);
835 
836   /* Create a new layer from the buffer, using the drawable's type
837    *  because it may be different from the image's type if we cut from
838    *  a channel or layer mask
839    */
840   layer = gimp_layer_new_from_gegl_buffer (buffer, image,
841                                            gimp_drawable_get_format_with_alpha (drawable),
842                                            _("Floated Layer"),
843                                            GIMP_OPACITY_OPAQUE,
844                                            gimp_image_get_default_new_layer_mode (image),
845                                            profile);
846 
847   /*  Set the offsets  */
848   gimp_item_set_offset (GIMP_ITEM (layer), x1 + off_x, y1 + off_y);
849 
850   /*  Free the temp buffer  */
851   g_object_unref (buffer);
852 
853   /*  Add the floating layer to the image  */
854   floating_sel_attach (layer, drawable);
855 
856   /*  End an undo group  */
857   gimp_image_undo_group_end (image);
858 
859   /*  invalidate the image's boundary variables  */
860   GIMP_CHANNEL (selection)->boundary_known = FALSE;
861 
862   return layer;
863 }
864