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 <string.h>
21 
22 #include <cairo.h>
23 #include <gegl.h>
24 #include <gdk-pixbuf/gdk-pixbuf.h>
25 
26 #include "libgimpbase/gimpbase.h"
27 #include "libgimpmath/gimpmath.h"
28 #include "libgimpcolor/gimpcolor.h"
29 
30 #include "core-types.h"
31 
32 #include "paint/gimppaintcore-stroke.h"
33 #include "paint/gimppaintoptions.h"
34 
35 #include "gegl/gimp-gegl-apply-operation.h"
36 #include "gegl/gimp-gegl-loops.h"
37 #include "gegl/gimp-gegl-mask.h"
38 #include "gegl/gimp-gegl-nodes.h"
39 
40 #include "gimp.h"
41 #include "gimp-utils.h"
42 #include "gimpboundary.h"
43 #include "gimpcontainer.h"
44 #include "gimperror.h"
45 #include "gimpimage.h"
46 #include "gimpimage-quick-mask.h"
47 #include "gimpimage-undo.h"
48 #include "gimpimage-undo-push.h"
49 #include "gimpchannel.h"
50 #include "gimpchannel-select.h"
51 #include "gimpcontext.h"
52 #include "gimpdrawable-fill.h"
53 #include "gimpdrawable-stroke.h"
54 #include "gimpmarshal.h"
55 #include "gimppaintinfo.h"
56 #include "gimppickable.h"
57 #include "gimpstrokeoptions.h"
58 
59 #include "gimp-intl.h"
60 
61 
62 #define RGBA_EPSILON 1e-6
63 
64 enum
65 {
66   COLOR_CHANGED,
67   LAST_SIGNAL
68 };
69 
70 
71 static void gimp_channel_pickable_iface_init (GimpPickableInterface *iface);
72 
73 static void       gimp_channel_finalize      (GObject           *object);
74 
75 static gint64     gimp_channel_get_memsize   (GimpObject        *object,
76                                               gint64            *gui_size);
77 
78 static gchar  * gimp_channel_get_description (GimpViewable      *viewable,
79                                               gchar            **tooltip);
80 
81 static GeglNode * gimp_channel_get_node      (GimpFilter        *filter);
82 
83 static gboolean   gimp_channel_is_attached   (GimpItem          *item);
84 static GimpItemTree * gimp_channel_get_tree  (GimpItem          *item);
85 static gboolean   gimp_channel_bounds        (GimpItem          *item,
86                                               gdouble           *x,
87                                               gdouble           *y,
88                                               gdouble           *width,
89                                               gdouble           *height);
90 static GimpItem * gimp_channel_duplicate     (GimpItem          *item,
91                                               GType              new_type);
92 static void       gimp_channel_convert       (GimpItem          *item,
93                                               GimpImage         *dest_image,
94                                               GType              old_type);
95 static void       gimp_channel_translate     (GimpItem          *item,
96                                               gdouble            off_x,
97                                               gdouble            off_y,
98                                               gboolean           push_undo);
99 static void       gimp_channel_scale         (GimpItem          *item,
100                                               gint               new_width,
101                                               gint               new_height,
102                                               gint               new_offset_x,
103                                               gint               new_offset_y,
104                                               GimpInterpolationType interp_type,
105                                               GimpProgress      *progress);
106 static void       gimp_channel_resize        (GimpItem          *item,
107                                               GimpContext       *context,
108                                               GimpFillType       fill_type,
109                                               gint               new_width,
110                                               gint               new_height,
111                                               gint               offset_x,
112                                               gint               offset_y);
113 static GimpTransformResize
114                   gimp_channel_get_clip      (GimpItem          *item,
115                                               GimpTransformResize clip_result);
116 static gboolean   gimp_channel_fill          (GimpItem          *item,
117                                               GimpDrawable      *drawable,
118                                               GimpFillOptions   *fill_options,
119                                               gboolean           push_undo,
120                                               GimpProgress      *progress,
121                                               GError           **error);
122 static gboolean   gimp_channel_stroke        (GimpItem          *item,
123                                               GimpDrawable      *drawable,
124                                               GimpStrokeOptions *stroke_options,
125                                               gboolean           push_undo,
126                                               GimpProgress      *progress,
127                                               GError           **error);
128 static void       gimp_channel_to_selection  (GimpItem          *item,
129                                               GimpChannelOps     op,
130                                               gboolean           antialias,
131                                               gboolean           feather,
132                                               gdouble            feather_radius_x,
133                                               gdouble            feather_radius_y);
134 
135 static void       gimp_channel_convert_type  (GimpDrawable      *drawable,
136                                               GimpImage         *dest_image,
137                                               const Babl        *new_format,
138                                               GimpColorProfile  *dest_profile,
139                                               GeglDitherMethod   layer_dither_type,
140                                               GeglDitherMethod   mask_dither_type,
141                                               gboolean           push_undo,
142                                               GimpProgress      *progress);
143 static void gimp_channel_invalidate_boundary   (GimpDrawable       *drawable);
144 static void gimp_channel_get_active_components (GimpDrawable       *drawable,
145                                                 gboolean           *active);
146 
147 static void      gimp_channel_set_buffer     (GimpDrawable        *drawable,
148                                               gboolean             push_undo,
149                                               const gchar         *undo_desc,
150                                               GeglBuffer          *buffer,
151                                               const GeglRectangle *bounds);
152 
153 static gdouble   gimp_channel_get_opacity_at (GimpPickable        *pickable,
154                                               gint                 x,
155                                               gint                 y);
156 
157 static gboolean   gimp_channel_real_boundary (GimpChannel         *channel,
158                                               const GimpBoundSeg **segs_in,
159                                               const GimpBoundSeg **segs_out,
160                                               gint                *num_segs_in,
161                                               gint                *num_segs_out,
162                                               gint                 x1,
163                                               gint                 y1,
164                                               gint                 x2,
165                                               gint                 y2);
166 static gboolean   gimp_channel_real_is_empty (GimpChannel         *channel);
167 static void       gimp_channel_real_feather  (GimpChannel         *channel,
168                                               gdouble              radius_x,
169                                               gdouble              radius_y,
170                                               gboolean             edge_lock,
171                                               gboolean             push_undo);
172 static void       gimp_channel_real_sharpen  (GimpChannel         *channel,
173                                               gboolean             push_undo);
174 static void       gimp_channel_real_clear    (GimpChannel         *channel,
175                                               const gchar         *undo_desc,
176                                               gboolean             push_undo);
177 static void       gimp_channel_real_all      (GimpChannel         *channel,
178                                               gboolean             push_undo);
179 static void       gimp_channel_real_invert   (GimpChannel         *channel,
180                                               gboolean             push_undo);
181 static void       gimp_channel_real_border   (GimpChannel         *channel,
182                                               gint                 radius_x,
183                                               gint                 radius_y,
184                                               GimpChannelBorderStyle style,
185                                               gboolean             edge_lock,
186                                               gboolean             push_undo);
187 static void       gimp_channel_real_grow     (GimpChannel         *channel,
188                                               gint                 radius_x,
189                                               gint                 radius_y,
190                                               gboolean             push_undo);
191 static void       gimp_channel_real_shrink   (GimpChannel         *channel,
192                                               gint                 radius_x,
193                                               gint                 radius_y,
194                                               gboolean             edge_lock,
195                                               gboolean             push_undo);
196 static void       gimp_channel_real_flood    (GimpChannel         *channel,
197                                               gboolean             push_undo);
198 
199 
200 static void      gimp_channel_buffer_changed (GeglBuffer          *buffer,
201                                               const GeglRectangle *rect,
202                                               GimpChannel         *channel);
203 
204 
205 G_DEFINE_TYPE_WITH_CODE (GimpChannel, gimp_channel, GIMP_TYPE_DRAWABLE,
206                          G_IMPLEMENT_INTERFACE (GIMP_TYPE_PICKABLE,
207                                                 gimp_channel_pickable_iface_init))
208 
209 #define parent_class gimp_channel_parent_class
210 
211 static guint channel_signals[LAST_SIGNAL] = { 0 };
212 
213 
214 static void
gimp_channel_class_init(GimpChannelClass * klass)215 gimp_channel_class_init (GimpChannelClass *klass)
216 {
217   GObjectClass      *object_class      = G_OBJECT_CLASS (klass);
218   GimpObjectClass   *gimp_object_class = GIMP_OBJECT_CLASS (klass);
219   GimpViewableClass *viewable_class    = GIMP_VIEWABLE_CLASS (klass);
220   GimpFilterClass   *filter_class      = GIMP_FILTER_CLASS (klass);
221   GimpItemClass     *item_class        = GIMP_ITEM_CLASS (klass);
222   GimpDrawableClass *drawable_class    = GIMP_DRAWABLE_CLASS (klass);
223 
224   channel_signals[COLOR_CHANGED] =
225     g_signal_new ("color-changed",
226                   G_TYPE_FROM_CLASS (klass),
227                   G_SIGNAL_RUN_FIRST,
228                   G_STRUCT_OFFSET (GimpChannelClass, color_changed),
229                   NULL, NULL,
230                   gimp_marshal_VOID__VOID,
231                   G_TYPE_NONE, 0);
232 
233   object_class->finalize            = gimp_channel_finalize;
234 
235   gimp_object_class->get_memsize    = gimp_channel_get_memsize;
236 
237   viewable_class->get_description   = gimp_channel_get_description;
238   viewable_class->default_icon_name = "gimp-channel";
239 
240   filter_class->get_node            = gimp_channel_get_node;
241 
242   item_class->is_attached          = gimp_channel_is_attached;
243   item_class->get_tree             = gimp_channel_get_tree;
244   item_class->bounds               = gimp_channel_bounds;
245   item_class->duplicate            = gimp_channel_duplicate;
246   item_class->convert              = gimp_channel_convert;
247   item_class->translate            = gimp_channel_translate;
248   item_class->scale                = gimp_channel_scale;
249   item_class->resize               = gimp_channel_resize;
250   item_class->get_clip             = gimp_channel_get_clip;
251   item_class->fill                 = gimp_channel_fill;
252   item_class->stroke               = gimp_channel_stroke;
253   item_class->to_selection         = gimp_channel_to_selection;
254   item_class->default_name         = _("Channel");
255   item_class->rename_desc          = C_("undo-type", "Rename Channel");
256   item_class->translate_desc       = C_("undo-type", "Move Channel");
257   item_class->scale_desc           = C_("undo-type", "Scale Channel");
258   item_class->resize_desc          = C_("undo-type", "Resize Channel");
259   item_class->flip_desc            = C_("undo-type", "Flip Channel");
260   item_class->rotate_desc          = C_("undo-type", "Rotate Channel");
261   item_class->transform_desc       = C_("undo-type", "Transform Channel");
262   item_class->fill_desc            = C_("undo-type", "Fill Channel");
263   item_class->stroke_desc          = C_("undo-type", "Stroke Channel");
264   item_class->to_selection_desc    = C_("undo-type", "Channel to Selection");
265   item_class->reorder_desc         = C_("undo-type", "Reorder Channel");
266   item_class->raise_desc           = C_("undo-type", "Raise Channel");
267   item_class->raise_to_top_desc    = C_("undo-type", "Raise Channel to Top");
268   item_class->lower_desc           = C_("undo-type", "Lower Channel");
269   item_class->lower_to_bottom_desc = C_("undo-type", "Lower Channel to Bottom");
270   item_class->raise_failed         = _("Channel cannot be raised higher.");
271   item_class->lower_failed         = _("Channel cannot be lowered more.");
272 
273   drawable_class->convert_type          = gimp_channel_convert_type;
274   drawable_class->invalidate_boundary   = gimp_channel_invalidate_boundary;
275   drawable_class->get_active_components = gimp_channel_get_active_components;
276   drawable_class->set_buffer            = gimp_channel_set_buffer;
277 
278   klass->boundary       = gimp_channel_real_boundary;
279   klass->is_empty       = gimp_channel_real_is_empty;
280   klass->feather        = gimp_channel_real_feather;
281   klass->sharpen        = gimp_channel_real_sharpen;
282   klass->clear          = gimp_channel_real_clear;
283   klass->all            = gimp_channel_real_all;
284   klass->invert         = gimp_channel_real_invert;
285   klass->border         = gimp_channel_real_border;
286   klass->grow           = gimp_channel_real_grow;
287   klass->shrink         = gimp_channel_real_shrink;
288   klass->flood          = gimp_channel_real_flood;
289 
290   klass->feather_desc   = C_("undo-type", "Feather Channel");
291   klass->sharpen_desc   = C_("undo-type", "Sharpen Channel");
292   klass->clear_desc     = C_("undo-type", "Clear Channel");
293   klass->all_desc       = C_("undo-type", "Fill Channel");
294   klass->invert_desc    = C_("undo-type", "Invert Channel");
295   klass->border_desc    = C_("undo-type", "Border Channel");
296   klass->grow_desc      = C_("undo-type", "Grow Channel");
297   klass->shrink_desc    = C_("undo-type", "Shrink Channel");
298   klass->flood_desc     = C_("undo-type", "Flood Channel");
299 }
300 
301 static void
gimp_channel_init(GimpChannel * channel)302 gimp_channel_init (GimpChannel *channel)
303 {
304   gimp_rgba_set (&channel->color, 0.0, 0.0, 0.0, GIMP_OPACITY_OPAQUE);
305 
306   channel->show_masked    = FALSE;
307 
308   /*  Selection mask variables  */
309   channel->boundary_known = FALSE;
310   channel->segs_in        = NULL;
311   channel->segs_out       = NULL;
312   channel->num_segs_in    = 0;
313   channel->num_segs_out   = 0;
314   channel->empty          = FALSE;
315   channel->bounds_known   = FALSE;
316   channel->x1             = 0;
317   channel->y1             = 0;
318   channel->x2             = 0;
319   channel->y2             = 0;
320 }
321 
322 static void
gimp_channel_pickable_iface_init(GimpPickableInterface * iface)323 gimp_channel_pickable_iface_init (GimpPickableInterface *iface)
324 {
325   iface->get_opacity_at = gimp_channel_get_opacity_at;
326 }
327 
328 static void
gimp_channel_finalize(GObject * object)329 gimp_channel_finalize (GObject *object)
330 {
331   GimpChannel *channel = GIMP_CHANNEL (object);
332 
333   g_clear_pointer (&channel->segs_in,  g_free);
334   g_clear_pointer (&channel->segs_out, g_free);
335 
336   G_OBJECT_CLASS (parent_class)->finalize (object);
337 }
338 
339 static gint64
gimp_channel_get_memsize(GimpObject * object,gint64 * gui_size)340 gimp_channel_get_memsize (GimpObject *object,
341                           gint64     *gui_size)
342 {
343   GimpChannel *channel = GIMP_CHANNEL (object);
344 
345   *gui_size += channel->num_segs_in  * sizeof (GimpBoundSeg);
346   *gui_size += channel->num_segs_out * sizeof (GimpBoundSeg);
347 
348   return GIMP_OBJECT_CLASS (parent_class)->get_memsize (object, gui_size);
349 }
350 
351 static gchar *
gimp_channel_get_description(GimpViewable * viewable,gchar ** tooltip)352 gimp_channel_get_description (GimpViewable  *viewable,
353                               gchar        **tooltip)
354 {
355   if (! strcmp (GIMP_IMAGE_QUICK_MASK_NAME,
356                 gimp_object_get_name (viewable)))
357     {
358       return g_strdup (_("Quick Mask"));
359     }
360 
361   return GIMP_VIEWABLE_CLASS (parent_class)->get_description (viewable,
362                                                               tooltip);
363 }
364 
365 static GeglNode *
gimp_channel_get_node(GimpFilter * filter)366 gimp_channel_get_node (GimpFilter *filter)
367 {
368   GimpDrawable *drawable = GIMP_DRAWABLE (filter);
369   GimpChannel  *channel  = GIMP_CHANNEL (filter);
370   GeglNode     *node;
371   GeglNode     *source;
372   GeglNode     *mode_node;
373   const Babl   *color_format;
374 
375   node = GIMP_FILTER_CLASS (parent_class)->get_node (filter);
376 
377   source = gimp_drawable_get_source_node (drawable);
378   gegl_node_add_child (node, source);
379 
380   g_warn_if_fail (channel->color_node == NULL);
381 
382   if (gimp_drawable_get_linear (drawable))
383     color_format = babl_format ("RGBA float");
384   else
385     color_format = babl_format ("R'G'B'A float");
386 
387   channel->color_node = gegl_node_new_child (node,
388                                              "operation", "gegl:color",
389                                              "format",    color_format,
390                                              NULL);
391   gimp_gegl_node_set_color (channel->color_node,
392                             &channel->color);
393 
394   g_warn_if_fail (channel->mask_node == NULL);
395 
396   channel->mask_node = gegl_node_new_child (node,
397                                             "operation", "gegl:opacity",
398                                             NULL);
399   gegl_node_connect_to (channel->color_node, "output",
400                         channel->mask_node,  "input");
401 
402   g_warn_if_fail (channel->invert_node == NULL);
403 
404   channel->invert_node = gegl_node_new_child (node,
405                                               "operation", "gegl:invert-linear",
406                                               NULL);
407 
408   if (channel->show_masked)
409     {
410       gegl_node_connect_to (source,               "output",
411                             channel->invert_node, "input");
412       gegl_node_connect_to (channel->invert_node, "output",
413                             channel->mask_node,   "aux");
414     }
415   else
416     {
417       gegl_node_connect_to (source,             "output",
418                             channel->mask_node, "aux");
419     }
420 
421   mode_node = gimp_drawable_get_mode_node (drawable);
422 
423   gegl_node_connect_to (channel->mask_node, "output",
424                         mode_node,          "aux");
425 
426   return node;
427 }
428 
429 static gboolean
gimp_channel_is_attached(GimpItem * item)430 gimp_channel_is_attached (GimpItem *item)
431 {
432   GimpImage *image = gimp_item_get_image (item);
433 
434   return (GIMP_IS_IMAGE (image) &&
435           gimp_container_have (gimp_image_get_channels (image),
436                                GIMP_OBJECT (item)));
437 }
438 
439 static GimpItemTree *
gimp_channel_get_tree(GimpItem * item)440 gimp_channel_get_tree (GimpItem *item)
441 {
442   if (gimp_item_is_attached (item))
443     {
444       GimpImage *image = gimp_item_get_image (item);
445 
446       return gimp_image_get_channel_tree (image);
447     }
448 
449   return NULL;
450 }
451 
452 static gboolean
gimp_channel_bounds(GimpItem * item,gdouble * x,gdouble * y,gdouble * width,gdouble * height)453 gimp_channel_bounds (GimpItem *item,
454                      gdouble  *x,
455                      gdouble  *y,
456                      gdouble  *width,
457                      gdouble  *height)
458 {
459   GimpChannel *channel = GIMP_CHANNEL (item);
460 
461   if (! channel->bounds_known)
462     {
463       GeglBuffer *buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (channel));
464 
465       channel->empty = ! gimp_gegl_mask_bounds (buffer,
466                                                 &channel->x1,
467                                                 &channel->y1,
468                                                 &channel->x2,
469                                                 &channel->y2);
470 
471       channel->bounds_known = TRUE;
472     }
473 
474   *x      = channel->x1;
475   *y      = channel->y1;
476   *width  = channel->x2 - channel->x1;
477   *height = channel->y2 - channel->y1;
478 
479   return ! channel->empty;
480 }
481 
482 static GimpItem *
gimp_channel_duplicate(GimpItem * item,GType new_type)483 gimp_channel_duplicate (GimpItem *item,
484                         GType     new_type)
485 {
486   GimpItem *new_item;
487 
488   g_return_val_if_fail (g_type_is_a (new_type, GIMP_TYPE_DRAWABLE), NULL);
489 
490   new_item = GIMP_ITEM_CLASS (parent_class)->duplicate (item, new_type);
491 
492   if (GIMP_IS_CHANNEL (new_item))
493     {
494       GimpChannel *channel     = GIMP_CHANNEL (item);
495       GimpChannel *new_channel = GIMP_CHANNEL (new_item);
496 
497       new_channel->color        = channel->color;
498       new_channel->show_masked  = channel->show_masked;
499 
500       /*  selection mask variables  */
501       new_channel->bounds_known = channel->bounds_known;
502       new_channel->empty        = channel->empty;
503       new_channel->x1           = channel->x1;
504       new_channel->y1           = channel->y1;
505       new_channel->x2           = channel->x2;
506       new_channel->y2           = channel->y2;
507 
508       if (new_type == GIMP_TYPE_CHANNEL)
509         {
510           /*  8-bit channel hack: make sure pixels between all sorts
511            *  of channels of an image is always copied without any
512            *  gamma conversion
513            */
514           GimpDrawable *new_drawable = GIMP_DRAWABLE (new_item);
515           GimpImage    *image        = gimp_item_get_image (item);
516           const Babl   *format       = gimp_image_get_channel_format (image);
517 
518           if (format != gimp_drawable_get_format (new_drawable))
519             {
520               GeglBuffer *new_buffer;
521 
522               new_buffer =
523                 gegl_buffer_new (GEGL_RECTANGLE (0, 0,
524                                                  gimp_item_get_width  (new_item),
525                                                  gimp_item_get_height (new_item)),
526                                  format);
527 
528               gegl_buffer_set_format (new_buffer,
529                                       gimp_drawable_get_format (new_drawable));
530               gimp_gegl_buffer_copy (gimp_drawable_get_buffer (new_drawable),
531                                      NULL, GEGL_ABYSS_NONE,
532                                      new_buffer, NULL);
533               gegl_buffer_set_format (new_buffer, NULL);
534 
535               gimp_drawable_set_buffer (new_drawable, FALSE, NULL, new_buffer);
536               g_object_unref (new_buffer);
537             }
538         }
539     }
540 
541   return new_item;
542 }
543 
544 static void
gimp_channel_convert(GimpItem * item,GimpImage * dest_image,GType old_type)545 gimp_channel_convert (GimpItem  *item,
546                       GimpImage *dest_image,
547                       GType      old_type)
548 {
549   GimpChannel  *channel  = GIMP_CHANNEL (item);
550   GimpDrawable *drawable = GIMP_DRAWABLE (item);
551 
552   if (! gimp_drawable_is_gray (drawable))
553     {
554       gimp_drawable_convert_type (drawable, dest_image,
555                                   GIMP_GRAY,
556                                   gimp_image_get_precision (dest_image),
557                                   gimp_drawable_has_alpha (drawable),
558                                   NULL,
559                                   GEGL_DITHER_NONE, GEGL_DITHER_NONE,
560                                   FALSE, NULL);
561     }
562 
563   if (gimp_drawable_has_alpha (drawable))
564     {
565       GeglBuffer *new_buffer;
566       const Babl *format;
567       GimpRGB     background;
568 
569       format = gimp_drawable_get_format_without_alpha (drawable);
570 
571       new_buffer =
572         gegl_buffer_new (GEGL_RECTANGLE (0, 0,
573                                          gimp_item_get_width (item),
574                                          gimp_item_get_height (item)),
575                          format);
576 
577       gimp_rgba_set (&background, 0.0, 0.0, 0.0, 0.0);
578 
579       gimp_gegl_apply_flatten (gimp_drawable_get_buffer (drawable),
580                                NULL, NULL,
581                                new_buffer, &background,
582                                GIMP_LAYER_COLOR_SPACE_RGB_LINEAR);
583 
584       gimp_drawable_set_buffer_full (drawable, FALSE, NULL,
585                                      new_buffer,
586                                      GEGL_RECTANGLE (
587                                        gimp_item_get_offset_x (item),
588                                        gimp_item_get_offset_y (item),
589                                        0, 0),
590                                      TRUE);
591       g_object_unref (new_buffer);
592     }
593 
594   if (G_TYPE_FROM_INSTANCE (channel) == GIMP_TYPE_CHANNEL)
595     {
596       gint width  = gimp_image_get_width  (dest_image);
597       gint height = gimp_image_get_height (dest_image);
598 
599       gimp_item_set_offset (item, 0, 0);
600 
601       if (gimp_item_get_width  (item) != width ||
602           gimp_item_get_height (item) != height)
603         {
604           gimp_item_resize (item, gimp_get_user_context (dest_image->gimp),
605                             GIMP_FILL_TRANSPARENT,
606                             width, height, 0, 0);
607         }
608     }
609 
610   GIMP_ITEM_CLASS (parent_class)->convert (item, dest_image, old_type);
611 }
612 
613 static void
gimp_channel_translate(GimpItem * item,gdouble off_x,gdouble off_y,gboolean push_undo)614 gimp_channel_translate (GimpItem *item,
615                         gdouble   off_x,
616                         gdouble   off_y,
617                         gboolean  push_undo)
618 {
619   GimpChannel *channel = GIMP_CHANNEL (item);
620   gint         x, y, width, height;
621 
622   gimp_item_bounds (GIMP_ITEM (channel), &x, &y, &width, &height);
623 
624   /*  update the old area  */
625   gimp_drawable_update (GIMP_DRAWABLE (item), x, y, width, height);
626 
627   if (push_undo)
628     gimp_channel_push_undo (channel, NULL);
629 
630   if (gimp_rectangle_intersect (x + SIGNED_ROUND (off_x),
631                                 y + SIGNED_ROUND (off_y),
632                                 width, height,
633                                 0, 0,
634                                 gimp_item_get_width  (GIMP_ITEM (channel)),
635                                 gimp_item_get_height (GIMP_ITEM (channel)),
636                                 &x, &y, &width, &height))
637     {
638       /*  copy the portion of the mask we will keep to a temporary
639        *  buffer
640        */
641       GeglBuffer *tmp_buffer =
642         gegl_buffer_new (GEGL_RECTANGLE (0, 0, width, height),
643                          gimp_drawable_get_format (GIMP_DRAWABLE (channel)));
644 
645       gimp_gegl_buffer_copy (gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
646                              GEGL_RECTANGLE (x - SIGNED_ROUND (off_x),
647                                              y - SIGNED_ROUND (off_y),
648                                              width, height),
649                              GEGL_ABYSS_NONE,
650                              tmp_buffer,
651                              GEGL_RECTANGLE (0, 0, 0, 0));
652 
653       /*  clear the mask  */
654       gegl_buffer_clear (gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
655                          NULL);
656 
657       /*  copy the temp mask back to the mask  */
658       gimp_gegl_buffer_copy (tmp_buffer, NULL, GEGL_ABYSS_NONE,
659                              gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
660                              GEGL_RECTANGLE (x, y, 0, 0));
661 
662       /*  free the temporary mask  */
663       g_object_unref (tmp_buffer);
664 
665       channel->x1 = x;
666       channel->y1 = y;
667       channel->x2 = x + width;
668       channel->y2 = y + height;
669     }
670   else
671     {
672       /*  clear the mask  */
673       gegl_buffer_clear (gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
674                          NULL);
675 
676       channel->empty = TRUE;
677       channel->x1    = 0;
678       channel->y1    = 0;
679       channel->x2    = gimp_item_get_width  (GIMP_ITEM (channel));
680       channel->y2    = gimp_item_get_height (GIMP_ITEM (channel));
681     }
682 
683   /*  update the new area  */
684   gimp_drawable_update (GIMP_DRAWABLE (item),
685                         channel->x1, channel->y1,
686                         channel->x2 - channel->x1,
687                         channel->y2 - channel->y1);
688 }
689 
690 static void
gimp_channel_scale(GimpItem * item,gint new_width,gint new_height,gint new_offset_x,gint new_offset_y,GimpInterpolationType interpolation_type,GimpProgress * progress)691 gimp_channel_scale (GimpItem              *item,
692                     gint                   new_width,
693                     gint                   new_height,
694                     gint                   new_offset_x,
695                     gint                   new_offset_y,
696                     GimpInterpolationType  interpolation_type,
697                     GimpProgress          *progress)
698 {
699   GimpChannel *channel = GIMP_CHANNEL (item);
700 
701   if (G_TYPE_FROM_INSTANCE (item) == GIMP_TYPE_CHANNEL)
702     {
703       new_offset_x = 0;
704       new_offset_y = 0;
705     }
706 
707   /*  don't waste CPU cycles scaling an empty channel  */
708   if (channel->bounds_known && channel->empty)
709     {
710       GimpDrawable *drawable = GIMP_DRAWABLE (item);
711       GeglBuffer   *new_buffer;
712 
713       new_buffer =
714         gegl_buffer_new (GEGL_RECTANGLE (0, 0, new_width, new_height),
715                          gimp_drawable_get_format (drawable));
716 
717       gimp_drawable_set_buffer_full (drawable,
718                                      gimp_item_is_attached (item), NULL,
719                                      new_buffer,
720                                      GEGL_RECTANGLE (new_offset_x, new_offset_y,
721                                                      0,            0),
722                                      TRUE);
723       g_object_unref (new_buffer);
724 
725       gimp_channel_clear (GIMP_CHANNEL (item), NULL, FALSE);
726     }
727   else
728     {
729       GIMP_ITEM_CLASS (parent_class)->scale (item, new_width, new_height,
730                                              new_offset_x, new_offset_y,
731                                              interpolation_type, progress);
732     }
733 }
734 
735 static void
gimp_channel_resize(GimpItem * item,GimpContext * context,GimpFillType fill_type,gint new_width,gint new_height,gint offset_x,gint offset_y)736 gimp_channel_resize (GimpItem     *item,
737                      GimpContext  *context,
738                      GimpFillType  fill_type,
739                      gint          new_width,
740                      gint          new_height,
741                      gint          offset_x,
742                      gint          offset_y)
743 {
744   GIMP_ITEM_CLASS (parent_class)->resize (item, context, GIMP_FILL_TRANSPARENT,
745                                           new_width, new_height,
746                                           offset_x, offset_y);
747 
748   if (G_TYPE_FROM_INSTANCE (item) == GIMP_TYPE_CHANNEL)
749     {
750       gimp_item_set_offset (item, 0, 0);
751     }
752 }
753 
754 static GimpTransformResize
gimp_channel_get_clip(GimpItem * item,GimpTransformResize clip_result)755 gimp_channel_get_clip (GimpItem            *item,
756                        GimpTransformResize  clip_result)
757 {
758   return GIMP_TRANSFORM_RESIZE_CLIP;
759 }
760 
761 static gboolean
gimp_channel_fill(GimpItem * item,GimpDrawable * drawable,GimpFillOptions * fill_options,gboolean push_undo,GimpProgress * progress,GError ** error)762 gimp_channel_fill (GimpItem         *item,
763                    GimpDrawable     *drawable,
764                    GimpFillOptions  *fill_options,
765                    gboolean          push_undo,
766                    GimpProgress     *progress,
767                    GError          **error)
768 {
769   GimpChannel        *channel = GIMP_CHANNEL (item);
770   const GimpBoundSeg *segs_in;
771   const GimpBoundSeg *segs_out;
772   gint                n_segs_in;
773   gint                n_segs_out;
774   gint                offset_x, offset_y;
775 
776   if (! gimp_channel_boundary (channel, &segs_in, &segs_out,
777                                &n_segs_in, &n_segs_out,
778                                0, 0, 0, 0))
779     {
780       g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
781                            _("Cannot fill empty channel."));
782       return FALSE;
783     }
784 
785   gimp_item_get_offset (item, &offset_x, &offset_y);
786 
787   gimp_drawable_fill_boundary (drawable,
788                                fill_options,
789                                segs_in, n_segs_in,
790                                offset_x, offset_y,
791                                push_undo);
792 
793   return TRUE;
794 }
795 
796 static gboolean
gimp_channel_stroke(GimpItem * item,GimpDrawable * drawable,GimpStrokeOptions * stroke_options,gboolean push_undo,GimpProgress * progress,GError ** error)797 gimp_channel_stroke (GimpItem           *item,
798                      GimpDrawable       *drawable,
799                      GimpStrokeOptions  *stroke_options,
800                      gboolean            push_undo,
801                      GimpProgress       *progress,
802                      GError            **error)
803 {
804   GimpChannel        *channel = GIMP_CHANNEL (item);
805   const GimpBoundSeg *segs_in;
806   const GimpBoundSeg *segs_out;
807   gint                n_segs_in;
808   gint                n_segs_out;
809   gboolean            retval = FALSE;
810   gint                offset_x, offset_y;
811 
812   if (! gimp_channel_boundary (channel, &segs_in, &segs_out,
813                                &n_segs_in, &n_segs_out,
814                                0, 0, 0, 0))
815     {
816       g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
817                            _("Cannot stroke empty channel."));
818       return FALSE;
819     }
820 
821   gimp_item_get_offset (item, &offset_x, &offset_y);
822 
823   switch (gimp_stroke_options_get_method (stroke_options))
824     {
825     case GIMP_STROKE_LINE:
826       gimp_drawable_stroke_boundary (drawable,
827                                      stroke_options,
828                                      segs_in, n_segs_in,
829                                      offset_x, offset_y,
830                                      push_undo);
831       retval = TRUE;
832       break;
833 
834     case GIMP_STROKE_PAINT_METHOD:
835       {
836         GimpPaintInfo    *paint_info;
837         GimpPaintCore    *core;
838         GimpPaintOptions *paint_options;
839         gboolean          emulate_dynamics;
840 
841         paint_info = gimp_context_get_paint_info (GIMP_CONTEXT (stroke_options));
842 
843         core = g_object_new (paint_info->paint_type, NULL);
844 
845         paint_options = gimp_stroke_options_get_paint_options (stroke_options);
846         emulate_dynamics = gimp_stroke_options_get_emulate_dynamics (stroke_options);
847 
848         retval = gimp_paint_core_stroke_boundary (core, drawable,
849                                                   paint_options,
850                                                   emulate_dynamics,
851                                                   segs_in, n_segs_in,
852                                                   offset_x, offset_y,
853                                                   push_undo, error);
854 
855         g_object_unref (core);
856       }
857       break;
858 
859     default:
860       g_return_val_if_reached (FALSE);
861     }
862 
863   return retval;
864 }
865 
866 static void
gimp_channel_to_selection(GimpItem * item,GimpChannelOps op,gboolean antialias,gboolean feather,gdouble feather_radius_x,gdouble feather_radius_y)867 gimp_channel_to_selection (GimpItem       *item,
868                            GimpChannelOps  op,
869                            gboolean        antialias,
870                            gboolean        feather,
871                            gdouble         feather_radius_x,
872                            gdouble         feather_radius_y)
873 {
874   GimpChannel *channel = GIMP_CHANNEL (item);
875   GimpImage   *image   = gimp_item_get_image (item);
876   gint         off_x, off_y;
877 
878   gimp_item_get_offset (item, &off_x, &off_y);
879 
880   gimp_channel_select_channel (gimp_image_get_mask (image),
881                                GIMP_ITEM_GET_CLASS (item)->to_selection_desc,
882                                channel, off_x, off_y,
883                                op,
884                                feather, feather_radius_x, feather_radius_x);
885 }
886 
887 static void
gimp_channel_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)888 gimp_channel_convert_type (GimpDrawable     *drawable,
889                            GimpImage        *dest_image,
890                            const Babl       *new_format,
891                            GimpColorProfile *dest_profile,
892                            GeglDitherMethod  layer_dither_type,
893                            GeglDitherMethod  mask_dither_type,
894                            gboolean          push_undo,
895                            GimpProgress     *progress)
896 {
897   GeglBuffer *dest_buffer;
898 
899   dest_buffer =
900     gegl_buffer_new (GEGL_RECTANGLE (0, 0,
901                                      gimp_item_get_width  (GIMP_ITEM (drawable)),
902                                      gimp_item_get_height (GIMP_ITEM (drawable))),
903                      new_format);
904 
905   if (mask_dither_type == GEGL_DITHER_NONE)
906     {
907       gimp_gegl_buffer_copy (gimp_drawable_get_buffer (drawable), NULL,
908                              GEGL_ABYSS_NONE,
909                              dest_buffer, NULL);
910     }
911   else
912     {
913       gint bits;
914 
915       bits = (babl_format_get_bytes_per_pixel (new_format) * 8 /
916               babl_format_get_n_components (new_format));
917 
918       gimp_gegl_apply_dither (gimp_drawable_get_buffer (drawable),
919                               NULL, NULL,
920                               dest_buffer, 1 << bits, mask_dither_type);
921     }
922 
923   gimp_drawable_set_buffer (drawable, push_undo, NULL, dest_buffer);
924   g_object_unref (dest_buffer);
925 }
926 
927 static void
gimp_channel_invalidate_boundary(GimpDrawable * drawable)928 gimp_channel_invalidate_boundary (GimpDrawable *drawable)
929 {
930   GimpChannel *channel = GIMP_CHANNEL (drawable);
931 
932   channel->boundary_known = FALSE;
933   channel->bounds_known   = FALSE;
934 }
935 
936 static void
gimp_channel_get_active_components(GimpDrawable * drawable,gboolean * active)937 gimp_channel_get_active_components (GimpDrawable *drawable,
938                                     gboolean     *active)
939 {
940   /*  Make sure that the alpha channel is not valid.  */
941   active[GRAY]    = TRUE;
942   active[ALPHA_G] = FALSE;
943 }
944 
945 static void
gimp_channel_set_buffer(GimpDrawable * drawable,gboolean push_undo,const gchar * undo_desc,GeglBuffer * buffer,const GeglRectangle * bounds)946 gimp_channel_set_buffer (GimpDrawable        *drawable,
947                          gboolean             push_undo,
948                          const gchar         *undo_desc,
949                          GeglBuffer          *buffer,
950                          const GeglRectangle *bounds)
951 {
952   GimpChannel *channel    = GIMP_CHANNEL (drawable);
953   GeglBuffer  *old_buffer = gimp_drawable_get_buffer (drawable);
954 
955   if (old_buffer)
956     {
957       g_signal_handlers_disconnect_by_func (old_buffer,
958                                             gimp_channel_buffer_changed,
959                                             channel);
960     }
961 
962   GIMP_DRAWABLE_CLASS (parent_class)->set_buffer (drawable,
963                                                   push_undo, undo_desc,
964                                                   buffer, bounds);
965 
966   gegl_buffer_signal_connect (buffer, "changed",
967                               G_CALLBACK (gimp_channel_buffer_changed),
968                               channel);
969 
970   if (gimp_filter_peek_node (GIMP_FILTER (channel)))
971     {
972       const Babl *color_format;
973 
974       if (gimp_drawable_get_linear (drawable))
975         color_format = babl_format ("RGBA float");
976       else
977         color_format = babl_format ("R'G'B'A float");
978 
979       gegl_node_set (channel->color_node,
980                      "format", color_format,
981                      NULL);
982     }
983 }
984 
985 static gdouble
gimp_channel_get_opacity_at(GimpPickable * pickable,gint x,gint y)986 gimp_channel_get_opacity_at (GimpPickable *pickable,
987                              gint          x,
988                              gint          y)
989 {
990   GimpChannel *channel = GIMP_CHANNEL (pickable);
991   gdouble      value   = GIMP_OPACITY_TRANSPARENT;
992 
993   if (x >= 0 && x < gimp_item_get_width  (GIMP_ITEM (channel)) &&
994       y >= 0 && y < gimp_item_get_height (GIMP_ITEM (channel)))
995     {
996       if (! channel->bounds_known ||
997           (! channel->empty &&
998            x >= channel->x1 &&
999            x <  channel->x2 &&
1000            y >= channel->y1 &&
1001            y <  channel->y2))
1002         {
1003           gegl_buffer_sample (gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
1004                               x, y, NULL, &value, babl_format ("Y double"),
1005                               GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
1006         }
1007     }
1008 
1009   return value;
1010 }
1011 
1012 static gboolean
gimp_channel_real_boundary(GimpChannel * channel,const GimpBoundSeg ** segs_in,const GimpBoundSeg ** segs_out,gint * num_segs_in,gint * num_segs_out,gint x1,gint y1,gint x2,gint y2)1013 gimp_channel_real_boundary (GimpChannel         *channel,
1014                             const GimpBoundSeg **segs_in,
1015                             const GimpBoundSeg **segs_out,
1016                             gint                *num_segs_in,
1017                             gint                *num_segs_out,
1018                             gint                 x1,
1019                             gint                 y1,
1020                             gint                 x2,
1021                             gint                 y2)
1022 {
1023   if (! channel->boundary_known)
1024     {
1025       gint x3, y3, x4, y4;
1026 
1027       /* free the out of date boundary segments */
1028       g_free (channel->segs_in);
1029       g_free (channel->segs_out);
1030 
1031       if (gimp_item_bounds (GIMP_ITEM (channel), &x3, &y3, &x4, &y4))
1032         {
1033           GeglBuffer    *buffer;
1034           GeglRectangle  rect = { x3, y3, x4, y4 };
1035 
1036           x4 += x3;
1037           y4 += y3;
1038 
1039           buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (channel));
1040 
1041           channel->segs_out = gimp_boundary_find (buffer, &rect,
1042                                                   babl_format ("Y float"),
1043                                                   GIMP_BOUNDARY_IGNORE_BOUNDS,
1044                                                   x1, y1, x2, y2,
1045                                                   GIMP_BOUNDARY_HALF_WAY,
1046                                                   &channel->num_segs_out);
1047           x1 = MAX (x1, x3);
1048           y1 = MAX (y1, y3);
1049           x2 = MIN (x2, x4);
1050           y2 = MIN (y2, y4);
1051 
1052           if (x2 > x1 && y2 > y1)
1053             {
1054               channel->segs_in = gimp_boundary_find (buffer, NULL,
1055                                                      babl_format ("Y float"),
1056                                                      GIMP_BOUNDARY_WITHIN_BOUNDS,
1057                                                      x1, y1, x2, y2,
1058                                                      GIMP_BOUNDARY_HALF_WAY,
1059                                                      &channel->num_segs_in);
1060             }
1061           else
1062             {
1063               channel->segs_in     = NULL;
1064               channel->num_segs_in = 0;
1065             }
1066         }
1067       else
1068         {
1069           channel->segs_in      = NULL;
1070           channel->segs_out     = NULL;
1071           channel->num_segs_in  = 0;
1072           channel->num_segs_out = 0;
1073         }
1074 
1075       channel->boundary_known = TRUE;
1076     }
1077 
1078   *segs_in      = channel->segs_in;
1079   *segs_out     = channel->segs_out;
1080   *num_segs_in  = channel->num_segs_in;
1081   *num_segs_out = channel->num_segs_out;
1082 
1083   return (! channel->empty);
1084 }
1085 
1086 static gboolean
gimp_channel_real_is_empty(GimpChannel * channel)1087 gimp_channel_real_is_empty (GimpChannel *channel)
1088 {
1089   GeglBuffer *buffer;
1090 
1091   if (channel->bounds_known)
1092     return channel->empty;
1093 
1094   buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (channel));
1095 
1096   if (! gimp_gegl_mask_is_empty (buffer))
1097     return FALSE;
1098 
1099   /*  The mask is empty, meaning we can set the bounds as known  */
1100   g_clear_pointer (&channel->segs_in,  g_free);
1101   g_clear_pointer (&channel->segs_out, g_free);
1102 
1103   channel->empty          = TRUE;
1104   channel->num_segs_in    = 0;
1105   channel->num_segs_out   = 0;
1106   channel->bounds_known   = TRUE;
1107   channel->boundary_known = TRUE;
1108   channel->x1             = 0;
1109   channel->y1             = 0;
1110   channel->x2             = gimp_item_get_width  (GIMP_ITEM (channel));
1111   channel->y2             = gimp_item_get_height (GIMP_ITEM (channel));
1112 
1113   return TRUE;
1114 }
1115 
1116 static void
gimp_channel_real_feather(GimpChannel * channel,gdouble radius_x,gdouble radius_y,gboolean edge_lock,gboolean push_undo)1117 gimp_channel_real_feather (GimpChannel *channel,
1118                            gdouble      radius_x,
1119                            gdouble      radius_y,
1120                            gboolean     edge_lock,
1121                            gboolean     push_undo)
1122 {
1123   gint x1, y1, x2, y2;
1124 
1125   if (radius_x <= 0.0 && radius_y <= 0.0)
1126     return;
1127 
1128   if (! gimp_item_bounds (GIMP_ITEM (channel), &x1, &y1, &x2, &y2))
1129     return;
1130 
1131   x2 += x1;
1132   y2 += y1;
1133 
1134   if (gimp_channel_is_empty (channel))
1135     return;
1136 
1137   x1 = MAX (0, x1 - ceil (radius_x));
1138   y1 = MAX (0, y1 - ceil (radius_y));
1139 
1140   x2 = MIN (gimp_item_get_width  (GIMP_ITEM (channel)), x2 + ceil (radius_x));
1141   y2 = MIN (gimp_item_get_height (GIMP_ITEM (channel)), y2 + ceil (radius_y));
1142 
1143   if (push_undo)
1144     gimp_channel_push_undo (channel,
1145                             GIMP_CHANNEL_GET_CLASS (channel)->feather_desc);
1146 
1147   gimp_gegl_apply_feather (gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
1148                            NULL, NULL,
1149                            gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
1150                            GEGL_RECTANGLE (x1, y1, x2 - x1, y2 - y1),
1151                            radius_x,
1152                            radius_y,
1153                            edge_lock);
1154 
1155   gimp_drawable_update (GIMP_DRAWABLE (channel), 0, 0, -1, -1);
1156 }
1157 
1158 static void
gimp_channel_real_sharpen(GimpChannel * channel,gboolean push_undo)1159 gimp_channel_real_sharpen (GimpChannel *channel,
1160                            gboolean     push_undo)
1161 {
1162   GimpDrawable *drawable = GIMP_DRAWABLE (channel);
1163 
1164   if (push_undo)
1165     gimp_channel_push_undo (channel,
1166                             GIMP_CHANNEL_GET_CLASS (channel)->sharpen_desc);
1167 
1168   gimp_gegl_apply_threshold (gimp_drawable_get_buffer (drawable),
1169                              NULL, NULL,
1170                              gimp_drawable_get_buffer (drawable),
1171                              0.5);
1172 
1173   gimp_drawable_update (GIMP_DRAWABLE (channel), 0, 0, -1, -1);
1174 }
1175 
1176 static void
gimp_channel_real_clear(GimpChannel * channel,const gchar * undo_desc,gboolean push_undo)1177 gimp_channel_real_clear (GimpChannel *channel,
1178                          const gchar *undo_desc,
1179                          gboolean     push_undo)
1180 {
1181   GeglBuffer    *buffer;
1182   GeglRectangle  rect;
1183   GeglRectangle  aligned_rect;
1184 
1185   if (channel->bounds_known && channel->empty)
1186     return;
1187 
1188   if (push_undo)
1189     {
1190       if (! undo_desc)
1191         undo_desc = GIMP_CHANNEL_GET_CLASS (channel)->clear_desc;
1192 
1193       gimp_channel_push_undo (channel, undo_desc);
1194     }
1195 
1196   buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (channel));
1197 
1198   if (channel->bounds_known)
1199     {
1200       rect.x      = channel->x1;
1201       rect.y      = channel->y1;
1202       rect.width  = channel->x2 - channel->x1;
1203       rect.height = channel->y2 - channel->y1;
1204     }
1205   else
1206     {
1207       rect.x      = 0;
1208       rect.y      = 0;
1209       rect.width  = gimp_item_get_width  (GIMP_ITEM (channel));
1210       rect.height = gimp_item_get_height (GIMP_ITEM (channel));
1211     }
1212 
1213   gegl_rectangle_align_to_buffer (&aligned_rect, &rect, buffer,
1214                                   GEGL_RECTANGLE_ALIGNMENT_SUPERSET);
1215 
1216   gegl_buffer_clear (buffer, &aligned_rect);
1217 
1218   /*  we know the bounds  */
1219   channel->bounds_known = TRUE;
1220   channel->empty        = TRUE;
1221   channel->x1           = 0;
1222   channel->y1           = 0;
1223   channel->x2           = gimp_item_get_width  (GIMP_ITEM (channel));
1224   channel->y2           = gimp_item_get_height (GIMP_ITEM (channel));
1225 
1226   gimp_drawable_update (GIMP_DRAWABLE (channel),
1227                         rect.x, rect.y, rect.width, rect.height);
1228 }
1229 
1230 static void
gimp_channel_real_all(GimpChannel * channel,gboolean push_undo)1231 gimp_channel_real_all (GimpChannel *channel,
1232                        gboolean     push_undo)
1233 {
1234   GeglColor *color;
1235 
1236   if (push_undo)
1237     gimp_channel_push_undo (channel,
1238                             GIMP_CHANNEL_GET_CLASS (channel)->all_desc);
1239 
1240   /*  clear the channel  */
1241   color = gegl_color_new ("#fff");
1242   gegl_buffer_set_color (gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
1243                          NULL, color);
1244   g_object_unref (color);
1245 
1246   /*  we know the bounds  */
1247   channel->bounds_known = TRUE;
1248   channel->empty        = FALSE;
1249   channel->x1           = 0;
1250   channel->y1           = 0;
1251   channel->x2           = gimp_item_get_width  (GIMP_ITEM (channel));
1252   channel->y2           = gimp_item_get_height (GIMP_ITEM (channel));
1253 
1254   gimp_drawable_update (GIMP_DRAWABLE (channel), 0, 0, -1, -1);
1255 }
1256 
1257 static void
gimp_channel_real_invert(GimpChannel * channel,gboolean push_undo)1258 gimp_channel_real_invert (GimpChannel *channel,
1259                           gboolean     push_undo)
1260 {
1261   GimpDrawable *drawable = GIMP_DRAWABLE (channel);
1262 
1263   if (push_undo)
1264     gimp_channel_push_undo (channel,
1265                             GIMP_CHANNEL_GET_CLASS (channel)->invert_desc);
1266 
1267   if (channel->bounds_known && channel->empty)
1268     {
1269       gimp_channel_all (channel, FALSE);
1270     }
1271   else
1272     {
1273       gimp_gegl_apply_invert_linear (gimp_drawable_get_buffer (drawable),
1274                                      NULL, NULL,
1275                                      gimp_drawable_get_buffer (drawable));
1276 
1277       gimp_drawable_update (GIMP_DRAWABLE (channel), 0, 0, -1, -1);
1278     }
1279 }
1280 
1281 static void
gimp_channel_real_border(GimpChannel * channel,gint radius_x,gint radius_y,GimpChannelBorderStyle style,gboolean edge_lock,gboolean push_undo)1282 gimp_channel_real_border (GimpChannel            *channel,
1283                           gint                    radius_x,
1284                           gint                    radius_y,
1285                           GimpChannelBorderStyle  style,
1286                           gboolean                edge_lock,
1287                           gboolean                push_undo)
1288 {
1289   gint x1, y1, x2, y2;
1290 
1291   if (radius_x == 0 && radius_y == 0)
1292     {
1293       /* The relevant GEGL operations require radius_x and radius_y to be > 0.
1294        * When both are 0 (currently can only be achieved by the user through
1295        * PDB), the effect should be to clear the channel.
1296        */
1297       gimp_channel_clear (channel,
1298                           GIMP_CHANNEL_GET_CLASS (channel)->border_desc,
1299                           push_undo);
1300       return;
1301     }
1302   else if (radius_x <= 0 || radius_y <= 0)
1303     {
1304       /* FIXME: Implement the case where only one of radius_x and radius_y is 0.
1305        * Currently, should never happen.
1306        */
1307       g_return_if_reached();
1308     }
1309 
1310   if (! gimp_item_bounds (GIMP_ITEM (channel), &x1, &y1, &x2, &y2))
1311     return;
1312 
1313   x2 += x1;
1314   y2 += y1;
1315 
1316   if (gimp_channel_is_empty (channel))
1317     return;
1318 
1319   if (x1 - radius_x < 0)
1320     x1 = 0;
1321   else
1322     x1 -= radius_x;
1323 
1324   if (x2 + radius_x > gimp_item_get_width (GIMP_ITEM (channel)))
1325     x2 = gimp_item_get_width (GIMP_ITEM (channel));
1326   else
1327     x2 += radius_x;
1328 
1329   if (y1 - radius_y < 0)
1330     y1 = 0;
1331   else
1332     y1 -= radius_y;
1333 
1334   if (y2 + radius_y > gimp_item_get_height (GIMP_ITEM (channel)))
1335     y2 = gimp_item_get_height (GIMP_ITEM (channel));
1336   else
1337     y2 += radius_y;
1338 
1339   if (push_undo)
1340     gimp_channel_push_undo (channel,
1341                             GIMP_CHANNEL_GET_CLASS (channel)->border_desc);
1342 
1343   gimp_gegl_apply_border (gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
1344                           NULL, NULL,
1345                           gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
1346                           GEGL_RECTANGLE (x1, y1, x2 - x1, y2 - y1),
1347                           radius_x, radius_y, style, edge_lock);
1348 
1349   gimp_drawable_update (GIMP_DRAWABLE (channel), 0, 0, -1, -1);
1350 }
1351 
1352 static void
gimp_channel_real_grow(GimpChannel * channel,gint radius_x,gint radius_y,gboolean push_undo)1353 gimp_channel_real_grow (GimpChannel *channel,
1354                         gint         radius_x,
1355                         gint         radius_y,
1356                         gboolean     push_undo)
1357 {
1358   gint x1, y1, x2, y2;
1359 
1360   if (radius_x == 0 && radius_y == 0)
1361     return;
1362 
1363   if (radius_x <= 0 && radius_y <= 0)
1364     {
1365       gimp_channel_shrink (channel, -radius_x, -radius_y, FALSE, push_undo);
1366       return;
1367     }
1368 
1369   if (radius_x < 0 || radius_y < 0)
1370     return;
1371 
1372   if (! gimp_item_bounds (GIMP_ITEM (channel), &x1, &y1, &x2, &y2))
1373     return;
1374 
1375   x2 += x1;
1376   y2 += y1;
1377 
1378   if (gimp_channel_is_empty (channel))
1379     return;
1380 
1381   if (x1 - radius_x > 0)
1382     x1 = x1 - radius_x;
1383   else
1384     x1 = 0;
1385 
1386   if (y1 - radius_y > 0)
1387     y1 = y1 - radius_y;
1388   else
1389     y1 = 0;
1390 
1391   if (x2 + radius_x < gimp_item_get_width (GIMP_ITEM (channel)))
1392     x2 = x2 + radius_x;
1393   else
1394     x2 = gimp_item_get_width (GIMP_ITEM (channel));
1395 
1396   if (y2 + radius_y < gimp_item_get_height (GIMP_ITEM (channel)))
1397     y2 = y2 + radius_y;
1398   else
1399     y2 = gimp_item_get_height (GIMP_ITEM (channel));
1400 
1401   if (push_undo)
1402     gimp_channel_push_undo (channel,
1403                             GIMP_CHANNEL_GET_CLASS (channel)->grow_desc);
1404 
1405   gimp_gegl_apply_grow (gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
1406                         NULL, NULL,
1407                         gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
1408                         GEGL_RECTANGLE (x1, y1, x2 - x1, y2 - y1),
1409                         radius_x, radius_y);
1410 
1411   gimp_drawable_update (GIMP_DRAWABLE (channel), 0, 0, -1, -1);
1412 }
1413 
1414 static void
gimp_channel_real_shrink(GimpChannel * channel,gint radius_x,gint radius_y,gboolean edge_lock,gboolean push_undo)1415 gimp_channel_real_shrink (GimpChannel *channel,
1416                           gint         radius_x,
1417                           gint         radius_y,
1418                           gboolean     edge_lock,
1419                           gboolean     push_undo)
1420 {
1421   gint x1, y1, x2, y2;
1422 
1423   if (radius_x == 0 && radius_y == 0)
1424     return;
1425 
1426   if (radius_x <= 0 && radius_y <= 0)
1427     {
1428       gimp_channel_grow (channel, -radius_x, -radius_y, push_undo);
1429       return;
1430     }
1431 
1432   if (radius_x < 0 || radius_y < 0)
1433     return;
1434 
1435   if (! gimp_item_bounds (GIMP_ITEM (channel), &x1, &y1, &x2, &y2))
1436     return;
1437 
1438   x2 += x1;
1439   y2 += y1;
1440 
1441   if (gimp_channel_is_empty (channel))
1442     return;
1443 
1444   if (x1 > 0)
1445     x1--;
1446   if (y1 > 0)
1447     y1--;
1448   if (x2 < gimp_item_get_width (GIMP_ITEM (channel)))
1449     x2++;
1450   if (y2 < gimp_item_get_height (GIMP_ITEM (channel)))
1451     y2++;
1452 
1453   if (push_undo)
1454     gimp_channel_push_undo (channel,
1455                             GIMP_CHANNEL_GET_CLASS (channel)->shrink_desc);
1456 
1457   gimp_gegl_apply_shrink (gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
1458                           NULL, NULL,
1459                           gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
1460                           GEGL_RECTANGLE (x1, y1, x2 - x1, y2 - y1),
1461                           radius_x, radius_y, edge_lock);
1462 
1463   gimp_drawable_update (GIMP_DRAWABLE (channel), 0, 0, -1, -1);
1464 }
1465 
1466 static void
gimp_channel_real_flood(GimpChannel * channel,gboolean push_undo)1467 gimp_channel_real_flood (GimpChannel *channel,
1468                          gboolean     push_undo)
1469 {
1470   gint x, y, width, height;
1471 
1472   if (! gimp_item_bounds (GIMP_ITEM (channel), &x, &y, &width, &height))
1473     return;
1474 
1475   if (gimp_channel_is_empty (channel))
1476     return;
1477 
1478   if (push_undo)
1479     gimp_channel_push_undo (channel,
1480                             GIMP_CHANNEL_GET_CLASS (channel)->flood_desc);
1481 
1482   gimp_gegl_apply_flood (gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
1483                          NULL, NULL,
1484                          gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
1485                          GEGL_RECTANGLE (x, y, width, height));
1486 
1487   gimp_drawable_update (GIMP_DRAWABLE (channel), x, y, width, height);
1488 }
1489 
1490 static void
gimp_channel_buffer_changed(GeglBuffer * buffer,const GeglRectangle * rect,GimpChannel * channel)1491 gimp_channel_buffer_changed (GeglBuffer          *buffer,
1492                              const GeglRectangle *rect,
1493                              GimpChannel         *channel)
1494 {
1495   gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (channel));
1496 }
1497 
1498 
1499 /*  public functions  */
1500 
1501 GimpChannel *
gimp_channel_new(GimpImage * image,gint width,gint height,const gchar * name,const GimpRGB * color)1502 gimp_channel_new (GimpImage     *image,
1503                   gint           width,
1504                   gint           height,
1505                   const gchar   *name,
1506                   const GimpRGB *color)
1507 {
1508   GimpChannel *channel;
1509 
1510   g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
1511 
1512   channel =
1513     GIMP_CHANNEL (gimp_drawable_new (GIMP_TYPE_CHANNEL,
1514                                      image, name,
1515                                      0, 0, width, height,
1516                                      gimp_image_get_channel_format (image)));
1517 
1518   if (color)
1519     channel->color = *color;
1520 
1521   channel->show_masked = TRUE;
1522 
1523   /*  selection mask variables  */
1524   channel->x2          = width;
1525   channel->y2          = height;
1526 
1527   return channel;
1528 }
1529 
1530 GimpChannel *
gimp_channel_new_from_buffer(GimpImage * image,GeglBuffer * buffer,const gchar * name,const GimpRGB * color)1531 gimp_channel_new_from_buffer (GimpImage     *image,
1532                               GeglBuffer    *buffer,
1533                               const gchar   *name,
1534                               const GimpRGB *color)
1535 {
1536   GimpChannel *channel;
1537   GeglBuffer  *dest;
1538 
1539   g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
1540   g_return_val_if_fail (GEGL_IS_BUFFER (buffer), NULL);
1541 
1542   channel = gimp_channel_new (image,
1543                               gegl_buffer_get_width  (buffer),
1544                               gegl_buffer_get_height (buffer),
1545                               name, color);
1546 
1547   dest = gimp_drawable_get_buffer (GIMP_DRAWABLE (channel));
1548   gimp_gegl_buffer_copy (buffer, NULL, GEGL_ABYSS_NONE, dest, NULL);
1549 
1550   return channel;
1551 }
1552 
1553 GimpChannel *
gimp_channel_new_from_alpha(GimpImage * image,GimpDrawable * drawable,const gchar * name,const GimpRGB * color)1554 gimp_channel_new_from_alpha (GimpImage     *image,
1555                              GimpDrawable  *drawable,
1556                              const gchar   *name,
1557                              const GimpRGB *color)
1558 {
1559   GimpChannel *channel;
1560   GeglBuffer  *dest_buffer;
1561   gint         width;
1562   gint         height;
1563 
1564   g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
1565   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
1566   g_return_val_if_fail (gimp_drawable_has_alpha (drawable), NULL);
1567 
1568   width  = gimp_item_get_width  (GIMP_ITEM (drawable));
1569   height = gimp_item_get_height (GIMP_ITEM (drawable));
1570 
1571   channel = gimp_channel_new (image, width, height, name, color);
1572 
1573   gimp_channel_clear (channel, NULL, FALSE);
1574 
1575   dest_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (channel));
1576 
1577   gegl_buffer_set_format (dest_buffer,
1578                           gimp_drawable_get_component_format (drawable,
1579                                                               GIMP_CHANNEL_ALPHA));
1580   gimp_gegl_buffer_copy (gimp_drawable_get_buffer (drawable), NULL,
1581                          GEGL_ABYSS_NONE,
1582                          dest_buffer, NULL);
1583   gegl_buffer_set_format (dest_buffer, NULL);
1584 
1585   return channel;
1586 }
1587 
1588 GimpChannel *
gimp_channel_new_from_component(GimpImage * image,GimpChannelType type,const gchar * name,const GimpRGB * color)1589 gimp_channel_new_from_component (GimpImage       *image,
1590                                  GimpChannelType  type,
1591                                  const gchar     *name,
1592                                  const GimpRGB   *color)
1593 {
1594   GimpChannel *channel;
1595   GeglBuffer  *src_buffer;
1596   GeglBuffer  *dest_buffer;
1597   gint         width;
1598   gint         height;
1599   const Babl  *format;
1600 
1601   g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
1602 
1603   format = gimp_image_get_component_format (image, type);
1604 
1605   g_return_val_if_fail (format != NULL, NULL);
1606 
1607   gimp_pickable_flush (GIMP_PICKABLE (image));
1608 
1609   src_buffer = gimp_pickable_get_buffer (GIMP_PICKABLE (image));
1610   width  = gegl_buffer_get_width  (src_buffer);
1611   height = gegl_buffer_get_height (src_buffer);
1612 
1613   channel = gimp_channel_new (image, width, height, name, color);
1614 
1615   dest_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (channel));
1616 
1617   gegl_buffer_set_format (dest_buffer, format);
1618   gimp_gegl_buffer_copy (src_buffer, NULL, GEGL_ABYSS_NONE, dest_buffer, NULL);
1619   gegl_buffer_set_format (dest_buffer, NULL);
1620 
1621   return channel;
1622 }
1623 
1624 GimpChannel *
gimp_channel_get_parent(GimpChannel * channel)1625 gimp_channel_get_parent (GimpChannel *channel)
1626 {
1627   g_return_val_if_fail (GIMP_IS_CHANNEL (channel), NULL);
1628 
1629   return GIMP_CHANNEL (gimp_viewable_get_parent (GIMP_VIEWABLE (channel)));
1630 }
1631 
1632 void
gimp_channel_set_color(GimpChannel * channel,const GimpRGB * color,gboolean push_undo)1633 gimp_channel_set_color (GimpChannel   *channel,
1634                         const GimpRGB *color,
1635                         gboolean       push_undo)
1636 {
1637   g_return_if_fail (GIMP_IS_CHANNEL (channel));
1638   g_return_if_fail (color != NULL);
1639 
1640   if (gimp_rgba_distance (&channel->color, color) > RGBA_EPSILON)
1641     {
1642       if (push_undo && gimp_item_is_attached (GIMP_ITEM (channel)))
1643         {
1644           GimpImage *image = gimp_item_get_image (GIMP_ITEM (channel));
1645 
1646           gimp_image_undo_push_channel_color (image, C_("undo-type", "Set Channel Color"),
1647                                               channel);
1648         }
1649 
1650       channel->color = *color;
1651 
1652       if (gimp_filter_peek_node (GIMP_FILTER (channel)))
1653         {
1654           gimp_gegl_node_set_color (channel->color_node,
1655                                     &channel->color);
1656         }
1657 
1658       gimp_drawable_update (GIMP_DRAWABLE (channel), 0, 0, -1, -1);
1659 
1660       g_signal_emit (channel, channel_signals[COLOR_CHANGED], 0);
1661     }
1662 }
1663 
1664 void
gimp_channel_get_color(GimpChannel * channel,GimpRGB * color)1665 gimp_channel_get_color (GimpChannel *channel,
1666                         GimpRGB     *color)
1667 {
1668   g_return_if_fail (GIMP_IS_CHANNEL (channel));
1669   g_return_if_fail (color != NULL);
1670 
1671   *color = channel->color;
1672 }
1673 
1674 gdouble
gimp_channel_get_opacity(GimpChannel * channel)1675 gimp_channel_get_opacity (GimpChannel *channel)
1676 {
1677   g_return_val_if_fail (GIMP_IS_CHANNEL (channel), GIMP_OPACITY_TRANSPARENT);
1678 
1679   return channel->color.a;
1680 }
1681 
1682 void
gimp_channel_set_opacity(GimpChannel * channel,gdouble opacity,gboolean push_undo)1683 gimp_channel_set_opacity (GimpChannel *channel,
1684                           gdouble      opacity,
1685                           gboolean     push_undo)
1686 {
1687   g_return_if_fail (GIMP_IS_CHANNEL (channel));
1688 
1689   opacity = CLAMP (opacity, GIMP_OPACITY_TRANSPARENT, GIMP_OPACITY_OPAQUE);
1690 
1691   if (channel->color.a != opacity)
1692     {
1693       if (push_undo && gimp_item_is_attached (GIMP_ITEM (channel)))
1694         {
1695           GimpImage *image = gimp_item_get_image (GIMP_ITEM (channel));
1696 
1697           gimp_image_undo_push_channel_color (image, C_("undo-type", "Set Channel Opacity"),
1698                                               channel);
1699         }
1700 
1701       channel->color.a = opacity;
1702 
1703       if (gimp_filter_peek_node (GIMP_FILTER (channel)))
1704         {
1705           gimp_gegl_node_set_color (channel->color_node,
1706                                     &channel->color);
1707         }
1708 
1709       gimp_drawable_update (GIMP_DRAWABLE (channel), 0, 0, -1, -1);
1710 
1711       g_signal_emit (channel, channel_signals[COLOR_CHANGED], 0);
1712     }
1713 }
1714 
1715 gboolean
gimp_channel_get_show_masked(GimpChannel * channel)1716 gimp_channel_get_show_masked (GimpChannel *channel)
1717 {
1718   g_return_val_if_fail (GIMP_IS_CHANNEL (channel), FALSE);
1719 
1720   return channel->show_masked;
1721 }
1722 
1723 void
gimp_channel_set_show_masked(GimpChannel * channel,gboolean show_masked)1724 gimp_channel_set_show_masked (GimpChannel *channel,
1725                               gboolean     show_masked)
1726 {
1727   g_return_if_fail (GIMP_IS_CHANNEL (channel));
1728 
1729   if (show_masked != channel->show_masked)
1730     {
1731       channel->show_masked = show_masked ? TRUE : FALSE;
1732 
1733       if (channel->invert_node)
1734         {
1735           GeglNode *source;
1736 
1737           source = gimp_drawable_get_source_node (GIMP_DRAWABLE (channel));
1738 
1739           if (channel->show_masked)
1740             {
1741               gegl_node_connect_to (source,               "output",
1742                                     channel->invert_node, "input");
1743               gegl_node_connect_to (channel->invert_node, "output",
1744                                     channel->mask_node,   "aux");
1745             }
1746           else
1747             {
1748               gegl_node_disconnect (channel->invert_node, "input");
1749 
1750               gegl_node_connect_to (source,             "output",
1751                                     channel->mask_node, "aux");
1752             }
1753         }
1754 
1755       gimp_drawable_update (GIMP_DRAWABLE (channel), 0, 0, -1, -1);
1756     }
1757 }
1758 
1759 void
gimp_channel_push_undo(GimpChannel * channel,const gchar * undo_desc)1760 gimp_channel_push_undo (GimpChannel *channel,
1761                         const gchar *undo_desc)
1762 {
1763   g_return_if_fail (GIMP_IS_CHANNEL (channel));
1764   g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel)));
1765 
1766   gimp_image_undo_push_mask (gimp_item_get_image (GIMP_ITEM (channel)),
1767                              undo_desc, channel);
1768 }
1769 
1770 
1771 /******************************/
1772 /*  selection mask functions  */
1773 /******************************/
1774 
1775 GimpChannel *
gimp_channel_new_mask(GimpImage * image,gint width,gint height)1776 gimp_channel_new_mask (GimpImage *image,
1777                        gint       width,
1778                        gint       height)
1779 {
1780   GimpChannel *channel;
1781 
1782   g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
1783 
1784   channel =
1785     GIMP_CHANNEL (gimp_drawable_new (GIMP_TYPE_CHANNEL,
1786                                      image, _("Selection Mask"),
1787                                      0, 0, width, height,
1788                                      gimp_image_get_mask_format (image)));
1789 
1790   channel->show_masked = TRUE;
1791   channel->x2          = width;
1792   channel->y2          = height;
1793 
1794   gegl_buffer_clear (gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
1795                      NULL);
1796 
1797   return channel;
1798 }
1799 
1800 gboolean
gimp_channel_boundary(GimpChannel * channel,const GimpBoundSeg ** segs_in,const GimpBoundSeg ** segs_out,gint * num_segs_in,gint * num_segs_out,gint x1,gint y1,gint x2,gint y2)1801 gimp_channel_boundary (GimpChannel         *channel,
1802                        const GimpBoundSeg **segs_in,
1803                        const GimpBoundSeg **segs_out,
1804                        gint                *num_segs_in,
1805                        gint                *num_segs_out,
1806                        gint                 x1,
1807                        gint                 y1,
1808                        gint                 x2,
1809                        gint                 y2)
1810 {
1811   g_return_val_if_fail (GIMP_IS_CHANNEL (channel), FALSE);
1812   g_return_val_if_fail (segs_in != NULL, FALSE);
1813   g_return_val_if_fail (segs_out != NULL, FALSE);
1814   g_return_val_if_fail (num_segs_in != NULL, FALSE);
1815   g_return_val_if_fail (num_segs_out != NULL, FALSE);
1816 
1817   return GIMP_CHANNEL_GET_CLASS (channel)->boundary (channel,
1818                                                      segs_in, segs_out,
1819                                                      num_segs_in, num_segs_out,
1820                                                      x1, y1,
1821                                                      x2, y2);
1822 }
1823 
1824 gboolean
gimp_channel_is_empty(GimpChannel * channel)1825 gimp_channel_is_empty (GimpChannel *channel)
1826 {
1827   g_return_val_if_fail (GIMP_IS_CHANNEL (channel), FALSE);
1828 
1829   return GIMP_CHANNEL_GET_CLASS (channel)->is_empty (channel);
1830 }
1831 
1832 void
gimp_channel_feather(GimpChannel * channel,gdouble radius_x,gdouble radius_y,gboolean edge_lock,gboolean push_undo)1833 gimp_channel_feather (GimpChannel *channel,
1834                       gdouble      radius_x,
1835                       gdouble      radius_y,
1836                       gboolean     edge_lock,
1837                       gboolean     push_undo)
1838 {
1839   g_return_if_fail (GIMP_IS_CHANNEL (channel));
1840 
1841   if (! gimp_item_is_attached (GIMP_ITEM (channel)))
1842     push_undo = FALSE;
1843 
1844   GIMP_CHANNEL_GET_CLASS (channel)->feather (channel, radius_x, radius_y,
1845                                              edge_lock, push_undo);
1846 }
1847 
1848 void
gimp_channel_sharpen(GimpChannel * channel,gboolean push_undo)1849 gimp_channel_sharpen (GimpChannel *channel,
1850                       gboolean     push_undo)
1851 {
1852   g_return_if_fail (GIMP_IS_CHANNEL (channel));
1853 
1854   if (! gimp_item_is_attached (GIMP_ITEM (channel)))
1855     push_undo = FALSE;
1856 
1857   GIMP_CHANNEL_GET_CLASS (channel)->sharpen (channel, push_undo);
1858 }
1859 
1860 void
gimp_channel_clear(GimpChannel * channel,const gchar * undo_desc,gboolean push_undo)1861 gimp_channel_clear (GimpChannel *channel,
1862                     const gchar *undo_desc,
1863                     gboolean     push_undo)
1864 {
1865   g_return_if_fail (GIMP_IS_CHANNEL (channel));
1866 
1867   if (! gimp_item_is_attached (GIMP_ITEM (channel)))
1868     push_undo = FALSE;
1869 
1870   GIMP_CHANNEL_GET_CLASS (channel)->clear (channel, undo_desc, push_undo);
1871 }
1872 
1873 void
gimp_channel_all(GimpChannel * channel,gboolean push_undo)1874 gimp_channel_all (GimpChannel *channel,
1875                   gboolean     push_undo)
1876 {
1877   g_return_if_fail (GIMP_IS_CHANNEL (channel));
1878 
1879   if (! gimp_item_is_attached (GIMP_ITEM (channel)))
1880     push_undo = FALSE;
1881 
1882   GIMP_CHANNEL_GET_CLASS (channel)->all (channel, push_undo);
1883 }
1884 
1885 void
gimp_channel_invert(GimpChannel * channel,gboolean push_undo)1886 gimp_channel_invert (GimpChannel *channel,
1887                      gboolean     push_undo)
1888 {
1889   g_return_if_fail (GIMP_IS_CHANNEL (channel));
1890 
1891   if (! gimp_item_is_attached (GIMP_ITEM (channel)))
1892     push_undo = FALSE;
1893 
1894   GIMP_CHANNEL_GET_CLASS (channel)->invert (channel, push_undo);
1895 }
1896 
1897 void
gimp_channel_border(GimpChannel * channel,gint radius_x,gint radius_y,GimpChannelBorderStyle style,gboolean edge_lock,gboolean push_undo)1898 gimp_channel_border (GimpChannel            *channel,
1899                      gint                    radius_x,
1900                      gint                    radius_y,
1901                      GimpChannelBorderStyle  style,
1902                      gboolean                edge_lock,
1903                      gboolean                push_undo)
1904 {
1905   g_return_if_fail (GIMP_IS_CHANNEL (channel));
1906 
1907   if (! gimp_item_is_attached (GIMP_ITEM (channel)))
1908     push_undo = FALSE;
1909 
1910   GIMP_CHANNEL_GET_CLASS (channel)->border (channel,
1911                                             radius_x, radius_y, style, edge_lock,
1912                                             push_undo);
1913 }
1914 
1915 void
gimp_channel_grow(GimpChannel * channel,gint radius_x,gint radius_y,gboolean push_undo)1916 gimp_channel_grow (GimpChannel *channel,
1917                    gint         radius_x,
1918                    gint         radius_y,
1919                    gboolean     push_undo)
1920 {
1921   g_return_if_fail (GIMP_IS_CHANNEL (channel));
1922 
1923   if (! gimp_item_is_attached (GIMP_ITEM (channel)))
1924     push_undo = FALSE;
1925 
1926   GIMP_CHANNEL_GET_CLASS (channel)->grow (channel, radius_x, radius_y,
1927                                           push_undo);
1928 }
1929 
1930 void
gimp_channel_shrink(GimpChannel * channel,gint radius_x,gint radius_y,gboolean edge_lock,gboolean push_undo)1931 gimp_channel_shrink (GimpChannel  *channel,
1932                      gint          radius_x,
1933                      gint          radius_y,
1934                      gboolean      edge_lock,
1935                      gboolean      push_undo)
1936 {
1937   g_return_if_fail (GIMP_IS_CHANNEL (channel));
1938 
1939   if (! gimp_item_is_attached (GIMP_ITEM (channel)))
1940     push_undo = FALSE;
1941 
1942   GIMP_CHANNEL_GET_CLASS (channel)->shrink (channel, radius_x, radius_y,
1943                                             edge_lock, push_undo);
1944 }
1945 
1946 void
gimp_channel_flood(GimpChannel * channel,gboolean push_undo)1947 gimp_channel_flood (GimpChannel *channel,
1948                     gboolean     push_undo)
1949 {
1950   g_return_if_fail (GIMP_IS_CHANNEL (channel));
1951 
1952   if (! gimp_item_is_attached (GIMP_ITEM (channel)))
1953     push_undo = FALSE;
1954 
1955   GIMP_CHANNEL_GET_CLASS (channel)->flood (channel, push_undo);
1956 }
1957