[gimp/goat-invasion] app: implement active, affected components in GEGL



commit bd6bea7366a6e2c41c123f6a562682651bf6aea7
Author: Michael Natterer <mitch gimp org>
Date:   Wed Apr 25 23:23:31 2012 +0200

    app: implement active, affected components in GEGL
    
    Add GimpOperationMaskComponents, enum GimpComponentMask, and image and
    drawable infrastructure to get the right mask, and plug the mask
    operation into gimp_gegl_create_apply_buffer_node().

 app/core/core-enums.c                  |   35 +++++++
 app/core/core-enums.h                  |   18 ++++
 app/core/gimpchannel.c                 |   10 ++
 app/core/gimpdrawable-combine.c        |   10 ++-
 app/core/gimpdrawable.c                |   16 +++
 app/core/gimpdrawable.h                |    2 +
 app/core/gimpimage.c                   |   31 ++++++
 app/core/gimpimage.h                   |    1 +
 app/core/gimplayer.c                   |   16 +++
 app/gegl/Makefile.am                   |    2 +
 app/gegl/gimp-gegl-nodes.c             |   46 +++++++--
 app/gegl/gimp-gegl-nodes.h             |    3 +-
 app/gegl/gimp-gegl-types.h             |    1 +
 app/gegl/gimp-gegl.c                   |    2 +
 app/gegl/gimpoperationmaskcomponents.c |  173 ++++++++++++++++++++++++++++++++
 app/gegl/gimpoperationmaskcomponents.h |   53 ++++++++++
 16 files changed, 408 insertions(+), 11 deletions(-)
---
diff --git a/app/core/core-enums.c b/app/core/core-enums.c
index e4391d5..e787d68 100644
--- a/app/core/core-enums.c
+++ b/app/core/core-enums.c
@@ -9,6 +9,41 @@
 
 /* enumerations from "./core-enums.h" */
 GType
