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 ©_x,
598 ©_y,
599 ©_width,
600 ©_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