[gimp] app: optimize simple whole-drawable fill/clear
- From: Ell <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: optimize simple whole-drawable fill/clear
- Date: Sun, 2 Dec 2018 08:13:10 +0000 (UTC)
commit dd8268c0a25a8b5df5a06bd9b0d841f4c6915e2a
Author: Ell <ell_se yahoo com>
Date: Sun Dec 2 02:59:24 2018 -0500
app: optimize simple whole-drawable fill/clear
In gimp_drawable_edit_fill(), when filling/clearing the whole
drawable, without any special compositing (i.e., when there's no
selection, the opacity is 100%, and the layer mode is trivial),
fill/clear the drawable's buffer directly, without using an
applicator. This makes such operations much faster, especially in
big images.
app/core/gimpdrawable-edit.c | 179 ++++++++++++++++++++++++++++++++++++++-----
1 file changed, 158 insertions(+), 21 deletions(-)
---
diff --git a/app/core/gimpdrawable-edit.c b/app/core/gimpdrawable-edit.c
index 0cc3f45d67..b6bd153eeb 100644
--- a/app/core/gimpdrawable-edit.c
+++ b/app/core/gimpdrawable-edit.c
@@ -24,14 +24,131 @@
#include "operations/layer-modes/gimp-layer-modes.h"
+#include "gegl/gimp-gegl-loops.h"
+
+#include "gimpchannel.h"
#include "gimpdrawable.h"
#include "gimpdrawable-edit.h"
+#include "gimpdrawableundo.h"
#include "gimpcontext.h"
#include "gimpfilloptions.h"
+#include "gimpimage.h"
+#include "gimpimage-undo.h"
+#include "gimppattern.h"
+#include "gimptempbuf.h"
#include "gimp-intl.h"
+/* local function prototypes */
+
+static gboolean gimp_drawable_edit_can_fill_direct (GimpDrawable *drawable,
+ GimpFillOptions *options);
+static void gimp_drawable_edit_fill_direct (GimpDrawable *drawable,
+ GimpFillOptions *options,
+ const gchar *undo_desc);
+
+
+/* private functions */
+
+static gboolean
+gimp_drawable_edit_can_fill_direct (GimpDrawable *drawable,
+ GimpFillOptions *options)
+{
+ GimpImage *image;
+ GimpContext *context;
+ gdouble opacity;
+ GimpLayerMode mode;
+ GimpLayerCompositeMode composite_mode;
+
+ image = gimp_item_get_image (GIMP_ITEM (drawable));
+ context = GIMP_CONTEXT (options);
+ opacity = gimp_context_get_opacity (context);
+ mode = gimp_context_get_paint_mode (context);
+ composite_mode = gimp_layer_mode_get_paint_composite_mode (mode);
+
+ if (gimp_channel_is_empty (gimp_image_get_mask (image)) &&
+ opacity == GIMP_OPACITY_OPAQUE &&
+ gimp_layer_mode_is_trivial (mode) &&
+ (gimp_layer_mode_is_subtractive (mode) ||
+ (gimp_layer_mode_get_included_region (mode, composite_mode) &
+ GIMP_LAYER_COMPOSITE_REGION_SOURCE)))
+ {
+ gboolean source_has_alpha = FALSE;
+
+ if (gimp_fill_options_get_style (options) == GIMP_FILL_STYLE_PATTERN &&
+ ! gimp_layer_mode_is_subtractive (mode))
+ {
+ GimpPattern *pattern;
+ const Babl *format;
+
+ pattern = gimp_context_get_pattern (context);
+ format = gimp_temp_buf_get_format (gimp_pattern_get_mask (pattern));
+
+ source_has_alpha = babl_format_has_alpha (format);
+ }
+
+ return ! source_has_alpha;
+ }
+
+ return FALSE;
+}
+
+static void
+gimp_drawable_edit_fill_direct (GimpDrawable *drawable,
+ GimpFillOptions *options,
+ const gchar *undo_desc)
+{
+ GeglBuffer *buffer;
+ GimpImage *image;
+ GimpContext *context;
+ GimpDrawableUndo *undo;
+ gdouble opacity;
+ GimpLayerMode mode;
+ GimpLayerMode composite_mode;
+ gint width;
+ gint height;
+
+ buffer = gimp_drawable_get_buffer (drawable);
+ image = gimp_item_get_image (GIMP_ITEM (drawable));
+ context = GIMP_CONTEXT (options);
+ opacity = gimp_context_get_opacity (context);
+ mode = gimp_context_get_paint_mode (context);
+ composite_mode = gimp_layer_mode_get_paint_composite_mode (mode);
+ width = gimp_item_get_width (GIMP_ITEM (drawable));
+ height = gimp_item_get_height (GIMP_ITEM (drawable));
+
+ gimp_drawable_push_undo (drawable, undo_desc,
+ NULL, 0, 0, width, height);
+
+ if (! gimp_layer_mode_is_subtractive (mode))
+ gimp_fill_options_fill_buffer (options, drawable, buffer, 0, 0);
+ else
+ gimp_gegl_clear (buffer, NULL);
+
+ undo = GIMP_DRAWABLE_UNDO (gimp_image_undo_get_fadeable (image));
+
+ if (undo)
+ {
+ undo->paint_mode = mode;
+ undo->blend_space = GIMP_LAYER_COLOR_SPACE_AUTO;
+ undo->composite_space = GIMP_LAYER_COLOR_SPACE_AUTO;
+ undo->composite_mode = composite_mode;
+ undo->opacity = opacity;
+
+ if (! gimp_layer_mode_is_subtractive (mode))
+ {
+ undo->applied_buffer = gegl_buffer_dup (buffer);
+ }
+ else
+ {
+ undo->applied_buffer = gimp_fill_options_create_buffer (
+ options, drawable, GEGL_RECTANGLE (0, 0, width, height), 0, 0);
+ }
+ }
+}
+
+
/* public functions */
void
@@ -63,36 +180,56 @@ gimp_drawable_edit_fill (GimpDrawable *drawable,
GimpFillOptions *options,
const gchar *undo_desc)
{
- GeglBuffer *buffer;
- gint x, y, width, height;
+ gint x, y, width, height;
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
g_return_if_fail (GIMP_IS_FILL_OPTIONS (options));
- if (! gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
- return; /* nothing to do, but the fill succeeded */
-
- buffer = gimp_fill_options_create_buffer (options, drawable,
- GEGL_RECTANGLE (0, 0,
- width, height),
- -x, -y);
+ if (! gimp_item_mask_intersect (GIMP_ITEM (drawable),
+ &x, &y, &width, &height))
+ {
+ return; /* nothing to do, but the fill succeeded */
+ }
if (! undo_desc)
undo_desc = gimp_fill_options_get_undo_desc (options);
- gimp_drawable_apply_buffer (drawable, buffer,
- GEGL_RECTANGLE (0, 0, width, height),
- TRUE, undo_desc,
- gimp_context_get_opacity (GIMP_CONTEXT (options)),
- gimp_context_get_paint_mode (GIMP_CONTEXT (options)),
- GIMP_LAYER_COLOR_SPACE_AUTO,
- GIMP_LAYER_COLOR_SPACE_AUTO,
- gimp_layer_mode_get_paint_composite_mode (
- gimp_context_get_paint_mode (GIMP_CONTEXT (options))),
- NULL, x, y);
-
- g_object_unref (buffer);
+ /* check if we can fill the drawable's buffer directly */
+ if (gimp_drawable_edit_can_fill_direct (drawable, options))
+ {
+ gimp_drawable_edit_fill_direct (drawable, options, undo_desc);
+ }
+ else
+ {
+ GeglBuffer *buffer;
+ GimpContext *context;
+ gdouble opacity;
+ GimpLayerMode mode;
+ GimpLayerMode composite_mode;
+
+ context = GIMP_CONTEXT (options);
+ opacity = gimp_context_get_opacity (context);
+ mode = gimp_context_get_paint_mode (context);
+ composite_mode = gimp_layer_mode_get_paint_composite_mode (mode);
+
+ buffer = gimp_fill_options_create_buffer (options, drawable,
+ GEGL_RECTANGLE (0, 0,
+ width, height),
+ -x, -y);
+
+ gimp_drawable_apply_buffer (drawable, buffer,
+ GEGL_RECTANGLE (0, 0, width, height),
+ TRUE, undo_desc,
+ opacity,
+ mode,
+ GIMP_LAYER_COLOR_SPACE_AUTO,
+ GIMP_LAYER_COLOR_SPACE_AUTO,
+ composite_mode,
+ NULL, x, y);
+
+ g_object_unref (buffer);
+ }
gimp_drawable_update (drawable, x, y, width, height);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]