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 <gegl.h>
22 #include <gdk-pixbuf/gdk-pixbuf.h>
23 
24 #include "libgimpbase/gimpbase.h"
25 #include "libgimpcolor/gimpcolor.h"
26 #include "libgimpmath/gimpmath.h"
27 
28 #include "core-types.h"
29 
30 #include "gegl/gimp-babl.h"
31 #include "gegl/gimp-gegl-apply-operation.h"
32 #include "gegl/gimp-gegl-loops.h"
33 #include "gegl/gimp-gegl-utils.h"
34 
35 #include "gimp-memsize.h"
36 #include "gimp-utils.h"
37 #include "gimpchannel.h"
38 #include "gimpcontext.h"
39 #include "gimpdrawable-combine.h"
40 #include "gimpdrawable-fill.h"
41 #include "gimpdrawable-floating-selection.h"
42 #include "gimpdrawable-preview.h"
43 #include "gimpdrawable-private.h"
44 #include "gimpdrawable-shadow.h"
45 #include "gimpdrawable-transform.h"
46 #include "gimpfilterstack.h"
47 #include "gimpimage.h"
48 #include "gimpimage-colormap.h"
49 #include "gimpimage-undo-push.h"
50 #include "gimpmarshal.h"
51 #include "gimppickable.h"
52 #include "gimpprogress.h"
53 
54 #include "gimp-log.h"
55 
56 #include "gimp-intl.h"
57 
58 
59 #define PAINT_UPDATE_CHUNK_WIDTH  32
60 #define PAINT_UPDATE_CHUNK_HEIGHT 32
61 
62 
63 enum
64 {
65   UPDATE,
66   FORMAT_CHANGED,
67   ALPHA_CHANGED,
68   BOUNDING_BOX_CHANGED,
69   LAST_SIGNAL
70 };
71 
72 enum
73 {
74   PROP_0,
75   PROP_BUFFER
76 };
77 
78 
79 /*  local function prototypes  */
80 
81 static void       gimp_color_managed_iface_init    (GimpColorManagedInterface *iface);
82 static void       gimp_pickable_iface_init         (GimpPickableInterface     *iface);
83 
84 static void       gimp_drawable_dispose            (GObject           *object);
85 static void       gimp_drawable_finalize           (GObject           *object);
86 static void       gimp_drawable_set_property       (GObject           *object,
87                                                     guint              property_id,
88                                                     const GValue      *value,
89                                                     GParamSpec        *pspec);
90 static void       gimp_drawable_get_property       (GObject           *object,
91                                                     guint              property_id,
92                                                     GValue            *value,
93                                                     GParamSpec        *pspec);
94 
95 static gint64     gimp_drawable_get_memsize        (GimpObject        *object,
96                                                     gint64            *gui_size);
97 
98 static gboolean   gimp_drawable_get_size           (GimpViewable      *viewable,
99                                                     gint              *width,
100                                                     gint              *height);
101 static void       gimp_drawable_preview_freeze     (GimpViewable      *viewable);
102 static void       gimp_drawable_preview_thaw       (GimpViewable      *viewable);
103 
104 static GeglNode * gimp_drawable_get_node           (GimpFilter        *filter);
105 
106 static void       gimp_drawable_removed            (GimpItem          *item);
107 static GimpItem * gimp_drawable_duplicate          (GimpItem          *item,
108                                                     GType              new_type);
109 static void       gimp_drawable_scale              (GimpItem          *item,
110                                                     gint               new_width,
111                                                     gint               new_height,
112                                                     gint               new_offset_x,
113                                                     gint               new_offset_y,
114                                                     GimpInterpolationType interp_type,
115                                                     GimpProgress      *progress);
116 static void       gimp_drawable_resize             (GimpItem          *item,
117                                                     GimpContext       *context,
118                                                     GimpFillType       fill_type,
119                                                     gint               new_width,
120                                                     gint               new_height,
121                                                     gint               offset_x,
122                                                     gint               offset_y);
123 static void       gimp_drawable_flip               (GimpItem          *item,
124                                                     GimpContext       *context,
125                                                     GimpOrientationType  flip_type,
126                                                     gdouble            axis,
127                                                     gboolean           clip_result);
128 static void       gimp_drawable_rotate             (GimpItem          *item,
129                                                     GimpContext       *context,
130                                                     GimpRotationType   rotate_type,
131                                                     gdouble            center_x,
132                                                     gdouble            center_y,
133                                                     gboolean           clip_result);
134 static void       gimp_drawable_transform          (GimpItem          *item,
135                                                     GimpContext       *context,
136                                                     const GimpMatrix3 *matrix,
137                                                     GimpTransformDirection direction,
138                                                     GimpInterpolationType interpolation_type,
139                                                     GimpTransformResize clip_result,
140                                                     GimpProgress      *progress);
141 
142 static const guint8 *
143                   gimp_drawable_get_icc_profile    (GimpColorManaged  *managed,
144                                                     gsize             *len);
145 static GimpColorProfile *
146                   gimp_drawable_get_color_profile  (GimpColorManaged  *managed);
147 static void       gimp_drawable_profile_changed    (GimpColorManaged  *managed);
148 
149 static gboolean   gimp_drawable_get_pixel_at       (GimpPickable      *pickable,
150                                                     gint               x,
151                                                     gint               y,
152                                                     const Babl        *format,
153                                                     gpointer           pixel);
154 static void       gimp_drawable_get_pixel_average  (GimpPickable      *pickable,
155                                                     const GeglRectangle *rect,
156                                                     const Babl        *format,
157                                                     gpointer           pixel);
158 
159 static void       gimp_drawable_real_update        (GimpDrawable      *drawable,
160                                                     gint               x,
161                                                     gint               y,
162                                                     gint               width,
163                                                     gint               height);
164 
165 static gint64  gimp_drawable_real_estimate_memsize (GimpDrawable      *drawable,
166                                                     GimpComponentType  component_type,
167                                                     gint               width,
168                                                     gint               height);
169 
170 static void       gimp_drawable_real_update_all    (GimpDrawable      *drawable);
171 
172 static GimpComponentMask
173                 gimp_drawable_real_get_active_mask (GimpDrawable      *drawable);
174 
175 static gboolean   gimp_drawable_real_supports_alpha
176                                                    (GimpDrawable     *drawable);
177 
178 static void       gimp_drawable_real_convert_type  (GimpDrawable      *drawable,
179                                                     GimpImage         *dest_image,
180                                                     const Babl        *new_format,
181                                                     GimpColorProfile  *dest_profile,
182                                                     GeglDitherMethod   layer_dither_type,
183                                                     GeglDitherMethod   mask_dither_type,
184                                                     gboolean           push_undo,
185                                                     GimpProgress      *progress);
186 
187 static GeglBuffer * gimp_drawable_real_get_buffer  (GimpDrawable      *drawable);
188 static void       gimp_drawable_real_set_buffer    (GimpDrawable      *drawable,
189                                                     gboolean           push_undo,
190                                                     const gchar       *undo_desc,
191                                                     GeglBuffer        *buffer,
192                                                     const GeglRectangle *bounds);
193 
194 static GeglRectangle gimp_drawable_real_get_bounding_box
195                                                    (GimpDrawable      *drawable);
196 
197 static void       gimp_drawable_real_push_undo     (GimpDrawable      *drawable,
198                                                     const gchar       *undo_desc,
199                                                     GeglBuffer        *buffer,
200                                                     gint               x,
201                                                     gint               y,
202                                                     gint               width,
203                                                     gint               height);
204 static void       gimp_drawable_real_swap_pixels   (GimpDrawable      *drawable,
205                                                     GeglBuffer        *buffer,
206                                                     gint               x,
207                                                     gint               y);
208 static GeglNode * gimp_drawable_real_get_source_node (GimpDrawable    *drawable);
209 
210 static void       gimp_drawable_format_changed     (GimpDrawable      *drawable);
211 static void       gimp_drawable_alpha_changed      (GimpDrawable      *drawable);
212 
213 
214 G_DEFINE_TYPE_WITH_CODE (GimpDrawable, gimp_drawable, GIMP_TYPE_ITEM,
215                          G_ADD_PRIVATE (GimpDrawable)
216                          G_IMPLEMENT_INTERFACE (GIMP_TYPE_COLOR_MANAGED,
217                                                 gimp_color_managed_iface_init)
218                          G_IMPLEMENT_INTERFACE (GIMP_TYPE_PICKABLE,
219                                                 gimp_pickable_iface_init))
220 
221 #define parent_class gimp_drawable_parent_class
222 
223 static guint gimp_drawable_signals[LAST_SIGNAL] = { 0 };
224 
225 
226 static void
gimp_drawable_class_init(GimpDrawableClass * klass)227 gimp_drawable_class_init (GimpDrawableClass *klass)
228 {
229   GObjectClass      *object_class      = G_OBJECT_CLASS (klass);
230   GimpObjectClass   *gimp_object_class = GIMP_OBJECT_CLASS (klass);
231   GimpViewableClass *viewable_class    = GIMP_VIEWABLE_CLASS (klass);
232   GimpFilterClass   *filter_class      = GIMP_FILTER_CLASS (klass);
233   GimpItemClass     *item_class        = GIMP_ITEM_CLASS (klass);
234 
235   gimp_drawable_signals[UPDATE] =
236     g_signal_new ("update",
237                   G_TYPE_FROM_CLASS (klass),
238                   G_SIGNAL_RUN_FIRST,
239                   G_STRUCT_OFFSET (GimpDrawableClass, update),
240                   NULL, NULL,
241                   gimp_marshal_VOID__INT_INT_INT_INT,
242                   G_TYPE_NONE, 4,
243                   G_TYPE_INT,
244                   G_TYPE_INT,
245                   G_TYPE_INT,
246                   G_TYPE_INT);
247 
248   gimp_drawable_signals[FORMAT_CHANGED] =
249     g_signal_new ("format-changed",
250                   G_TYPE_FROM_CLASS (klass),
251                   G_SIGNAL_RUN_FIRST,
252                   G_STRUCT_OFFSET (GimpDrawableClass, format_changed),
253                   NULL, NULL,
254                   gimp_marshal_VOID__VOID,
255                   G_TYPE_NONE, 0);
256 
257   gimp_drawable_signals[ALPHA_CHANGED] =
258     g_signal_new ("alpha-changed",
259                   G_TYPE_FROM_CLASS (klass),
260                   G_SIGNAL_RUN_FIRST,
261                   G_STRUCT_OFFSET (GimpDrawableClass, alpha_changed),
262                   NULL, NULL,
263                   gimp_marshal_VOID__VOID,
264                   G_TYPE_NONE, 0);
265 
266   gimp_drawable_signals[BOUNDING_BOX_CHANGED] =
267     g_signal_new ("bounding-box-changed",
268                   G_TYPE_FROM_CLASS (klass),
269                   G_SIGNAL_RUN_FIRST,
270                   G_STRUCT_OFFSET (GimpDrawableClass, bounding_box_changed),
271                   NULL, NULL,
272                   gimp_marshal_VOID__VOID,
273                   G_TYPE_NONE, 0);
274 
275   object_class->dispose           = gimp_drawable_dispose;
276   object_class->finalize          = gimp_drawable_finalize;
277   object_class->set_property      = gimp_drawable_set_property;
278   object_class->get_property      = gimp_drawable_get_property;
279 
280   gimp_object_class->get_memsize  = gimp_drawable_get_memsize;
281 
282   viewable_class->get_size        = gimp_drawable_get_size;
283   viewable_class->get_new_preview = gimp_drawable_get_new_preview;
284   viewable_class->get_new_pixbuf  = gimp_drawable_get_new_pixbuf;
285   viewable_class->preview_freeze  = gimp_drawable_preview_freeze;
286   viewable_class->preview_thaw    = gimp_drawable_preview_thaw;
287 
288   filter_class->get_node          = gimp_drawable_get_node;
289 
290   item_class->removed             = gimp_drawable_removed;
291   item_class->duplicate           = gimp_drawable_duplicate;
292   item_class->scale               = gimp_drawable_scale;
293   item_class->resize              = gimp_drawable_resize;
294   item_class->flip                = gimp_drawable_flip;
295   item_class->rotate              = gimp_drawable_rotate;
296   item_class->transform           = gimp_drawable_transform;
297 
298   klass->update                   = gimp_drawable_real_update;
299   klass->format_changed           = NULL;
300   klass->alpha_changed            = NULL;
301   klass->bounding_box_changed     = NULL;
302   klass->estimate_memsize         = gimp_drawable_real_estimate_memsize;
303   klass->update_all               = gimp_drawable_real_update_all;
304   klass->invalidate_boundary      = NULL;
305   klass->get_active_components    = NULL;
306   klass->get_active_mask          = gimp_drawable_real_get_active_mask;
307   klass->supports_alpha           = gimp_drawable_real_supports_alpha;
308   klass->convert_type             = gimp_drawable_real_convert_type;
309   klass->apply_buffer             = gimp_drawable_real_apply_buffer;
310   klass->get_buffer               = gimp_drawable_real_get_buffer;
311   klass->set_buffer               = gimp_drawable_real_set_buffer;
312   klass->get_bounding_box         = gimp_drawable_real_get_bounding_box;
313   klass->push_undo                = gimp_drawable_real_push_undo;
314   klass->swap_pixels              = gimp_drawable_real_swap_pixels;
315   klass->get_source_node          = gimp_drawable_real_get_source_node;
316 
317   g_object_class_override_property (object_class, PROP_BUFFER, "buffer");
318 }
319 
320 static void
gimp_drawable_init(GimpDrawable * drawable)321 gimp_drawable_init (GimpDrawable *drawable)
322 {
323   drawable->private = gimp_drawable_get_instance_private (drawable);
324 
325   drawable->private->filter_stack = gimp_filter_stack_new (GIMP_TYPE_FILTER);
326 }
327 
328 /* sorry for the evil casts */
329 
330 static void
gimp_color_managed_iface_init(GimpColorManagedInterface * iface)331 gimp_color_managed_iface_init (GimpColorManagedInterface *iface)
332 {
333   iface->get_icc_profile   = gimp_drawable_get_icc_profile;
334   iface->get_color_profile = gimp_drawable_get_color_profile;
335   iface->profile_changed   = gimp_drawable_profile_changed;
336 }
337 
338 static void
gimp_pickable_iface_init(GimpPickableInterface * iface)339 gimp_pickable_iface_init (GimpPickableInterface *iface)
340 {
341   iface->get_image             = (GimpImage     * (*) (GimpPickable *pickable)) gimp_item_get_image;
342   iface->get_format            = (const Babl    * (*) (GimpPickable *pickable)) gimp_drawable_get_format;
343   iface->get_format_with_alpha = (const Babl    * (*) (GimpPickable *pickable)) gimp_drawable_get_format_with_alpha;
344   iface->get_buffer            = (GeglBuffer    * (*) (GimpPickable *pickable)) gimp_drawable_get_buffer;
345   iface->get_pixel_at          = gimp_drawable_get_pixel_at;
346   iface->get_pixel_average     = gimp_drawable_get_pixel_average;
347 }
348 
349 static void
gimp_drawable_dispose(GObject * object)350 gimp_drawable_dispose (GObject *object)
351 {
352   GimpDrawable *drawable = GIMP_DRAWABLE (object);
353 
354   if (gimp_drawable_get_floating_sel (drawable))
355     gimp_drawable_detach_floating_sel (drawable);
356 
357   G_OBJECT_CLASS (parent_class)->dispose (object);
358 }
359 
360 static void
gimp_drawable_finalize(GObject * object)361 gimp_drawable_finalize (GObject *object)
362 {
363   GimpDrawable *drawable = GIMP_DRAWABLE (object);
364 
365   while (drawable->private->paint_count)
366     gimp_drawable_end_paint (drawable);
367 
368   g_clear_object (&drawable->private->buffer);
369 
370   gimp_drawable_free_shadow_buffer (drawable);
371 
372   g_clear_object (&drawable->private->source_node);
373   g_clear_object (&drawable->private->buffer_source_node);
374   g_clear_object (&drawable->private->filter_stack);
375 
376   G_OBJECT_CLASS (parent_class)->finalize (object);
377 }
378 
379 static void
gimp_drawable_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)380 gimp_drawable_set_property (GObject      *object,
381                             guint         property_id,
382                             const GValue *value,
383                             GParamSpec   *pspec)
384 {
385   switch (property_id)
386     {
387     case PROP_BUFFER:
388     default:
389       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
390       break;
391     }
392 }
393 
394 static void
gimp_drawable_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)395 gimp_drawable_get_property (GObject    *object,
396                             guint       property_id,
397                             GValue     *value,
398                             GParamSpec *pspec)
399 {
400   GimpDrawable *drawable = GIMP_DRAWABLE (object);
401 
402   switch (property_id)
403     {
404     case PROP_BUFFER:
405       g_value_set_object (value, drawable->private->buffer);
406       break;
407 
408     default:
409       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
410       break;
411     }
412 }
413 
414 static gint64
gimp_drawable_get_memsize(GimpObject * object,gint64 * gui_size)415 gimp_drawable_get_memsize (GimpObject *object,
416                            gint64     *gui_size)
417 {
418   GimpDrawable *drawable = GIMP_DRAWABLE (object);
419   gint64        memsize  = 0;
420 
421   memsize += gimp_gegl_buffer_get_memsize (gimp_drawable_get_buffer (drawable));
422   memsize += gimp_gegl_buffer_get_memsize (drawable->private->shadow);
423 
424   return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
425                                                                   gui_size);
426 }
427 
428 static gboolean
gimp_drawable_get_size(GimpViewable * viewable,gint * width,gint * height)429 gimp_drawable_get_size (GimpViewable *viewable,
430                         gint         *width,
431                         gint         *height)
432 {
433   GimpItem *item = GIMP_ITEM (viewable);
434 
435   *width  = gimp_item_get_width  (item);
436   *height = gimp_item_get_height (item);
437 
438   return TRUE;
439 }
440 
441 static void
gimp_drawable_preview_freeze(GimpViewable * viewable)442 gimp_drawable_preview_freeze (GimpViewable *viewable)
443 {
444   GimpViewable *parent = gimp_viewable_get_parent (viewable);
445 
446   if (! parent && gimp_item_is_attached (GIMP_ITEM (viewable)))
447     parent = GIMP_VIEWABLE (gimp_item_get_image (GIMP_ITEM (viewable)));
448 
449   if (parent)
450     gimp_viewable_preview_freeze (parent);
451 }
452 
453 static void
gimp_drawable_preview_thaw(GimpViewable * viewable)454 gimp_drawable_preview_thaw (GimpViewable *viewable)
455 {
456   GimpViewable *parent = gimp_viewable_get_parent (viewable);
457 
458   if (! parent && gimp_item_is_attached (GIMP_ITEM (viewable)))
459     parent = GIMP_VIEWABLE (gimp_item_get_image (GIMP_ITEM (viewable)));
460 
461   if (parent)
462     gimp_viewable_preview_thaw (parent);
463 }
464 
465 static GeglNode *
gimp_drawable_get_node(GimpFilter * filter)466 gimp_drawable_get_node (GimpFilter *filter)
467 {
468   GimpDrawable *drawable = GIMP_DRAWABLE (filter);
469   GeglNode     *node;
470   GeglNode     *input;
471   GeglNode     *output;
472 
473   node = GIMP_FILTER_CLASS (parent_class)->get_node (filter);
474 
475   g_warn_if_fail (drawable->private->mode_node == NULL);
476 
477   drawable->private->mode_node =
478     gegl_node_new_child (node,
479                          "operation", "gimp:normal",
480                          NULL);
481 
482   input  = gegl_node_get_input_proxy  (node, "input");
483   output = gegl_node_get_output_proxy (node, "output");
484 
485   gegl_node_connect_to (input,                        "output",
486                         drawable->private->mode_node, "input");
487   gegl_node_connect_to (drawable->private->mode_node, "output",
488                         output,                       "input");
489 
490   return node;
491 }
492 
493 static void
gimp_drawable_removed(GimpItem * item)494 gimp_drawable_removed (GimpItem *item)
495 {
496   GimpDrawable *drawable = GIMP_DRAWABLE (item);
497 
498   gimp_drawable_free_shadow_buffer (drawable);
499 
500   if (GIMP_ITEM_CLASS (parent_class)->removed)
501     GIMP_ITEM_CLASS (parent_class)->removed (item);
502 }
503 
504 static GimpItem *
gimp_drawable_duplicate(GimpItem * item,GType new_type)505 gimp_drawable_duplicate (GimpItem *item,
506                          GType     new_type)
507 {
508   GimpItem *new_item;
509 
510   g_return_val_if_fail (g_type_is_a (new_type, GIMP_TYPE_DRAWABLE), NULL);
511 
512   new_item = GIMP_ITEM_CLASS (parent_class)->duplicate (item, new_type);
513 
514   if (GIMP_IS_DRAWABLE (new_item))
515     {
516       GimpDrawable  *drawable     = GIMP_DRAWABLE (item);
517       GimpDrawable  *new_drawable = GIMP_DRAWABLE (new_item);
518       GeglBuffer    *new_buffer;
519 
520       new_buffer = gimp_gegl_buffer_dup (gimp_drawable_get_buffer (drawable));
521 
522       gimp_drawable_set_buffer (new_drawable, FALSE, NULL, new_buffer);
523       g_object_unref (new_buffer);
524     }
525 
526   return new_item;
527 }
528 
529 static void
gimp_drawable_scale(GimpItem * item,gint new_width,gint new_height,gint new_offset_x,gint new_offset_y,GimpInterpolationType interpolation_type,GimpProgress * progress)530 gimp_drawable_scale (GimpItem              *item,
531                      gint                   new_width,
532                      gint                   new_height,
533                      gint                   new_offset_x,
534                      gint                   new_offset_y,
535                      GimpInterpolationType  interpolation_type,
536                      GimpProgress          *progress)
537 {
538   GimpDrawable *drawable = GIMP_DRAWABLE (item);
539   GeglBuffer   *new_buffer;
540 
541   new_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
542                                                 new_width, new_height),
543                                 gimp_drawable_get_format (drawable));
544 
545   gimp_gegl_apply_scale (gimp_drawable_get_buffer (drawable),
546                          progress, C_("undo-type", "Scale"),
547                          new_buffer,
548                          interpolation_type,
549                          ((gdouble) new_width /
550                           gimp_item_get_width  (item)),
551                          ((gdouble) new_height /
552                           gimp_item_get_height (item)));
553 
554   gimp_drawable_set_buffer_full (drawable, gimp_item_is_attached (item), NULL,
555                                  new_buffer,
556                                  GEGL_RECTANGLE (new_offset_x, new_offset_y,
557                                                  0,            0),
558                                  TRUE);
559   g_object_unref (new_buffer);
560 }
561 
562 static void
gimp_drawable_resize(GimpItem * item,GimpContext * context,GimpFillType fill_type,gint new_width,gint new_height,gint offset_x,gint offset_y)563 gimp_drawable_resize (GimpItem     *item,
564                       GimpContext  *context,
565                       GimpFillType  fill_type,
566                       gint          new_width,
567                       gint          new_height,
568                       gint          offset_x,
569                       gint          offset_y)
570 {
571   GimpDrawable *drawable = GIMP_DRAWABLE (item);
572   GeglBuffer   *new_buffer;
573   gint          new_offset_x;
574   gint          new_offset_y;
575   gint          copy_x, copy_y;
576   gint          copy_width, copy_height;
577   gboolean      intersect;
578 
579   /*  if the size doesn't change, this is a nop  */
580   if (new_width  == gimp_item_get_width  (item) &&
581       new_height == gimp_item_get_height (item) &&
582       offset_x   == 0                           &&
583       offset_y   == 0)
584     return;
585 
586   new_offset_x = gimp_item_get_offset_x (item) - offset_x;
587   new_offset_y = gimp_item_get_offset_y (item) - offset_y;
588 
589   intersect = gimp_rectangle_intersect (gimp_item_get_offset_x (item),
590                                         gimp_item_get_offset_y (item),
591                                         gimp_item_get_width (item),
592                                         gimp_item_get_height (item),
593                                         new_offset_x,
594                                         new_offset_y,
595                                         new_width,
596                                         new_height,
597                                         &copy_x,
598                                         &copy_y,
599                                         &copy_width,
600                                         &copy_height);
601 
602   new_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
603                                                 new_width, new_height),
604                                 gimp_drawable_get_format (drawable));
605 
606   if (! intersect              ||
607       copy_width  != new_width ||
608       copy_height != new_height)
609     {
610       /*  Clear the new buffer if needed  */
611 
612       GimpRGB      color;
613       GimpPattern *pattern;
614 
615       gimp_get_fill_params (context, fill_type, &color, &pattern, NULL);
616       gimp_drawable_fill_buffer (drawable, new_buffer,
617                                  &color, pattern, 0, 0);
618     }
619 
620   if (intersect && copy_width && copy_height)
621     {
622       /*  Copy the pixels in the intersection  */
623       gimp_gegl_buffer_copy (
624         gimp_drawable_get_buffer (drawable),
625         GEGL_RECTANGLE (copy_x - gimp_item_get_offset_x (item),
626                         copy_y - gimp_item_get_offset_y (item),
627                         copy_width,
628                         copy_height), GEGL_ABYSS_NONE,
629         new_buffer,
630         GEGL_RECTANGLE (copy_x - new_offset_x,
631                         copy_y - new_offset_y, 0, 0));
632     }
633 
634   gimp_drawable_set_buffer_full (drawable, gimp_item_is_attached (item), NULL,
635                                  new_buffer,
636                                  GEGL_RECTANGLE (new_offset_x, new_offset_y,
637                                                  0,            0),
638                                  TRUE);
639   g_object_unref (new_buffer);
640 }
641 
642 static void
gimp_drawable_flip(GimpItem * item,GimpContext * context,GimpOrientationType flip_type,gdouble axis,gboolean clip_result)643 gimp_drawable_flip (GimpItem            *item,
644                     GimpContext         *context,
645                     GimpOrientationType  flip_type,
646                     gdouble              axis,
647                     gboolean             clip_result)
648 {
649   GimpDrawable     *drawable = GIMP_DRAWABLE (item);
650   GeglBuffer       *buffer;
651   GimpColorProfile *buffer_profile;
652   gint              off_x, off_y;
653   gint              new_off_x, new_off_y;
654 
655   gimp_item_get_offset (item, &off_x, &off_y);
656 
657   buffer = gimp_drawable_transform_buffer_flip (drawable, context,
658                                                 gimp_drawable_get_buffer (drawable),
659                                                 off_x, off_y,
660                                                 flip_type, axis,
661                                                 clip_result,
662                                                 &buffer_profile,
663                                                 &new_off_x, &new_off_y);
664 
665   if (buffer)
666     {
667       gimp_drawable_transform_paste (drawable, buffer, buffer_profile,
668                                      new_off_x, new_off_y, FALSE);
669       g_object_unref (buffer);
670     }
671 }
672 
673 static void
gimp_drawable_rotate(GimpItem * item,GimpContext * context,GimpRotationType rotate_type,gdouble center_x,gdouble center_y,gboolean clip_result)674 gimp_drawable_rotate (GimpItem         *item,
675                       GimpContext      *context,
676                       GimpRotationType  rotate_type,
677                       gdouble           center_x,
678                       gdouble           center_y,
679                       gboolean          clip_result)
680 {
681   GimpDrawable     *drawable = GIMP_DRAWABLE (item);
682   GeglBuffer       *buffer;
683   GimpColorProfile *buffer_profile;
684   gint              off_x, off_y;
685   gint              new_off_x, new_off_y;
686 
687   gimp_item_get_offset (item, &off_x, &off_y);
688 
689   buffer = gimp_drawable_transform_buffer_rotate (drawable, context,
690                                                   gimp_drawable_get_buffer (drawable),
691                                                   off_x, off_y,
692                                                   rotate_type, center_x, center_y,
693                                                   clip_result,
694                                                   &buffer_profile,
695                                                   &new_off_x, &new_off_y);
696 
697   if (buffer)
698     {
699       gimp_drawable_transform_paste (drawable, buffer, buffer_profile,
700                                      new_off_x, new_off_y, FALSE);
701       g_object_unref (buffer);
702     }
703 }
704 
705 static void
gimp_drawable_transform(GimpItem * item,GimpContext * context,const GimpMatrix3 * matrix,GimpTransformDirection direction,GimpInterpolationType interpolation_type,GimpTransformResize clip_result,GimpProgress * progress)706 gimp_drawable_transform (GimpItem               *item,
707                          GimpContext            *context,
708                          const GimpMatrix3      *matrix,
709                          GimpTransformDirection  direction,
710                          GimpInterpolationType   interpolation_type,
711                          GimpTransformResize     clip_result,
712                          GimpProgress           *progress)
713 {
714   GimpDrawable     *drawable = GIMP_DRAWABLE (item);
715   GeglBuffer       *buffer;
716   GimpColorProfile *buffer_profile;
717   gint              off_x, off_y;
718   gint              new_off_x, new_off_y;
719 
720   gimp_item_get_offset (item, &off_x, &off_y);
721 
722   buffer = gimp_drawable_transform_buffer_affine (drawable, context,
723                                                   gimp_drawable_get_buffer (drawable),
724                                                   off_x, off_y,
725                                                   matrix, direction,
726                                                   interpolation_type,
727                                                   clip_result,
728                                                   &buffer_profile,
729                                                   &new_off_x, &new_off_y,
730                                                   progress);
731 
732   if (buffer)
733     {
734       gimp_drawable_transform_paste (drawable, buffer, buffer_profile,
735                                      new_off_x, new_off_y, FALSE);
736       g_object_unref (buffer);
737     }
738 }
739 
740 static const guint8 *
gimp_drawable_get_icc_profile(GimpColorManaged * managed,gsize * len)741 gimp_drawable_get_icc_profile (GimpColorManaged *managed,
742                                gsize            *len)
743 {
744   GimpColorProfile *profile = gimp_color_managed_get_color_profile (managed);
745 
746   return gimp_color_profile_get_icc_profile (profile, len);
747 }
748 
749 static GimpColorProfile *
gimp_drawable_get_color_profile(GimpColorManaged * managed)750 gimp_drawable_get_color_profile (GimpColorManaged *managed)
751 {
752   const Babl *format = gimp_drawable_get_format (GIMP_DRAWABLE (managed));
753 
754   return gimp_babl_format_get_color_profile (format);
755 }
756 
757 static void
gimp_drawable_profile_changed(GimpColorManaged * managed)758 gimp_drawable_profile_changed (GimpColorManaged *managed)
759 {
760   gimp_viewable_invalidate_preview (GIMP_VIEWABLE (managed));
761 }
762 
763 static gboolean
gimp_drawable_get_pixel_at(GimpPickable * pickable,gint x,gint y,const Babl * format,gpointer pixel)764 gimp_drawable_get_pixel_at (GimpPickable *pickable,
765                             gint          x,
766                             gint          y,
767                             const Babl   *format,
768                             gpointer      pixel)
769 {
770   GimpDrawable *drawable = GIMP_DRAWABLE (pickable);
771 
772   /* do not make this a g_return_if_fail() */
773   if (x < 0 || x >= gimp_item_get_width  (GIMP_ITEM (drawable)) ||
774       y < 0 || y >= gimp_item_get_height (GIMP_ITEM (drawable)))
775     return FALSE;
776 
777   gegl_buffer_sample (gimp_drawable_get_buffer (drawable),
778                       x, y, NULL, pixel, format,
779                       GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
780 
781   return TRUE;
782 }
783 
784 static void
gimp_drawable_get_pixel_average(GimpPickable * pickable,const GeglRectangle * rect,const Babl * format,gpointer pixel)785 gimp_drawable_get_pixel_average (GimpPickable        *pickable,
786                                  const GeglRectangle *rect,
787                                  const Babl          *format,
788                                  gpointer             pixel)
789 {
790   GimpDrawable *drawable = GIMP_DRAWABLE (pickable);
791 
792   return gimp_gegl_average_color (gimp_drawable_get_buffer (drawable),
793                                   rect, TRUE, GEGL_ABYSS_NONE, format, pixel);
794 }
795 
796 static void
gimp_drawable_real_update(GimpDrawable * drawable,gint x,gint y,gint width,gint height)797 gimp_drawable_real_update (GimpDrawable *drawable,
798                            gint          x,
799                            gint          y,
800                            gint          width,
801                            gint          height)
802 {
803   gimp_viewable_invalidate_preview (GIMP_VIEWABLE (drawable));
804 }
805 
806 static gint64
gimp_drawable_real_estimate_memsize(GimpDrawable * drawable,GimpComponentType component_type,gint width,gint height)807 gimp_drawable_real_estimate_memsize (GimpDrawable      *drawable,
808                                      GimpComponentType  component_type,
809                                      gint               width,
810                                      gint               height)
811 {
812   GimpImage  *image  = gimp_item_get_image (GIMP_ITEM (drawable));
813   gboolean    linear = gimp_drawable_get_linear (drawable);
814   const Babl *format;
815 
816   format = gimp_image_get_format (image,
817                                   gimp_drawable_get_base_type (drawable),
818                                   gimp_babl_precision (component_type, linear),
819                                   gimp_drawable_has_alpha (drawable));
820 
821   return (gint64) babl_format_get_bytes_per_pixel (format) * width * height;
822 }
823 
824 static void
gimp_drawable_real_update_all(GimpDrawable * drawable)825 gimp_drawable_real_update_all (GimpDrawable *drawable)
826 {
827   gimp_drawable_update (drawable, 0, 0, -1, -1);
828 }
829 
830 static GimpComponentMask
gimp_drawable_real_get_active_mask(GimpDrawable * drawable)831 gimp_drawable_real_get_active_mask (GimpDrawable *drawable)
832 {
833   /*  Return all, because that skips the component mask op when painting  */
834   return GIMP_COMPONENT_MASK_ALL;
835 }
836 
837 static gboolean
gimp_drawable_real_supports_alpha(GimpDrawable * drawable)838 gimp_drawable_real_supports_alpha (GimpDrawable *drawable)
839 {
840   return FALSE;
841 }
842 
843 /* FIXME: this default impl is currently unused because no subclass
844  * chains up. the goal is to handle the almost identical subclass code
845  * here again.
846  */
847 static void
gimp_drawable_real_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)848 gimp_drawable_real_convert_type (GimpDrawable      *drawable,
849                                  GimpImage         *dest_image,
850                                  const Babl        *new_format,
851                                  GimpColorProfile  *dest_profile,
852                                  GeglDitherMethod   layer_dither_type,
853                                  GeglDitherMethod   mask_dither_type,
854                                  gboolean           push_undo,
855                                  GimpProgress      *progress)
856 {
857   GeglBuffer *dest_buffer;
858 
859   dest_buffer =
860     gegl_buffer_new (GEGL_RECTANGLE (0, 0,
861                                      gimp_item_get_width  (GIMP_ITEM (drawable)),
862                                      gimp_item_get_height (GIMP_ITEM (drawable))),
863                      new_format);
864 
865   gimp_gegl_buffer_copy (
866     gimp_drawable_get_buffer (drawable), NULL, GEGL_ABYSS_NONE,
867     dest_buffer, NULL);
868 
869   gimp_drawable_set_buffer (drawable, push_undo, NULL, dest_buffer);
870   g_object_unref (dest_buffer);
871 }
872 
873 static GeglBuffer *
gimp_drawable_real_get_buffer(GimpDrawable * drawable)874 gimp_drawable_real_get_buffer (GimpDrawable *drawable)
875 {
876   return drawable->private->buffer;
877 }
878 
879 static void
gimp_drawable_real_set_buffer(GimpDrawable * drawable,gboolean push_undo,const gchar * undo_desc,GeglBuffer * buffer,const GeglRectangle * bounds)880 gimp_drawable_real_set_buffer (GimpDrawable        *drawable,
881                                gboolean             push_undo,
882                                const gchar         *undo_desc,
883                                GeglBuffer          *buffer,
884                                const GeglRectangle *bounds)
885 {
886   GimpItem   *item          = GIMP_ITEM (drawable);
887   const Babl *old_format    = NULL;
888   gint        old_has_alpha = -1;
889 
890   g_object_freeze_notify (G_OBJECT (drawable));
891 
892   gimp_drawable_invalidate_boundary (drawable);
893 
894   if (push_undo)
895     gimp_image_undo_push_drawable_mod (gimp_item_get_image (item), undo_desc,
896                                        drawable, FALSE);
897 
898   if (drawable->private->buffer)
899     {
900       old_format    = gimp_drawable_get_format (drawable);
901       old_has_alpha = gimp_drawable_has_alpha (drawable);
902     }
903 
904   g_set_object (&drawable->private->buffer, buffer);
905 
906   if (drawable->private->buffer_source_node)
907     gegl_node_set (drawable->private->buffer_source_node,
908                    "buffer", gimp_drawable_get_buffer (drawable),
909                    NULL);
910 
911   gimp_item_set_offset (item, bounds->x, bounds->y);
912   gimp_item_set_size (item,
913                       bounds->width  ? bounds->width :
914                                        gegl_buffer_get_width (buffer),
915                       bounds->height ? bounds->height :
916                                        gegl_buffer_get_height (buffer));
917 
918   gimp_drawable_update_bounding_box (drawable);
919 
920   if (gimp_drawable_get_format (drawable) != old_format)
921     gimp_drawable_format_changed (drawable);
922 
923   if (gimp_drawable_has_alpha (drawable) != old_has_alpha)
924     gimp_drawable_alpha_changed (drawable);
925 
926   g_object_notify (G_OBJECT (drawable), "buffer");
927 
928   g_object_thaw_notify (G_OBJECT (drawable));
929 }
930 
931 static GeglRectangle
gimp_drawable_real_get_bounding_box(GimpDrawable * drawable)932 gimp_drawable_real_get_bounding_box (GimpDrawable *drawable)
933 {
934   return gegl_node_get_bounding_box (gimp_drawable_get_source_node (drawable));
935 }
936 
937 static void
gimp_drawable_real_push_undo(GimpDrawable * drawable,const gchar * undo_desc,GeglBuffer * buffer,gint x,gint y,gint width,gint height)938 gimp_drawable_real_push_undo (GimpDrawable *drawable,
939                               const gchar  *undo_desc,
940                               GeglBuffer   *buffer,
941                               gint          x,
942                               gint          y,
943                               gint          width,
944                               gint          height)
945 {
946   GimpImage *image;
947 
948   if (! buffer)
949     {
950       GeglBuffer    *drawable_buffer = gimp_drawable_get_buffer (drawable);
951       GeglRectangle  drawable_rect;
952 
953       gegl_rectangle_align_to_buffer (
954         &drawable_rect,
955         GEGL_RECTANGLE (x, y, width, height),
956         drawable_buffer,
957         GEGL_RECTANGLE_ALIGNMENT_SUPERSET);
958 
959       x      = drawable_rect.x;
960       y      = drawable_rect.y;
961       width  = drawable_rect.width;
962       height = drawable_rect.height;
963 
964       buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, width, height),
965                                 gimp_drawable_get_format (drawable));
966 
967       gimp_gegl_buffer_copy (
968         drawable_buffer,
969         &drawable_rect, GEGL_ABYSS_NONE,
970         buffer,
971         GEGL_RECTANGLE (0, 0, 0, 0));
972     }
973   else
974     {
975       g_object_ref (buffer);
976     }
977 
978   image = gimp_item_get_image (GIMP_ITEM (drawable));
979 
980   gimp_image_undo_push_drawable (image,
981                                  undo_desc, drawable,
982                                  buffer, x, y);
983 
984   g_object_unref (buffer);
985 }
986 
987 static void
gimp_drawable_real_swap_pixels(GimpDrawable * drawable,GeglBuffer * buffer,gint x,gint y)988 gimp_drawable_real_swap_pixels (GimpDrawable *drawable,
989                                 GeglBuffer   *buffer,
990                                 gint          x,
991                                 gint          y)
992 {
993   GeglBuffer *tmp;
994   gint        width  = gegl_buffer_get_width (buffer);
995   gint        height = gegl_buffer_get_height (buffer);
996 
997   tmp = gimp_gegl_buffer_dup (buffer);
998 
999   gimp_gegl_buffer_copy (gimp_drawable_get_buffer (drawable),
1000                          GEGL_RECTANGLE (x, y, width, height), GEGL_ABYSS_NONE,
1001                          buffer,
1002                          GEGL_RECTANGLE (0, 0, 0, 0));
1003   gimp_gegl_buffer_copy (tmp,
1004                          GEGL_RECTANGLE (0, 0, width, height), GEGL_ABYSS_NONE,
1005                          gimp_drawable_get_buffer (drawable),
1006                          GEGL_RECTANGLE (x, y, 0, 0));
1007 
1008   g_object_unref (tmp);
1009 
1010   gimp_drawable_update (drawable, x, y, width, height);
1011 }
1012 
1013 static GeglNode *
gimp_drawable_real_get_source_node(GimpDrawable * drawable)1014 gimp_drawable_real_get_source_node (GimpDrawable *drawable)
1015 {
1016   g_warn_if_fail (drawable->private->buffer_source_node == NULL);
1017 
1018   drawable->private->buffer_source_node =
1019     gegl_node_new_child (NULL,
1020                          "operation", "gimp:buffer-source-validate",
1021                          "buffer",    gimp_drawable_get_buffer (drawable),
1022                          NULL);
1023 
1024   return g_object_ref (drawable->private->buffer_source_node);
1025 }
1026 
1027 static void
gimp_drawable_format_changed(GimpDrawable * drawable)1028 gimp_drawable_format_changed (GimpDrawable *drawable)
1029 {
1030   g_signal_emit (drawable, gimp_drawable_signals[FORMAT_CHANGED], 0);
1031 }
1032 
1033 static void
gimp_drawable_alpha_changed(GimpDrawable * drawable)1034 gimp_drawable_alpha_changed (GimpDrawable *drawable)
1035 {
1036   g_signal_emit (drawable, gimp_drawable_signals[ALPHA_CHANGED], 0);
1037 }
1038 
1039 
1040 /*  public functions  */
1041 
1042 GimpDrawable *
gimp_drawable_new(GType type,GimpImage * image,const gchar * name,gint offset_x,gint offset_y,gint width,gint height,const Babl * format)1043 gimp_drawable_new (GType          type,
1044                    GimpImage     *image,
1045                    const gchar   *name,
1046                    gint           offset_x,
1047                    gint           offset_y,
1048                    gint           width,
1049                    gint           height,
1050                    const Babl    *format)
1051 {
1052   GimpDrawable *drawable;
1053   GeglBuffer   *buffer;
1054 
1055   g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
1056   g_return_val_if_fail (g_type_is_a (type, GIMP_TYPE_DRAWABLE), NULL);
1057   g_return_val_if_fail (width > 0 && height > 0, NULL);
1058   g_return_val_if_fail (format != NULL, NULL);
1059 
1060   drawable = GIMP_DRAWABLE (gimp_item_new (type,
1061                                            image, name,
1062                                            offset_x, offset_y,
1063                                            width, height));
1064 
1065   buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, width, height), format);
1066 
1067   gimp_drawable_set_buffer (drawable, FALSE, NULL, buffer);
1068   g_object_unref (buffer);
1069 
1070   return drawable;
1071 }
1072 
1073 gint64
gimp_drawable_estimate_memsize(GimpDrawable * drawable,GimpComponentType component_type,gint width,gint height)1074 gimp_drawable_estimate_memsize (GimpDrawable      *drawable,
1075                                 GimpComponentType  component_type,
1076                                 gint               width,
1077                                 gint               height)
1078 {
1079   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), 0);
1080 
1081   return GIMP_DRAWABLE_GET_CLASS (drawable)->estimate_memsize (drawable,
1082                                                                component_type,
1083                                                                width, height);
1084 }
1085 
1086 void
gimp_drawable_update(GimpDrawable * drawable,gint x,gint y,gint width,gint height)1087 gimp_drawable_update (GimpDrawable *drawable,
1088                       gint          x,
1089                       gint          y,
1090                       gint          width,
1091                       gint          height)
1092 {
1093   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
1094 
1095   if (width < 0)
1096     {
1097       GeglRectangle bounding_box;
1098 
1099       bounding_box = gimp_drawable_get_bounding_box (drawable);
1100 
1101       x     = bounding_box.x;
1102       width = bounding_box.width;
1103     }
1104 
1105   if (height < 0)
1106     {
1107       GeglRectangle bounding_box;
1108 
1109       bounding_box = gimp_drawable_get_bounding_box (drawable);
1110 
1111       y      = bounding_box.y;
1112       height = bounding_box.height;
1113     }
1114 
1115   if (drawable->private->paint_count == 0)
1116     {
1117       g_signal_emit (drawable, gimp_drawable_signals[UPDATE], 0,
1118                      x, y, width, height);
1119     }
1120   else
1121     {
1122       GeglRectangle rect;
1123 
1124       if (gegl_rectangle_intersect (
1125             &rect,
1126             GEGL_RECTANGLE (x, y, width, height),
1127             GEGL_RECTANGLE (0, 0,
1128                             gimp_item_get_width  (GIMP_ITEM (drawable)),
1129                             gimp_item_get_height (GIMP_ITEM (drawable)))))
1130         {
1131           GeglRectangle aligned_rect;
1132 
1133           gegl_rectangle_align_to_buffer (&aligned_rect, &rect,
1134                                           gimp_drawable_get_buffer (drawable),
1135                                           GEGL_RECTANGLE_ALIGNMENT_SUPERSET);
1136 
1137           if (drawable->private->paint_copy_region)
1138             {
1139               cairo_region_union_rectangle (
1140                 drawable->private->paint_copy_region,
1141                 (const cairo_rectangle_int_t *) &aligned_rect);
1142             }
1143           else
1144             {
1145               drawable->private->paint_copy_region =
1146                 cairo_region_create_rectangle (
1147                   (const cairo_rectangle_int_t *) &aligned_rect);
1148             }
1149 
1150           gegl_rectangle_align (&aligned_rect, &rect,
1151                                 GEGL_RECTANGLE (0, 0,
1152                                                 PAINT_UPDATE_CHUNK_WIDTH,
1153                                                 PAINT_UPDATE_CHUNK_HEIGHT),
1154                                 GEGL_RECTANGLE_ALIGNMENT_SUPERSET);
1155 
1156           if (drawable->private->paint_update_region)
1157             {
1158               cairo_region_union_rectangle (
1159                 drawable->private->paint_update_region,
1160                 (const cairo_rectangle_int_t *) &aligned_rect);
1161             }
1162           else
1163             {
1164               drawable->private->paint_update_region =
1165                 cairo_region_create_rectangle (
1166                   (const cairo_rectangle_int_t *) &aligned_rect);
1167             }
1168         }
1169     }
1170 }
1171 
1172 void
gimp_drawable_update_all(GimpDrawable * drawable)1173 gimp_drawable_update_all (GimpDrawable *drawable)
1174 {
1175   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
1176 
1177   GIMP_DRAWABLE_GET_CLASS (drawable)->update_all (drawable);
1178 }
1179 
1180 void
gimp_drawable_invalidate_boundary(GimpDrawable * drawable)1181 gimp_drawable_invalidate_boundary (GimpDrawable *drawable)
1182 {
1183   GimpDrawableClass *drawable_class;
1184 
1185   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
1186 
1187   drawable_class = GIMP_DRAWABLE_GET_CLASS (drawable);
1188 
1189   if (drawable_class->invalidate_boundary)
1190     drawable_class->invalidate_boundary (drawable);
1191 }
1192 
1193 void
gimp_drawable_get_active_components(GimpDrawable * drawable,gboolean * active)1194 gimp_drawable_get_active_components (GimpDrawable *drawable,
1195                                      gboolean     *active)
1196 {
1197   GimpDrawableClass *drawable_class;
1198 
1199   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
1200   g_return_if_fail (active != NULL);
1201 
1202   drawable_class = GIMP_DRAWABLE_GET_CLASS (drawable);
1203 
1204   if (drawable_class->get_active_components)
1205     drawable_class->get_active_components (drawable, active);
1206 }
1207 
1208 GimpComponentMask
gimp_drawable_get_active_mask(GimpDrawable * drawable)1209 gimp_drawable_get_active_mask (GimpDrawable *drawable)
1210 {
1211   GimpComponentMask mask;
1212 
1213   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), 0);
1214 
1215   mask = GIMP_DRAWABLE_GET_CLASS (drawable)->get_active_mask (drawable);
1216 
1217   /* if the drawable doesn't have an alpha channel, the value of the mask's
1218    * alpha-bit doesn't matter, however, we'd like to have a fully-clear or
1219    * fully-set mask whenever possible, since it allows us to skip component
1220    * masking altogether.  we therefore set or clear the alpha bit, depending on
1221    * the state of the other bits, so that it never gets in the way of a uniform
1222    * mask.
1223    */
1224   if (! gimp_drawable_has_alpha (drawable))
1225     {
1226       if (mask & ~GIMP_COMPONENT_MASK_ALPHA)
1227         mask |= GIMP_COMPONENT_MASK_ALPHA;
1228       else
1229         mask &= ~GIMP_COMPONENT_MASK_ALPHA;
1230     }
1231 
1232   return mask;
1233 }
1234 
1235 gboolean
gimp_drawable_supports_alpha(GimpDrawable * drawable)1236 gimp_drawable_supports_alpha (GimpDrawable *drawable)
1237 {
1238   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
1239 
1240   return GIMP_DRAWABLE_GET_CLASS (drawable)->supports_alpha (drawable);
1241 }
1242 
1243 void
gimp_drawable_convert_type(GimpDrawable * drawable,GimpImage * dest_image,GimpImageBaseType new_base_type,GimpPrecision new_precision,gboolean new_has_alpha,GimpColorProfile * dest_profile,GeglDitherMethod layer_dither_type,GeglDitherMethod mask_dither_type,gboolean push_undo,GimpProgress * progress)1244 gimp_drawable_convert_type (GimpDrawable      *drawable,
1245                             GimpImage         *dest_image,
1246                             GimpImageBaseType  new_base_type,
1247                             GimpPrecision      new_precision,
1248                             gboolean           new_has_alpha,
1249                             GimpColorProfile  *dest_profile,
1250                             GeglDitherMethod   layer_dither_type,
1251                             GeglDitherMethod   mask_dither_type,
1252                             gboolean           push_undo,
1253                             GimpProgress      *progress)
1254 {
1255   const Babl *old_format;
1256   const Babl *new_format;
1257   gint        old_bits;
1258   gint        new_bits;
1259 
1260   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
1261   g_return_if_fail (GIMP_IS_IMAGE (dest_image));
1262   g_return_if_fail (new_base_type != gimp_drawable_get_base_type (drawable) ||
1263                     new_precision != gimp_drawable_get_precision (drawable) ||
1264                     new_has_alpha != gimp_drawable_has_alpha (drawable)     ||
1265                     dest_profile);
1266   g_return_if_fail (dest_profile == NULL || GIMP_IS_COLOR_PROFILE (dest_profile));
1267   g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));
1268 
1269   if (! gimp_item_is_attached (GIMP_ITEM (drawable)))
1270     push_undo = FALSE;
1271 
1272   old_format = gimp_drawable_get_format (drawable);
1273   new_format = gimp_image_get_format (dest_image,
1274                                       new_base_type,
1275                                       new_precision,
1276                                       new_has_alpha);
1277 
1278   old_bits = (babl_format_get_bytes_per_pixel (old_format) * 8 /
1279               babl_format_get_n_components (old_format));
1280   new_bits = (babl_format_get_bytes_per_pixel (new_format) * 8 /
1281               babl_format_get_n_components (new_format));
1282 
1283   if (old_bits <= new_bits || new_bits > 16)
1284     {
1285       /*  don't dither if we are converting to a higher bit depth,
1286        *  or to more than 16 bits (gegl:dither only does
1287        *  16 bits).
1288        */
1289       layer_dither_type = GEGL_DITHER_NONE;
1290       mask_dither_type  = GEGL_DITHER_NONE;
1291     }
1292 
1293   GIMP_DRAWABLE_GET_CLASS (drawable)->convert_type (drawable, dest_image,
1294                                                     new_format,
1295                                                     dest_profile,
1296                                                     layer_dither_type,
1297                                                     mask_dither_type,
1298                                                     push_undo,
1299                                                     progress);
1300 
1301   if (progress)
1302     gimp_progress_set_value (progress, 1.0);
1303 }
1304 
1305 void
gimp_drawable_apply_buffer(GimpDrawable * drawable,GeglBuffer * buffer,const GeglRectangle * buffer_region,gboolean push_undo,const gchar * undo_desc,gdouble opacity,GimpLayerMode mode,GimpLayerColorSpace blend_space,GimpLayerColorSpace composite_space,GimpLayerCompositeMode composite_mode,GeglBuffer * base_buffer,gint base_x,gint base_y)1306 gimp_drawable_apply_buffer (GimpDrawable           *drawable,
1307                             GeglBuffer             *buffer,
1308                             const GeglRectangle    *buffer_region,
1309                             gboolean                push_undo,
1310                             const gchar            *undo_desc,
1311                             gdouble                 opacity,
1312                             GimpLayerMode           mode,
1313                             GimpLayerColorSpace     blend_space,
1314                             GimpLayerColorSpace     composite_space,
1315                             GimpLayerCompositeMode  composite_mode,
1316                             GeglBuffer             *base_buffer,
1317                             gint                    base_x,
1318                             gint                    base_y)
1319 {
1320   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
1321   g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
1322   g_return_if_fail (GEGL_IS_BUFFER (buffer));
1323   g_return_if_fail (buffer_region != NULL);
1324   g_return_if_fail (base_buffer == NULL || GEGL_IS_BUFFER (base_buffer));
1325 
1326   GIMP_DRAWABLE_GET_CLASS (drawable)->apply_buffer (drawable, buffer,
1327                                                     buffer_region,
1328                                                     push_undo, undo_desc,
1329                                                     opacity, mode,
1330                                                     blend_space,
1331                                                     composite_space,
1332                                                     composite_mode,
1333                                                     base_buffer,
1334                                                     base_x, base_y);
1335 }
1336 
1337 GeglBuffer *
gimp_drawable_get_buffer(GimpDrawable * drawable)1338 gimp_drawable_get_buffer (GimpDrawable *drawable)
1339 {
1340   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
1341 
1342   if (drawable->private->paint_count == 0)
1343     return GIMP_DRAWABLE_GET_CLASS (drawable)->get_buffer (drawable);
1344   else
1345     return drawable->private->paint_buffer;
1346 }
1347 
1348 void
gimp_drawable_set_buffer(GimpDrawable * drawable,gboolean push_undo,const gchar * undo_desc,GeglBuffer * buffer)1349 gimp_drawable_set_buffer (GimpDrawable *drawable,
1350                           gboolean      push_undo,
1351                           const gchar  *undo_desc,
1352                           GeglBuffer   *buffer)
1353 {
1354   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
1355   g_return_if_fail (GEGL_IS_BUFFER (buffer));
1356 
1357   if (! gimp_item_is_attached (GIMP_ITEM (drawable)))
1358     push_undo = FALSE;
1359 
1360   gimp_drawable_set_buffer_full (drawable, push_undo, undo_desc, buffer, NULL,
1361                                  TRUE);
1362 }
1363 
1364 void
gimp_drawable_set_buffer_full(GimpDrawable * drawable,gboolean push_undo,const gchar * undo_desc,GeglBuffer * buffer,const GeglRectangle * bounds,gboolean update)1365 gimp_drawable_set_buffer_full (GimpDrawable        *drawable,
1366                                gboolean             push_undo,
1367                                const gchar         *undo_desc,
1368                                GeglBuffer          *buffer,
1369                                const GeglRectangle *bounds,
1370                                gboolean             update)
1371 {
1372   GimpItem      *item;
1373   GeglRectangle  curr_bounds;
1374 
1375   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
1376   g_return_if_fail (GEGL_IS_BUFFER (buffer));
1377 
1378   item = GIMP_ITEM (drawable);
1379 
1380   if (! gimp_item_is_attached (GIMP_ITEM (drawable)))
1381     push_undo = FALSE;
1382 
1383   if (! bounds)
1384     {
1385       gimp_item_get_offset (GIMP_ITEM (drawable),
1386                             &curr_bounds.x, &curr_bounds.y);
1387 
1388       curr_bounds.width  = 0;
1389       curr_bounds.height = 0;
1390 
1391       bounds = &curr_bounds;
1392     }
1393 
1394   if (update && gimp_drawable_get_buffer (drawable))
1395     {
1396       GeglBuffer    *old_buffer = gimp_drawable_get_buffer (drawable);
1397       GeglRectangle  old_extent;
1398       GeglRectangle  new_extent;
1399 
1400       old_extent = *gegl_buffer_get_extent (old_buffer);
1401       old_extent.x += gimp_item_get_offset_x (item);
1402       old_extent.y += gimp_item_get_offset_x (item);
1403 
1404       new_extent = *gegl_buffer_get_extent (buffer);
1405       new_extent.x += bounds->x;
1406       new_extent.y += bounds->y;
1407 
1408       if (! gegl_rectangle_equal (&old_extent, &new_extent))
1409         gimp_drawable_update (drawable, 0, 0, -1, -1);
1410     }
1411 
1412   g_object_freeze_notify (G_OBJECT (drawable));
1413 
1414   GIMP_DRAWABLE_GET_CLASS (drawable)->set_buffer (drawable,
1415                                                   push_undo, undo_desc,
1416                                                   buffer, bounds);
1417 
1418   g_object_thaw_notify (G_OBJECT (drawable));
1419 
1420   if (update)
1421     gimp_drawable_update (drawable, 0, 0, -1, -1);
1422 }
1423 
1424 void
gimp_drawable_steal_buffer(GimpDrawable * drawable,GimpDrawable * src_drawable)1425 gimp_drawable_steal_buffer (GimpDrawable *drawable,
1426                             GimpDrawable *src_drawable)
1427 {
1428   GeglBuffer *buffer;
1429   GeglBuffer *replacement_buffer;
1430 
1431   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
1432   g_return_if_fail (GIMP_IS_DRAWABLE (src_drawable));
1433 
1434   buffer = gimp_drawable_get_buffer (src_drawable);
1435 
1436   g_return_if_fail (buffer != NULL);
1437 
1438   g_object_ref (buffer);
1439 
1440   replacement_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, 1, 1),
1441                                         gegl_buffer_get_format (buffer));
1442 
1443   gimp_drawable_set_buffer (src_drawable, FALSE, NULL, replacement_buffer);
1444   gimp_drawable_set_buffer (drawable,     FALSE, NULL, buffer);
1445 
1446   g_object_unref (replacement_buffer);
1447   g_object_unref (buffer);
1448 }
1449 
1450 GeglNode *
gimp_drawable_get_source_node(GimpDrawable * drawable)1451 gimp_drawable_get_source_node (GimpDrawable *drawable)
1452 {
1453   GeglNode *input;
1454   GeglNode *source;
1455   GeglNode *filter;
1456   GeglNode *output;
1457 
1458   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
1459 
1460   if (drawable->private->source_node)
1461     return drawable->private->source_node;
1462 
1463   drawable->private->source_node = gegl_node_new ();
1464 
1465   input = gegl_node_get_input_proxy (drawable->private->source_node, "input");
1466 
1467   source = GIMP_DRAWABLE_GET_CLASS (drawable)->get_source_node (drawable);
1468 
1469   gegl_node_add_child (drawable->private->source_node, source);
1470 
1471   g_object_unref (source);
1472 
1473   if (gegl_node_has_pad (source, "input"))
1474     {
1475       gegl_node_connect_to (input,  "output",
1476                             source, "input");
1477     }
1478 
1479   filter = gimp_filter_stack_get_graph (GIMP_FILTER_STACK (drawable->private->filter_stack));
1480 
1481   gegl_node_add_child (drawable->private->source_node, filter);
1482 
1483   gegl_node_connect_to (source, "output",
1484                         filter, "input");
1485 
1486   output = gegl_node_get_output_proxy (drawable->private->source_node, "output");
1487 
1488   gegl_node_connect_to (filter, "output",
1489                         output, "input");
1490 
1491   if (gimp_drawable_get_floating_sel (drawable))
1492     _gimp_drawable_add_floating_sel_filter (drawable);
1493 
1494   return drawable->private->source_node;
1495 }
1496 
1497 GeglNode *
gimp_drawable_get_mode_node(GimpDrawable * drawable)1498 gimp_drawable_get_mode_node (GimpDrawable *drawable)
1499 {
1500   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
1501 
1502   if (! drawable->private->mode_node)
1503     gimp_filter_get_node (GIMP_FILTER (drawable));
1504 
1505   return drawable->private->mode_node;
1506 }
1507 
1508 GeglRectangle
gimp_drawable_get_bounding_box(GimpDrawable * drawable)1509 gimp_drawable_get_bounding_box (GimpDrawable *drawable)
1510 {
1511   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable),
1512                         *GEGL_RECTANGLE (0, 0, 0, 0));
1513 
1514   if (gegl_rectangle_is_empty (&drawable->private->bounding_box))
1515     gimp_drawable_update_bounding_box (drawable);
1516 
1517   return drawable->private->bounding_box;
1518 }
1519 
1520 gboolean
gimp_drawable_update_bounding_box(GimpDrawable * drawable)1521 gimp_drawable_update_bounding_box (GimpDrawable *drawable)
1522 {
1523   GeglRectangle bounding_box;
1524 
1525   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
1526 
1527   bounding_box =
1528     GIMP_DRAWABLE_GET_CLASS (drawable)->get_bounding_box (drawable);
1529 
1530   if (! gegl_rectangle_equal (&bounding_box, &drawable->private->bounding_box))
1531     {
1532       GeglRectangle old_bounding_box = drawable->private->bounding_box;
1533       GeglRectangle diff_rects[4];
1534       gint          n_diff_rects;
1535       gint          i;
1536 
1537       n_diff_rects = gegl_rectangle_subtract (diff_rects,
1538                                               &old_bounding_box,
1539                                               &bounding_box);
1540 
1541       for (i = 0; i < n_diff_rects; i++)
1542         {
1543           gimp_drawable_update (drawable,
1544                                 diff_rects[i].x,
1545                                 diff_rects[i].y,
1546                                 diff_rects[i].width,
1547                                 diff_rects[i].height);
1548         }
1549 
1550       drawable->private->bounding_box = bounding_box;
1551 
1552       g_signal_emit (drawable, gimp_drawable_signals[BOUNDING_BOX_CHANGED], 0);
1553 
1554       n_diff_rects = gegl_rectangle_subtract (diff_rects,
1555                                               &bounding_box,
1556                                               &old_bounding_box);
1557 
1558       for (i = 0; i < n_diff_rects; i++)
1559         {
1560           gimp_drawable_update (drawable,
1561                                 diff_rects[i].x,
1562                                 diff_rects[i].y,
1563                                 diff_rects[i].width,
1564                                 diff_rects[i].height);
1565         }
1566 
1567       return TRUE;
1568     }
1569 
1570   return FALSE;
1571 }
1572 
1573 void
gimp_drawable_swap_pixels(GimpDrawable * drawable,GeglBuffer * buffer,gint x,gint y)1574 gimp_drawable_swap_pixels (GimpDrawable *drawable,
1575                            GeglBuffer   *buffer,
1576                            gint          x,
1577                            gint          y)
1578 {
1579   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
1580   g_return_if_fail (GEGL_IS_BUFFER (buffer));
1581 
1582   GIMP_DRAWABLE_GET_CLASS (drawable)->swap_pixels (drawable, buffer, x, y);
1583 }
1584 
1585 void
gimp_drawable_push_undo(GimpDrawable * drawable,const gchar * undo_desc,GeglBuffer * buffer,gint x,gint y,gint width,gint height)1586 gimp_drawable_push_undo (GimpDrawable *drawable,
1587                          const gchar  *undo_desc,
1588                          GeglBuffer   *buffer,
1589                          gint          x,
1590                          gint          y,
1591                          gint          width,
1592                          gint          height)
1593 {
1594   GimpItem *item;
1595 
1596   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
1597   g_return_if_fail (buffer == NULL || GEGL_IS_BUFFER (buffer));
1598 
1599   item = GIMP_ITEM (drawable);
1600 
1601   g_return_if_fail (gimp_item_is_attached (item));
1602 
1603   if (! buffer &&
1604       ! gimp_rectangle_intersect (x, y,
1605                                   width, height,
1606                                   0, 0,
1607                                   gimp_item_get_width (item),
1608                                   gimp_item_get_height (item),
1609                                   &x, &y, &width, &height))
1610     {
1611       g_warning ("%s: tried to push empty region", G_STRFUNC);
1612       return;
1613     }
1614 
1615   GIMP_DRAWABLE_GET_CLASS (drawable)->push_undo (drawable, undo_desc,
1616                                                  buffer,
1617                                                  x, y, width, height);
1618 }
1619 
1620 const Babl *
gimp_drawable_get_format(GimpDrawable * drawable)1621 gimp_drawable_get_format (GimpDrawable *drawable)
1622 {
1623   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
1624 
1625   return gegl_buffer_get_format (drawable->private->buffer);
1626 }
1627 
1628 const Babl *
gimp_drawable_get_format_with_alpha(GimpDrawable * drawable)1629 gimp_drawable_get_format_with_alpha (GimpDrawable *drawable)
1630 {
1631   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
1632 
1633   return gimp_image_get_format (gimp_item_get_image (GIMP_ITEM (drawable)),
1634                                 gimp_drawable_get_base_type (drawable),
1635                                 gimp_drawable_get_precision (drawable),
1636                                 TRUE);
1637 }
1638 
1639 const Babl *
gimp_drawable_get_format_without_alpha(GimpDrawable * drawable)1640 gimp_drawable_get_format_without_alpha (GimpDrawable *drawable)
1641 {
1642   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
1643 
1644   return gimp_image_get_format (gimp_item_get_image (GIMP_ITEM (drawable)),
1645                                 gimp_drawable_get_base_type (drawable),
1646                                 gimp_drawable_get_precision (drawable),
1647                                 FALSE);
1648 }
1649 
1650 gboolean
gimp_drawable_get_linear(GimpDrawable * drawable)1651 gimp_drawable_get_linear (GimpDrawable *drawable)
1652 {
1653   const Babl *format;
1654 
1655   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
1656 
1657   format = gegl_buffer_get_format (drawable->private->buffer);
1658 
1659   return gimp_babl_format_get_linear (format);
1660 }
1661 
1662 gboolean
gimp_drawable_has_alpha(GimpDrawable * drawable)1663 gimp_drawable_has_alpha (GimpDrawable *drawable)
1664 {
1665   const Babl *format;
1666 
1667   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
1668 
1669   format = gegl_buffer_get_format (drawable->private->buffer);
1670 
1671   return babl_format_has_alpha (format);
1672 }
1673 
1674 GimpImageBaseType
gimp_drawable_get_base_type(GimpDrawable * drawable)1675 gimp_drawable_get_base_type (GimpDrawable *drawable)
1676 {
1677   const Babl *format;
1678 
1679   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);
1680 
1681   format = gegl_buffer_get_format (drawable->private->buffer);
1682 
1683   return gimp_babl_format_get_base_type (format);
1684 }
1685 
1686 GimpComponentType
gimp_drawable_get_component_type(GimpDrawable * drawable)1687 gimp_drawable_get_component_type (GimpDrawable *drawable)
1688 {
1689   const Babl *format;
1690 
1691   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);
1692 
1693   format = gegl_buffer_get_format (drawable->private->buffer);
1694 
1695   return gimp_babl_format_get_component_type (format);
1696 }
1697 
1698 GimpPrecision
gimp_drawable_get_precision(GimpDrawable * drawable)1699 gimp_drawable_get_precision (GimpDrawable *drawable)
1700 {
1701   const Babl *format;
1702 
1703   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);
1704 
1705   format = gegl_buffer_get_format (drawable->private->buffer);
1706 
1707   return gimp_babl_format_get_precision (format);
1708 }
1709 
1710 gboolean
gimp_drawable_is_rgb(GimpDrawable * drawable)1711 gimp_drawable_is_rgb (GimpDrawable *drawable)
1712 {
1713   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
1714 
1715   return (gimp_drawable_get_base_type (drawable) == GIMP_RGB);
1716 }
1717 
1718 gboolean
gimp_drawable_is_gray(GimpDrawable * drawable)1719 gimp_drawable_is_gray (GimpDrawable *drawable)
1720 {
1721   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
1722 
1723   return (gimp_drawable_get_base_type (drawable) == GIMP_GRAY);
1724 }
1725 
1726 gboolean
gimp_drawable_is_indexed(GimpDrawable * drawable)1727 gimp_drawable_is_indexed (GimpDrawable *drawable)
1728 {
1729   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
1730 
1731   return (gimp_drawable_get_base_type (drawable) == GIMP_INDEXED);
1732 }
1733 
1734 const Babl *
gimp_drawable_get_component_format(GimpDrawable * drawable,GimpChannelType channel)1735 gimp_drawable_get_component_format (GimpDrawable    *drawable,
1736                                     GimpChannelType  channel)
1737 {
1738   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
1739 
1740   switch (channel)
1741     {
1742     case GIMP_CHANNEL_RED:
1743       return gimp_babl_component_format (GIMP_RGB,
1744                                          gimp_drawable_get_precision (drawable),
1745                                          RED);
1746 
1747     case GIMP_CHANNEL_GREEN:
1748       return gimp_babl_component_format (GIMP_RGB,
1749                                          gimp_drawable_get_precision (drawable),
1750                                          GREEN);
1751 
1752     case GIMP_CHANNEL_BLUE:
1753       return gimp_babl_component_format (GIMP_RGB,
1754                                          gimp_drawable_get_precision (drawable),
1755                                          BLUE);
1756 
1757     case GIMP_CHANNEL_ALPHA:
1758       return gimp_babl_component_format (GIMP_RGB,
1759                                          gimp_drawable_get_precision (drawable),
1760                                          ALPHA);
1761 
1762     case GIMP_CHANNEL_GRAY:
1763       return gimp_babl_component_format (GIMP_GRAY,
1764                                          gimp_drawable_get_precision (drawable),
1765                                          GRAY);
1766 
1767     case GIMP_CHANNEL_INDEXED:
1768       return babl_format ("Y u8"); /* will extract grayscale, the best
1769                                     * we can do here */
1770     }
1771 
1772   return NULL;
1773 }
1774 
1775 gint
gimp_drawable_get_component_index(GimpDrawable * drawable,GimpChannelType channel)1776 gimp_drawable_get_component_index (GimpDrawable    *drawable,
1777                                    GimpChannelType  channel)
1778 {
1779   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), -1);
1780 
1781   switch (channel)
1782     {
1783     case GIMP_CHANNEL_RED:     return RED;
1784     case GIMP_CHANNEL_GREEN:   return GREEN;
1785     case GIMP_CHANNEL_BLUE:    return BLUE;
1786     case GIMP_CHANNEL_GRAY:    return GRAY;
1787     case GIMP_CHANNEL_INDEXED: return INDEXED;
1788     case GIMP_CHANNEL_ALPHA:
1789       switch (gimp_drawable_get_base_type (drawable))
1790         {
1791         case GIMP_RGB:     return ALPHA;
1792         case GIMP_GRAY:    return ALPHA_G;
1793         case GIMP_INDEXED: return ALPHA_I;
1794         }
1795     }
1796 
1797   return -1;
1798 }
1799 
1800 const guchar *
gimp_drawable_get_colormap(GimpDrawable * drawable)1801 gimp_drawable_get_colormap (GimpDrawable *drawable)
1802 {
1803   GimpImage *image;
1804 
1805   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
1806 
1807   image = gimp_item_get_image (GIMP_ITEM (drawable));
1808 
1809   return image ? gimp_image_get_colormap (image) : NULL;
1810 }
1811 
1812 void
gimp_drawable_start_paint(GimpDrawable * drawable)1813 gimp_drawable_start_paint (GimpDrawable *drawable)
1814 {
1815   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
1816 
1817   if (drawable->private->paint_count == 0)
1818     {
1819       GeglBuffer *buffer = gimp_drawable_get_buffer (drawable);
1820 
1821       g_return_if_fail (buffer != NULL);
1822       g_return_if_fail (drawable->private->paint_buffer == NULL);
1823       g_return_if_fail (drawable->private->paint_copy_region == NULL);
1824       g_return_if_fail (drawable->private->paint_update_region == NULL);
1825 
1826       drawable->private->paint_buffer = gimp_gegl_buffer_dup (buffer);
1827     }
1828 
1829   drawable->private->paint_count++;
1830 }
1831 
1832 gboolean
gimp_drawable_end_paint(GimpDrawable * drawable)1833 gimp_drawable_end_paint (GimpDrawable *drawable)
1834 {
1835   gboolean result = FALSE;
1836 
1837   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
1838   g_return_val_if_fail (drawable->private->paint_count > 0, FALSE);
1839 
1840   if (drawable->private->paint_count == 1)
1841     {
1842       result = gimp_drawable_flush_paint (drawable);
1843 
1844       g_clear_object (&drawable->private->paint_buffer);
1845     }
1846 
1847   drawable->private->paint_count--;
1848 
1849   return result;
1850 }
1851 
1852 gboolean
gimp_drawable_flush_paint(GimpDrawable * drawable)1853 gimp_drawable_flush_paint (GimpDrawable *drawable)
1854 {
1855   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
1856   g_return_val_if_fail (drawable->private->paint_count > 0, FALSE);
1857 
1858   if (drawable->private->paint_copy_region)
1859     {
1860       GeglBuffer *buffer;
1861       gint        n_rects;
1862       gint        i;
1863 
1864       buffer = GIMP_DRAWABLE_GET_CLASS (drawable)->get_buffer (drawable);
1865 
1866       g_return_val_if_fail (buffer != NULL, FALSE);
1867       g_return_val_if_fail (drawable->private->paint_buffer != NULL, FALSE);
1868 
1869       n_rects = cairo_region_num_rectangles (
1870         drawable->private->paint_copy_region);
1871 
1872       for (i = 0; i < n_rects; i++)
1873         {
1874           GeglRectangle rect;
1875 
1876           cairo_region_get_rectangle (drawable->private->paint_copy_region,
1877                                       i, (cairo_rectangle_int_t *) &rect);
1878 
1879           gimp_gegl_buffer_copy (
1880             drawable->private->paint_buffer, &rect, GEGL_ABYSS_NONE,
1881             buffer, NULL);
1882         }
1883 
1884       g_clear_pointer (&drawable->private->paint_copy_region,
1885                        cairo_region_destroy);
1886 
1887       n_rects = cairo_region_num_rectangles (
1888         drawable->private->paint_update_region);
1889 
1890       for (i = 0; i < n_rects; i++)
1891         {
1892           GeglRectangle rect;
1893 
1894           cairo_region_get_rectangle (drawable->private->paint_update_region,
1895                                       i, (cairo_rectangle_int_t *) &rect);
1896 
1897           g_signal_emit (drawable, gimp_drawable_signals[UPDATE], 0,
1898                          rect.x, rect.y, rect.width, rect.height);
1899         }
1900 
1901       g_clear_pointer (&drawable->private->paint_update_region,
1902                        cairo_region_destroy);
1903 
1904       return TRUE;
1905     }
1906 
1907   return FALSE;
1908 }
1909 
1910 gboolean
gimp_drawable_is_painting(GimpDrawable * drawable)1911 gimp_drawable_is_painting (GimpDrawable *drawable)
1912 {
1913   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
1914 
1915   return drawable->private->paint_count > 0;
1916 }
1917