+gimp_component_mask_get_type (void)
+{
+  static const GFlagsValue values[] =
+  {
+    { GIMP_COMPONENT_RED, "GIMP_COMPONENT_RED", "red" },
+    { GIMP_COMPONENT_GREEN, "GIMP_COMPONENT_GREEN", "green" },
+    { GIMP_COMPONENT_BLUE, "GIMP_COMPONENT_BLUE", "blue" },
+    { GIMP_COMPONENT_ALPHA, "GIMP_COMPONENT_ALPHA", "alpha" },
+    { GIMP_COMPONENT_ALL, "GIMP_COMPONENT_ALL", "all" },
+    { 0, NULL, NULL }
+  };
+
+  static const GimpFlagsDesc descs[] =
+  {
+    { GIMP_COMPONENT_RED, "GIMP_COMPONENT_RED", NULL },
+    { GIMP_COMPONENT_GREEN, "GIMP_COMPONENT_GREEN", NULL },
+    { GIMP_COMPONENT_BLUE, "GIMP_COMPONENT_BLUE", NULL },
+    { GIMP_COMPONENT_ALPHA, "GIMP_COMPONENT_ALPHA", NULL },
+    { GIMP_COMPONENT_ALL, "GIMP_COMPONENT_ALL", NULL },
+    { 0, NULL, NULL }
+  };
+
+  static GType type = 0;
+
+  if (G_UNLIKELY (! type))
+    {
+      type = g_flags_register_static ("GimpComponentMask", values);
+      gimp_type_set_translation_context (type, "component-mask");
+      gimp_flags_set_value_descriptions (type, descs);
+    }
+
+  return type;
+}
+
+GType
 gimp_container_policy_get_type (void)
 {
   static const GEnumValue values[] =
diff --git a/app/core/core-enums.h b/app/core/core-enums.h
index a46608a..fbca549 100644
--- a/app/core/core-enums.h
+++ b/app/core/core-enums.h
@@ -36,6 +36,24 @@
  */
 
 
+#define GIMP_TYPE_COMPONENT_MASK (gimp_component_mask_get_type ())
+
+GType gimp_component_mask_get_type (void) G_GNUC_CONST;
+
+typedef enum /*< pdb-skip >*/
+{
+  GIMP_COMPONENT_RED   = 1 << 0,
+  GIMP_COMPONENT_GREEN = 1 << 1,
+  GIMP_COMPONENT_BLUE  = 1 << 2,
+  GIMP_COMPONENT_ALPHA = 1 << 3,
+
+  GIMP_COMPONENT_ALL = (GIMP_COMPONENT_RED   |
+                        GIMP_COMPONENT_GREEN |
+                        GIMP_COMPONENT_BLUE  |
+                        GIMP_COMPONENT_ALPHA)
+} GimpComponentMask;
+
+
 #define GIMP_TYPE_CONTAINER_POLICY (gimp_container_policy_get_type ())
 
 GType gimp_container_policy_get_type (void) G_GNUC_CONST;
diff --git a/app/core/gimpchannel.c b/app/core/gimpchannel.c
index 9d39520..fa78ccf 100644
--- a/app/core/gimpchannel.c
+++ b/app/core/gimpchannel.c
@@ -132,6 +132,8 @@ static void       gimp_channel_to_selection  (GimpItem          *item,
 static void gimp_channel_invalidate_boundary   (GimpDrawable       *drawable);
 static void gimp_channel_get_active_components (const GimpDrawable *drawable,
                                                 gboolean           *active);
+static GimpComponentMask
+                  gimp_channel_get_active_mask (const GimpDrawable *drawable);
 
 static void      gimp_channel_apply_buffer   (GimpDrawable        *drawable,
                                               GeglBuffer          *buffer,
@@ -284,6 +286,7 @@ gimp_channel_class_init (GimpChannelClass *klass)
 
   drawable_class->invalidate_boundary   = gimp_channel_invalidate_boundary;
   drawable_class->get_active_components = gimp_channel_get_active_components;
+  drawable_class->get_active_mask       = gimp_channel_get_active_mask;
   drawable_class->apply_buffer          = gimp_channel_apply_buffer;
   drawable_class->replace_buffer        = gimp_channel_replace_buffer;
   drawable_class->project_region        = gimp_channel_project_region;
@@ -802,6 +805,13 @@ gimp_channel_get_active_components (const GimpDrawable *drawable,
   active[ALPHA_G] = FALSE;
 }
 
+static GimpComponentMask
+gimp_channel_get_active_mask (const GimpDrawable *drawable)
+{
+  /*  Return all, because that skips the component mask op when painting  */
+  return GIMP_COMPONENT_ALL;
+}
+
 static void
 gimp_channel_apply_buffer (GimpDrawable         *drawable,
                            GeglBuffer           *buffer,
diff --git a/app/core/gimpdrawable-combine.c b/app/core/gimpdrawable-combine.c
index 36dcf81..fc290fe 100644
--- a/app/core/gimpdrawable-combine.c
+++ b/app/core/gimpdrawable-combine.c
@@ -125,14 +125,17 @@ gimp_drawable_real_apply_buffer (GimpDrawable         *drawable,
 
   if (gimp_use_gegl (image->gimp) && ! dest_buffer)
     {
-      GeglBuffer *mask_buffer = NULL;
-      GeglNode   *apply;
+      GeglBuffer        *mask_buffer = NULL;
+      GeglNode          *apply;
+      GimpComponentMask  affect;
 
       if (mask)
         mask_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask));
 
       dest_buffer = gimp_drawable_get_buffer (drawable);
 
+      affect = gimp_drawable_get_active_mask (drawable);
+
       apply = gimp_gegl_create_apply_buffer_node (buffer,
                                                   base_x - buffer_region->x,
                                                   base_y - buffer_region->y,
@@ -144,7 +147,8 @@ gimp_drawable_real_apply_buffer (GimpDrawable         *drawable,
                                                   -offset_x,
                                                   -offset_y,
                                                   opacity,
-                                                  mode);
+                                                  mode,
+                                                  affect);
 
       gimp_apply_operation (base_buffer, NULL, NULL,
                             apply,
diff --git a/app/core/gimpdrawable.c b/app/core/gimpdrawable.c
index fc48a14..1f6c161 100644
--- a/app/core/gimpdrawable.c
+++ b/app/core/gimpdrawable.c
@@ -234,6 +234,7 @@ gimp_drawable_class_init (GimpDrawableClass *klass)
   klass->estimate_memsize            = gimp_drawable_real_estimate_memsize;
   klass->invalidate_boundary         = NULL;
   klass->get_active_components       = NULL;
+  klass->get_active_mask             = NULL;
   klass->convert_type                = gimp_drawable_real_convert_type;
   klass->apply_buffer                = gimp_drawable_real_apply_buffer;
   klass->replace_buffer              = gimp_drawable_real_replace_buffer;
@@ -1156,6 +1157,21 @@ gimp_drawable_get_active_components (const GimpDrawable *drawable,
     drawable_class->get_active_components (drawable, active);
 }
 
+GimpComponentMask
+gimp_drawable_get_active_mask (const GimpDrawable *drawable)
+{
+  GimpDrawableClass *drawable_class;
+
+  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), 0);
+
+  drawable_class = GIMP_DRAWABLE_GET_CLASS (drawable);
+
+  if (drawable_class->get_active_mask)
+    return drawable_class->get_active_mask (drawable);
+
+  return 0;
+}
+
 void
 gimp_drawable_convert_type (GimpDrawable      *drawable,
                             GimpImage         *dest_image,
diff --git a/app/core/gimpdrawable.h b/app/core/gimpdrawable.h
index 06dfd2b..be8d039 100644
--- a/app/core/gimpdrawable.h
+++ b/app/core/gimpdrawable.h
@@ -59,6 +59,7 @@ struct _GimpDrawableClass
   void          (* invalidate_boundary)   (GimpDrawable         *drawable);
   void          (* get_active_components) (const GimpDrawable   *drawable,
                                            gboolean             *active);
+  GimpComponentMask (* get_active_mask)   (const GimpDrawable   *drawable);
   void          (* convert_type)          (GimpDrawable         *drawable,
                                            GimpImage            *dest_image,
                                            GimpImageBaseType     new_base_type,
@@ -140,6 +141,7 @@ void            gimp_drawable_alpha_changed      (GimpDrawable       *drawable);
 void           gimp_drawable_invalidate_boundary (GimpDrawable       *drawable);
 void         gimp_drawable_get_active_components (const GimpDrawable *drawable,
                                                   gboolean           *active);
+GimpComponentMask gimp_drawable_get_active_mask  (const GimpDrawable *drawable);
 
 void            gimp_drawable_convert_type       (GimpDrawable       *drawable,
                                                   GimpImage          *dest_image,
diff --git a/app/core/gimpimage.c b/app/core/gimpimage.c
index 64032d8..a1e05cd 100644
--- a/app/core/gimpimage.c
+++ b/app/core/gimpimage.c
@@ -2224,6 +2224,37 @@ gimp_image_get_active_array (const GimpImage *image,
     components[i] = private->active[i];
 }
 
+GimpComponentMask
+gimp_image_get_active_mask (const GimpImage *image)
+{
+  GimpImagePrivate  *private;
+  GimpComponentMask  mask = 0;
+
+  g_return_val_if_fail (GIMP_IS_IMAGE (image), 0);
+
+  private = GIMP_IMAGE_GET_PRIVATE (image);
+
+  switch (gimp_image_base_type (image))
+    {
+    case GIMP_RGB:
+      mask |= (private->active[RED])   ? GIMP_COMPONENT_RED   : 0;
+      mask |= (private->active[GREEN]) ? GIMP_COMPONENT_GREEN : 0;
+      mask |= (private->active[BLUE])  ? GIMP_COMPONENT_BLUE  : 0;
+      mask |= (private->active[ALPHA]) ? GIMP_COMPONENT_ALPHA : 0;
+      break;
+
+    case GIMP_GRAY:
+    case GIMP_INDEXED:
+      mask |= (private->active[GRAY])  ? GIMP_COMPONENT_RED   : 0;
+      mask |= (private->active[GRAY])  ? GIMP_COMPONENT_GREEN : 0;
+      mask |= (private->active[GRAY])  ? GIMP_COMPONENT_BLUE  : 0;
+      mask |= (private->active[ALPHA]) ? GIMP_COMPONENT_ALPHA : 0;
+      break;
+    }
+
+  return mask;
+}
+
 void
 gimp_image_set_component_visible (GimpImage       *image,
                                   GimpChannelType  channel,
diff --git a/app/core/gimpimage.h b/app/core/gimpimage.h
index edccd8b..43b4534 100644
--- a/app/core/gimpimage.h
+++ b/app/core/gimpimage.h
@@ -202,6 +202,7 @@ gboolean        gimp_image_get_component_active  (const GimpImage    *image,
                                                   GimpChannelType     type);
 void            gimp_image_get_active_array      (const GimpImage    *image,
                                                   gboolean           *components);
+GimpComponentMask gimp_image_get_active_mask     (const GimpImage    *image);
 
 void            gimp_image_set_component_visible (GimpImage          *image,
                                                   GimpChannelType     type,
diff --git a/app/core/gimplayer.c b/app/core/gimplayer.c
index ff8f433..e02d168 100644
--- a/app/core/gimplayer.c
+++ b/app/core/gimplayer.c
@@ -163,6 +163,8 @@ static void    gimp_layer_convert_type          (GimpDrawable       *drawable,
 static void    gimp_layer_invalidate_boundary   (GimpDrawable       *drawable);
 static void    gimp_layer_get_active_components (const GimpDrawable *drawable,
                                                  gboolean           *active);
+static GimpComponentMask
+               gimp_layer_get_active_mask       (const GimpDrawable *drawable);
 
 static gdouble gimp_layer_get_opacity_at        (GimpPickable       *pickable,
                                                  gint                x,
@@ -305,6 +307,7 @@ gimp_layer_class_init (GimpLayerClass *klass)
   drawable_class->convert_type          = gimp_layer_convert_type;
   drawable_class->invalidate_boundary   = gimp_layer_invalidate_boundary;
   drawable_class->get_active_components = gimp_layer_get_active_components;
+  drawable_class->get_active_mask       = gimp_layer_get_active_mask;
   drawable_class->project_region        = gimp_layer_project_region;
 
   klass->opacity_changed              = NULL;
@@ -999,6 +1002,19 @@ gimp_layer_get_active_components (const GimpDrawable *drawable,
     active[babl_format_get_n_components (format) - 1] = FALSE;
 }
 
+static GimpComponentMask
+gimp_layer_get_active_mask (const GimpDrawable *drawable)
+{
+  GimpLayer         *layer = GIMP_LAYER (drawable);
+  GimpImage         *image = gimp_item_get_image (GIMP_ITEM (drawable));
+  GimpComponentMask  mask  = gimp_image_get_active_mask (image);
+
+  if (gimp_drawable_has_alpha (drawable) && layer->lock_alpha)
+    mask &= ~GIMP_COMPONENT_ALPHA;
+
+  return mask;
+}
+
 static gdouble
 gimp_layer_get_opacity_at (GimpPickable *pickable,
                            gint          x,
diff --git a/app/gegl/Makefile.am b/app/gegl/Makefile.am
index c63af32..ead06f0 100644
--- a/app/gegl/Makefile.am
+++ b/app/gegl/Makefile.am
@@ -70,6 +70,8 @@ libappgegl_a_sources = \
 	gimpoperationgrow.h			\
 	gimpoperationhistogramsink.c		\
 	gimpoperationhistogramsink.h		\
+	gimpoperationmaskcomponents.c		\
+	gimpoperationmaskcomponents.h		\
 	gimpoperationsetalpha.c			\
 	gimpoperationsetalpha.h			\
 	gimpoperationshapeburst.c		\
diff --git a/app/gegl/gimp-gegl-nodes.c b/app/gegl/gimp-gegl-nodes.c
index 63e63ee..3eba02b 100644
--- a/app/gegl/gimp-gegl-nodes.c
+++ b/app/gegl/gimp-gegl-nodes.c
@@ -116,7 +116,8 @@ gimp_gegl_create_apply_buffer_node (GeglBuffer           *buffer,
                                     gint                  mask_offset_x,
                                     gint                  mask_offset_y,
                                     gdouble               opacity,
-                                    GimpLayerModeEffects  mode)
+                                    GimpLayerModeEffects  mode,
+                                    GimpComponentMask     affect)
 
 {
   GeglNode *node;
@@ -131,10 +132,6 @@ gimp_gegl_create_apply_buffer_node (GeglBuffer           *buffer,
 
   node = gegl_node_new ();
 
-  buffer_source = gimp_gegl_add_buffer_source (node, buffer,
-                                               buffer_offset_x,
-                                               buffer_offset_y);
-
   input = gegl_node_get_input_proxy (node, "input");
 
   if (src_offset_x != 0 || src_offset_y != 0)
@@ -169,6 +166,21 @@ gimp_gegl_create_apply_buffer_node (GeglBuffer           *buffer,
       output = translate;
     }
 
+  if (affect == 0)
+    {
+      /*  nothing to do, pass through  */
+
+      gegl_node_connect_to (input,  "output",
+                            output, "input");
+
+      return;
+    }
+
+  buffer_source = gimp_gegl_add_buffer_source (node, buffer,
+                                               buffer_offset_x,
+                                               buffer_offset_y);
+
+
   if (mask)
     mask_source = gimp_gegl_add_buffer_source (node, mask,
                                                mask_offset_x,
@@ -235,8 +247,28 @@ gimp_gegl_create_apply_buffer_node (GeglBuffer           *buffer,
 
   gegl_node_connect_to (input,     "output",
                         mode_node, "input");
-  gegl_node_connect_to (mode_node, "output",
-                        output,    "input");
+
+  if (affect == GIMP_COMPONENT_ALL)
+    {
+      gegl_node_connect_to (mode_node, "output",
+                            output,    "input");
+    }
+  else
+    {
+      GeglNode *affect_node;
+
+      affect_node = gegl_node_new_child (node,
+                                         "operation", "gimp:mask-components",
+                                         "mask",      affect,
+                                         NULL);
+
+      gegl_node_connect_to (input,       "output",
+                            affect_node, "input");
+      gegl_node_connect_to (mode_node,   "output",
+                            affect_node, "aux");
+      gegl_node_connect_to (affect_node, "output",
+                            output,      "input");
+    }
 
   return node;
 }
diff --git a/app/gegl/gimp-gegl-nodes.h b/app/gegl/gimp-gegl-nodes.h
index ecff41f..8fcbd0f 100644
--- a/app/gegl/gimp-gegl-nodes.h
+++ b/app/gegl/gimp-gegl-nodes.h
@@ -38,7 +38,8 @@ GeglNode * gimp_gegl_create_apply_buffer_node  (GeglBuffer           *buffer,
                                                 gint                  mask_offset_x,
                                                 gint                  mask_offset_y,
                                                 gdouble               opacity,
-                                                GimpLayerModeEffects  mode);
+                                                GimpLayerModeEffects  mode,
+                                                GimpComponentMask     affect);
 
 GeglNode * gimp_gegl_add_buffer_source         (GeglNode             *parent,
                                                 GeglBuffer           *buffer,
diff --git a/app/gegl/gimp-gegl-types.h b/app/gegl/gimp-gegl-types.h
index 85dc530..dc6e708 100644
--- a/app/gegl/gimp-gegl-types.h
+++ b/app/gegl/gimp-gegl-types.h
@@ -33,6 +33,7 @@ typedef struct _GimpOperationCageTransform      GimpOperationCageTransform;
 typedef struct _GimpOperationEqualize           GimpOperationEqualize;
 typedef struct _GimpOperationGrow               GimpOperationGrow;
 typedef struct _GimpOperationHistogramSink      GimpOperationHistogramSink;
+typedef struct _GimpOperationMaskComponents     GimpOperationMaskComponents;
 typedef struct _GimpOperationSetAlpha           GimpOperationSetAlpha;
 typedef struct _GimpOperationShapeburst         GimpOperationShapeburst;
 typedef struct _GimpOperationShrink             GimpOperationShrink;
diff --git a/app/gegl/gimp-gegl.c b/app/gegl/gimp-gegl.c
index 8f905d1..b37ec629 100644
--- a/app/gegl/gimp-gegl.c
+++ b/app/gegl/gimp-gegl.c
@@ -39,6 +39,7 @@
 #include "gimpoperationequalize.h"
 #include "gimpoperationgrow.h"
 #include "gimpoperationhistogramsink.h"
+#include "gimpoperationmaskcomponents.h"
 #include "gimpoperationsetalpha.h"
 #include "gimpoperationshapeburst.h"
 #include "gimpoperationshrink.h"
@@ -120,6 +121,7 @@ gimp_gegl_init (Gimp *gimp)
   g_type_class_ref (GIMP_TYPE_OPERATION_EQUALIZE);
   g_type_class_ref (GIMP_TYPE_OPERATION_GROW);
   g_type_class_ref (GIMP_TYPE_OPERATION_HISTOGRAM_SINK);
+  g_type_class_ref (GIMP_TYPE_OPERATION_MASK_COMPONENTS);
   g_type_class_ref (GIMP_TYPE_OPERATION_SET_ALPHA);
   g_type_class_ref (GIMP_TYPE_OPERATION_SHAPEBURST);
   g_type_class_ref (GIMP_TYPE_OPERATION_SHRINK);
diff --git a/app/gegl/gimpoperationmaskcomponents.c b/app/gegl/gimpoperationmaskcomponents.c
new file mode 100644
index 0000000..703e19d
--- /dev/null
+++ b/app/gegl/gimpoperationmaskcomponents.c
@@ -0,0 +1,173 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpoperationmaskcomponents.c
+ * Copyright (C) 2012 Michael Natterer <mitch gimp org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+
+#include "gimp-gegl-types.h"
+
+#include "gimpoperationmaskcomponents.h"
+
+
+enum
+{
+  PROP_0,
+  PROP_MASK
+};
+
+
+static void       gimp_operation_mask_components_get_property (GObject             *object,
+                                                               guint                property_id,
+                                                               GValue              *value,
+                                                               GParamSpec          *pspec);
+static void       gimp_operation_mask_components_set_property (GObject             *object,
+                                                               guint                property_id,
+                                                               const GValue        *value,
+                                                               GParamSpec          *pspec);
+
+static void       gimp_operation_mask_components_prepare      (GeglOperation       *operation);
+static gboolean   gimp_operation_mask_components_process      (GeglOperation       *operation,
+                                                               void                *in_buf,
+                                                               void                *aux_buf,
+                                                               void                *out_buf,
+                                                               glong                samples,
+                                                               const GeglRectangle *roi,
+                                                               gint                 level);
+
+
+G_DEFINE_TYPE (GimpOperationMaskComponents, gimp_operation_mask_components,
+               GEGL_TYPE_OPERATION_POINT_COMPOSER)
+
+#define parent_class gimp_operation_mask_components_parent_class
+
+
+static void
+gimp_operation_mask_components_class_init (GimpOperationMaskComponentsClass *klass)
+{
+  GObjectClass                    *object_class    = G_OBJECT_CLASS (klass);
+  GeglOperationClass              *operation_class = GEGL_OPERATION_CLASS (klass);
+  GeglOperationPointComposerClass *point_class     = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass);
+
+  object_class->set_property = gimp_operation_mask_components_set_property;
+  object_class->get_property = gimp_operation_mask_components_get_property;
+
+  gegl_operation_class_set_keys (operation_class,
+                                 "name",        "gimp:mask-components",
+                                 "categories",  "gimp",
+                                 "description", "Selectively pick components from src or aux",
+                                 NULL);
+
+  operation_class->prepare = gimp_operation_mask_components_prepare;
+
+  point_class->process     = gimp_operation_mask_components_process;
+
+  g_object_class_install_property (object_class, PROP_MASK,
+                                   g_param_spec_flags ("mask",
+                                                       "Mask",
+                                                       "The component mask",
+                                                       GIMP_TYPE_COMPONENT_MASK,
+                                                       GIMP_COMPONENT_ALL,
+                                                       G_PARAM_READWRITE |
+                                                       G_PARAM_CONSTRUCT));
+}
+
+static void
+gimp_operation_mask_components_init (GimpOperationMaskComponents *self)
+{
+}
+
+static void
+gimp_operation_mask_components_get_property (GObject    *object,
+                                             guint       property_id,
+                                             GValue     *value,
+                                             GParamSpec *pspec)
+{
+  GimpOperationMaskComponents *self = GIMP_OPERATION_MASK_COMPONENTS (object);
+
+  switch (property_id)
+    {
+    case PROP_MASK:
+      g_value_set_flags (value, self->mask);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gimp_operation_mask_components_set_property (GObject      *object,
+                                             guint         property_id,
+                                             const GValue *value,
+                                             GParamSpec   *pspec)
+{
+  GimpOperationMaskComponents *self = GIMP_OPERATION_MASK_COMPONENTS (object);
+
+  switch (property_id)
+    {
+    case PROP_MASK:
+      self->mask = g_value_get_flags (value);
+      break;
+
+   default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gimp_operation_mask_components_prepare (GeglOperation *operation)
+{
+  gegl_operation_set_format (operation, "input",  babl_format ("RGBA float"));
+  gegl_operation_set_format (operation, "aux",    babl_format ("RGBA float"));
+  gegl_operation_set_format (operation, "output", babl_format ("RGBA float"));
+}
+
+static gboolean
+gimp_operation_mask_components_process (GeglOperation       *operation,
+                                        void                *in_buf,
+                                        void                *aux_buf,
+                                        void                *out_buf,
+                                        glong                samples,
+                                        const GeglRectangle *roi,
+                                        gint                 level)
+{
+  GimpOperationMaskComponents *self = GIMP_OPERATION_MASK_COMPONENTS (operation);
+  gfloat                      *src  = in_buf;
+  gfloat                      *aux  = aux_buf;
+  gfloat                      *dest = out_buf;
+  GimpComponentMask            mask = self->mask;
+
+  while (samples--)
+    {
+      dest[RED]   = (mask & GIMP_COMPONENT_RED)   ? aux[RED]   : src[RED];
+      dest[GREEN] = (mask & GIMP_COMPONENT_GREEN) ? aux[GREEN] : src[GREEN];
+      dest[BLUE]  = (mask & GIMP_COMPONENT_BLUE)  ? aux[BLUE]  : src[BLUE];
+      dest[ALPHA] = (mask & GIMP_COMPONENT_ALPHA) ? aux[ALPHA] : src[ALPHA];
+
+      src  += 4;
+      aux  += 4;
+      dest += 4;
+    }
+
+  return TRUE;
+}
diff --git a/app/gegl/gimpoperationmaskcomponents.h b/app/gegl/gimpoperationmaskcomponents.h
new file mode 100644
index 0000000..e0d1bc6
--- /dev/null
+++ b/app/gegl/gimpoperationmaskcomponents.h
@@ -0,0 +1,53 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpoperationmaskcomponents.h
+ * Copyright (C) 2012 Michael Natterer <mitch gimp org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_OPERATION_MASK_COMPONENTS_H__
+#define __GIMP_OPERATION_MASK_COMPONENTS_H__
+
+#include <gegl-plugin.h>
+
+
+#define GIMP_TYPE_OPERATION_MASK_COMPONENTS            (gimp_operation_mask_components_get_type ())
+#define GIMP_OPERATION_MASK_COMPONENTS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_OPERATION_MASK_COMPONENTS, GimpOperationMaskComponents))
+#define GIMP_OPERATION_MASK_COMPONENTS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  GIMP_TYPE_OPERATION_MASK_COMPONENTS, GimpOperationMaskComponentsClass))
+#define GIMP_IS_OPERATION_MASK_COMPONENTS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_OPERATION_MASK_COMPONENTS))
+#define GIMP_IS_OPERATION_MASK_COMPONENTS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  GIMP_TYPE_OPERATION_MASK_COMPONENTS))
+#define GIMP_OPERATION_MASK_COMPONENTS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  GIMP_TYPE_OPERATION_MASK_COMPONENTS, GimpOperationMaskComponentsClass))
+
+
+typedef struct _GimpOperationMaskComponentsClass GimpOperationMaskComponentsClass;
+
+struct _GimpOperationMaskComponents
+{
+  GeglOperationPointComposer  parent_instance;
+
+  GimpComponentMask           mask;
+};
+
+struct _GimpOperationMaskComponentsClass
+{
+  GeglOperationPointComposerClass  parent_class;
+};
+
+
+GType   gimp_operation_mask_components_get_type (void) G_GNUC_CONST;
+
+
+#endif /* __GIMP_OPERATION_MASK_COMPONENTS_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]