[gimp] app: move bottom-layer special casing to GimpOperationLayerMode
- From: N/A <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: move bottom-layer special casing to GimpOperationLayerMode
- Date: Tue, 8 Aug 2017 19:42:29 +0000 (UTC)
commit 3635cf04ab69bafb76d7583da804f580f2d5fbf3
Author: Ell <ell_se yahoo com>
Date: Fri Apr 21 19:42:04 2017 -0400
app: move bottom-layer special casing to GimpOperationLayerMode
GimpFilter's is_last_node field only reflects the item's position
within the parent stack. When a layer is contained in a pass-
through group, it can be the last layer of the group, while not
being the last layer in the graph as a whole (paticularly, if
there are visible layers below the group). In fact, when we have
nested pass-through groups, whether or not a layer is the last
node depends on which group we're considering as the root (since
we exclude the backdrop from the group's projection, resulting in
different graphs for different groups).
Instead of rolling our own graph traversal, just move the relevant
logic to GimpOperationLayerMode, and let GEGL do the work for us.
At processing time, we can tell if we're the last node by checking
if we have any input.
For this to work, GimpOperationLayerMode's process() function needs
to have control over what's going on. Replace the derived op
classes, which override process(), with a call to the layer mode's
function (as per gimp_layer_mode_get_function()) in
GimpOperationLayerMode's process() function. (Well, actually, this
commit keeps the ops around, and just hacks around them in
gimp_layer_mode_get_operation(), because laziness :P)
Keep using the layer's is_last_node property to do the invalidation.
app/core/gimplayer.c | 22 +---
app/operations/layer-modes/gimp-layer-modes.c | 46 ++++---
app/operations/layer-modes/gimp-layer-modes.h | 2 +
.../layer-modes/gimpoperationlayermode.c | 162 +++++++++++++++++---
.../layer-modes/gimpoperationlayermode.h | 3 +-
5 files changed, 178 insertions(+), 57 deletions(-)
---
diff --git a/app/core/gimplayer.c b/app/core/gimplayer.c
index d608611..a9b97b9 100644
--- a/app/core/gimplayer.c
+++ b/app/core/gimplayer.c
@@ -668,24 +668,10 @@ gimp_layer_update_mode_node (GimpLayer *layer)
}
else
{
- if (gimp_filter_get_is_last_node (GIMP_FILTER (layer)))
- {
- if (layer->mode != GIMP_LAYER_MODE_DISSOLVE)
- visible_mode = GIMP_LAYER_MODE_NORMAL_LEGACY;
- else
- visible_mode = GIMP_LAYER_MODE_DISSOLVE;
-
- visible_blend_space = GIMP_LAYER_COLOR_SPACE_AUTO;
- visible_composite_space = GIMP_LAYER_COLOR_SPACE_AUTO;
- visible_composite_mode = GIMP_LAYER_COMPOSITE_AUTO;
- }
- else
- {
- visible_mode = layer->mode;
- visible_blend_space = layer->blend_space;
- visible_composite_space = layer->composite_space;
- visible_composite_mode = layer->composite_mode;
- }
+ visible_mode = layer->mode;
+ visible_blend_space = layer->blend_space;
+ visible_composite_space = layer->composite_space;
+ visible_composite_mode = layer->composite_mode;
}
gimp_gegl_mode_node_set_mode (mode_node,
diff --git a/app/operations/layer-modes/gimp-layer-modes.c b/app/operations/layer-modes/gimp-layer-modes.c
index e1fd152..efaee4d 100644
--- a/app/operations/layer-modes/gimp-layer-modes.c
+++ b/app/operations/layer-modes/gimp-layer-modes.c
@@ -60,15 +60,16 @@ typedef struct _GimpLayerModeInfo GimpLayerModeInfo;
struct _GimpLayerModeInfo
{
- GimpLayerMode layer_mode;
- const gchar *op_name;
- GimpLayerModeFunc function;
- GimpLayerModeFlags flags;
- GimpLayerModeContext context;
- GimpLayerCompositeMode paint_composite_mode;
- GimpLayerCompositeMode composite_mode;
- GimpLayerColorSpace composite_space;
- GimpLayerColorSpace blend_space;
+ GimpLayerMode layer_mode;
+ const gchar *op_name;
+ GimpLayerModeFunc function;
+ GimpLayerModeFlags flags;
+ GimpLayerModeContext context;
+ GimpLayerCompositeMode paint_composite_mode;
+ GimpLayerCompositeMode composite_mode;
+ GimpLayerColorSpace composite_space;
+ GimpLayerColorSpace blend_space;
+ GimpLayerCompositeRegion affected_region;
};
@@ -98,7 +99,8 @@ static const GimpLayerModeInfo layer_mode_infos[] =
GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE,
.context = GIMP_LAYER_MODE_CONTEXT_ALL,
.paint_composite_mode = GIMP_LAYER_COMPOSITE_SRC_OVER,
- .composite_mode = GIMP_LAYER_COMPOSITE_SRC_OVER
+ .composite_mode = GIMP_LAYER_COMPOSITE_SRC_OVER,
+ .affected_region = GIMP_LAYER_COMPOSITE_REGION_SOURCE
},
{ GIMP_LAYER_MODE_BEHIND_LEGACY,
@@ -869,7 +871,8 @@ static const GimpLayerModeInfo layer_mode_infos[] =
.context = GIMP_LAYER_MODE_CONTEXT_FADE,
.paint_composite_mode = GIMP_LAYER_COMPOSITE_SRC_OVER,
.composite_mode = GIMP_LAYER_COMPOSITE_SRC_OVER,
- .composite_space = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR
+ .composite_space = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
+ .affected_region = GIMP_LAYER_COMPOSITE_REGION_DESTINATION
},
{ GIMP_LAYER_MODE_ANTI_ERASE,
@@ -880,7 +883,8 @@ static const GimpLayerModeInfo layer_mode_infos[] =
GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE,
.context = GIMP_LAYER_MODE_CONTEXT_FADE,
.paint_composite_mode = GIMP_LAYER_COMPOSITE_SRC_OVER,
- .composite_mode = GIMP_LAYER_COMPOSITE_SRC_OVER
+ .composite_mode = GIMP_LAYER_COMPOSITE_SRC_OVER,
+ .affected_region = GIMP_LAYER_COMPOSITE_REGION_SOURCE
}
};
@@ -1276,12 +1280,7 @@ gimp_layer_mode_get_paint_composite_mode (GimpLayerMode mode)
const gchar *
gimp_layer_mode_get_operation (GimpLayerMode mode)
{
- const GimpLayerModeInfo *info = gimp_layer_mode_info (mode);
-
- if (! info)
- return "gimp:layer-mode";
-
- return info->op_name;
+ return "gimp:layer-mode";
}
GimpLayerModeFunc
@@ -1461,6 +1460,17 @@ gimp_layer_mode_get_format (GimpLayerMode mode,
}
GimpLayerCompositeRegion
+gimp_layer_mode_get_affected_region (GimpLayerMode mode)
+{
+ const GimpLayerModeInfo *info = gimp_layer_mode_info (mode);
+
+ if (! info)
+ return GIMP_LAYER_COMPOSITE_REGION_INTERSECTION;
+
+ return info->affected_region;
+}
+
+GimpLayerCompositeRegion
gimp_layer_mode_get_included_region (GimpLayerMode mode,
GimpLayerCompositeMode composite_mode)
{
diff --git a/app/operations/layer-modes/gimp-layer-modes.h b/app/operations/layer-modes/gimp-layer-modes.h
index 3661a93..a8463cd 100644
--- a/app/operations/layer-modes/gimp-layer-modes.h
+++ b/app/operations/layer-modes/gimp-layer-modes.h
@@ -62,6 +62,8 @@ const Babl * gimp_layer_mode_get_format (GimpLayer
GimpLayerColorSpace blend_space,
const Babl
*preferred_format);
+GimpLayerCompositeRegion gimp_layer_mode_get_affected_region (GimpLayerMode mode);
+
GimpLayerCompositeRegion gimp_layer_mode_get_included_region (GimpLayerMode mode,
GimpLayerCompositeMode
composite_mode);
diff --git a/app/operations/layer-modes/gimpoperationlayermode.c
b/app/operations/layer-modes/gimpoperationlayermode.c
index 75768a0..513705f 100644
--- a/app/operations/layer-modes/gimpoperationlayermode.c
+++ b/app/operations/layer-modes/gimpoperationlayermode.c
@@ -76,14 +76,24 @@ static void gimp_operation_layer_mode_get_property (GObject *
guint property_id,
GValue *value,
GParamSpec *pspec);
-
+
static void gimp_operation_layer_mode_prepare (GeglOperation *operation);
-static gboolean gimp_operation_layer_mode_process (GeglOperation *operation,
+static gboolean
+ gimp_operation_layer_mode_parent_process (GeglOperation *operation,
GeglOperationContext *context,
const gchar *output_prop,
const GeglRectangle *result,
gint level);
+static gboolean gimp_operation_layer_mode_process (GeglOperation *operation,
+ void *in,
+ void *layer,
+ void *mask,
+ void *out,
+ glong samples,
+ const GeglRectangle *roi,
+ gint level);
+
static GimpLayerCompositeRegion
gimp_operation_layer_mode_real_get_affected_region (GimpOperationLayerMode *layer_mode);
@@ -155,6 +165,15 @@ static inline void composite_func_src_atop_sse2 (gfloat *in,
gint samples);
#endif
+static gboolean process_layer_only (GeglOperation *operation,
+ void *in,
+ void *layer,
+ void *mask,
+ void *out,
+ glong samples,
+ const GeglRectangle *roi,
+ gint level);
+
G_DEFINE_TYPE (GimpOperationLayerMode, gimp_operation_layer_mode,
GEGL_TYPE_OPERATION_POINT_COMPOSER3)
@@ -193,8 +212,8 @@ gimp_operation_layer_mode_class_init (GimpOperationLayerModeClass *klass)
object_class->get_property = gimp_operation_layer_mode_get_property;
operation_class->prepare = gimp_operation_layer_mode_prepare;
- operation_class->process = gimp_operation_layer_mode_process;
- point_composer3_class->process = gimp_operation_layer_mode_process_pixels;
+ operation_class->process = gimp_operation_layer_mode_parent_process;
+ point_composer3_class->process = gimp_operation_layer_mode_process;
klass->get_affected_region = gimp_operation_layer_mode_real_get_affected_region;
@@ -352,15 +371,42 @@ static void
gimp_operation_layer_mode_prepare (GeglOperation *operation)
{
GimpOperationLayerMode *self = GIMP_OPERATION_LAYER_MODE (operation);
- const Babl *in_format;
+ const GeglRectangle *input_extent;
+ const Babl *preferred_format;
const Babl *format;
- in_format = gegl_operation_get_source_format (operation, "input");
+ self->func = gimp_layer_mode_get_function (self->layer_mode);
+
+ input_extent = gegl_operation_source_get_bounding_box (operation, "input");
+
+ /* if the input pad has data, work as usual. */
+ if (input_extent && ! gegl_rectangle_is_empty (input_extent))
+ {
+ self->is_last_node = FALSE;
+
+ preferred_format = gegl_operation_get_source_format (operation, "input");
+ }
+ /* otherwise, we're the last node (corresponding to the bottom layer).
+ * in this case, we render the layer (as if) using src-over mode.
+ */
+ else
+ {
+ self->is_last_node = TRUE;
+
+ /* if the layer mode doesn't affect the source, use a shortcut
+ * function that only applies the opacity/mask to the layer.
+ */
+ if (! (gimp_layer_mode_get_affected_region (self->layer_mode) &
+ GIMP_LAYER_COMPOSITE_REGION_SOURCE))
+ self->func = process_layer_only;
- format = gimp_layer_mode_get_format (self->layer_mode,
- self->composite_space,
- self->blend_space,
- in_format);
+ preferred_format = gegl_operation_get_source_format (operation, "aux");
+ }
+
+ format = gimp_layer_mode_get_format (self->layer_mode,
+ self->composite_space,
+ self->blend_space,
+ preferred_format);
gegl_operation_set_format (operation, "input", format);
gegl_operation_set_format (operation, "output", format);
@@ -369,11 +415,11 @@ gimp_operation_layer_mode_prepare (GeglOperation *operation)
}
static gboolean
-gimp_operation_layer_mode_process (GeglOperation *operation,
- GeglOperationContext *context,
- const gchar *output_prop,
- const GeglRectangle *result,
- gint level)
+gimp_operation_layer_mode_parent_process (GeglOperation *operation,
+ GeglOperationContext *context,
+ const gchar *output_prop,
+ const GeglRectangle *result,
+ gint level)
{
GimpOperationLayerMode *point = GIMP_OPERATION_LAYER_MODE (operation);
GObject *input;
@@ -403,19 +449,28 @@ gimp_operation_layer_mode_process (GeglOperation *operation,
gegl_buffer_get_extent (GEGL_BUFFER (aux)),
result);
- included_region = gimp_layer_mode_get_included_region (point->layer_mode,
- point->composite_mode);
+ if (point->is_last_node)
+ {
+ included_region = GIMP_LAYER_COMPOSITE_REGION_SOURCE;
+ }
+ else
+ {
+ included_region = gimp_layer_mode_get_included_region (point->layer_mode,
+ point->composite_mode);
+ }
/* if there's no 'input' ... */
if (! has_input)
{
- /* ... and there's 'aux', and the composite mode includes it ... */
+ /* ... and there's 'aux', and the composite mode includes it (or we're
+ * the last node) ...
+ */
if (has_aux && (included_region & GIMP_LAYER_COMPOSITE_REGION_SOURCE))
{
GimpLayerCompositeRegion affected_region;
affected_region =
- gimp_operation_layer_mode_get_affected_region (point);
+ gimp_layer_mode_get_affected_region (point->layer_mode);
/* ... and the op doesn't otherwise affect 'aux', or changes its
* alpha ...
@@ -452,7 +507,7 @@ gimp_operation_layer_mode_process (GeglOperation *operation,
GimpLayerCompositeRegion affected_region;
affected_region =
- gimp_operation_layer_mode_get_affected_region (point);
+ gimp_layer_mode_get_affected_region (point->layer_mode);
/* ... and the op doesn't otherwise affect 'input' ... */
if (! (affected_region & GIMP_LAYER_COMPOSITE_REGION_DESTINATION))
@@ -497,6 +552,43 @@ gimp_operation_layer_mode_process (GeglOperation *operation,
level);
}
+static gboolean
+gimp_operation_layer_mode_process (GeglOperation *operation,
+ void *in,
+ void *layer,
+ void *mask,
+ void *out,
+ glong samples,
+ const GeglRectangle *roi,
+ gint level)
+{
+ GimpOperationLayerMode *point = GIMP_OPERATION_LAYER_MODE (operation);
+
+ /* if we're not the last node, or we're using the opacity/mask shortcut
+ * function, forward directly to the real process function.
+ */
+ if (! point->is_last_node || point->func == process_layer_only)
+ {
+ return point->func (operation, in, layer, mask, out, samples, roi, level);
+ }
+ /* otherwise, switch the composite mode temporarily to src-over, before
+ * handing processing over to the real process function.
+ */
+ else
+ {
+ GimpLayerCompositeMode composite_mode = point->composite_mode;
+ gboolean result;
+
+ point->composite_mode = GIMP_LAYER_COMPOSITE_SRC_OVER;
+
+ result = point->func (operation, in, layer, mask, out, samples, roi, level);
+
+ point->composite_mode = composite_mode;
+
+ return result;
+ }
+}
+
static GimpLayerCompositeRegion
gimp_operation_layer_mode_real_get_affected_region (GimpOperationLayerMode *layer_mode)
{
@@ -548,6 +640,36 @@ gimp_operation_layer_mode_process_pixels (GeglOperation *operation,
return TRUE;
}
+static gboolean
+process_layer_only (GeglOperation *operation,
+ void *in_buf,
+ void *layer_buf,
+ void *mask_buf,
+ void *out_buf,
+ glong samples,
+ const GeglRectangle *roi,
+ gint level)
+{
+ gfloat *out = out_buf;
+ gfloat *layer = layer_buf;
+ gfloat *mask = mask_buf;
+ gfloat opacity = GIMP_OPERATION_LAYER_MODE (operation)->opacity;
+
+ while (samples--)
+ {
+ memcpy (out, layer, 3 * sizeof (gfloat));
+
+ out[ALPHA] = layer[ALPHA] * opacity;
+ if (mask)
+ out[ALPHA] *= *mask++;
+
+ layer += 4;
+ out += 4;
+ }
+
+ return TRUE;
+}
+
/* non-subtractive compositing functions. these functions expect comp[ALPHA]
* to be the same as layer[ALPHA]. when in[ALPHA] or layer[ALPHA] are zero,
diff --git a/app/operations/layer-modes/gimpoperationlayermode.h
b/app/operations/layer-modes/gimpoperationlayermode.h
index 4544f87..c2b044f 100644
--- a/app/operations/layer-modes/gimpoperationlayermode.h
+++ b/app/operations/layer-modes/gimpoperationlayermode.h
@@ -58,7 +58,8 @@ struct _GimpOperationLayerMode
GimpLayerColorSpace blend_space;
GimpLayerColorSpace composite_space;
GimpLayerCompositeMode composite_mode;
- GimpBlendFunc blend_func;
+ GimpLayerModeFunc func;
+ gboolean is_last_node;
};
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]