[gimp] app: in gimppaintcore-loops, add [Temp]CompMask algorithm helper-classes



commit e36847febb936797f9de15e834df3bd0bdeca290
Author: Ell <ell_se yahoo com>
Date:   Tue Feb 12 03:02:22 2019 -0500

    app: in gimppaintcore-loops, add [Temp]CompMask algorithm helper-classes
    
    In gimppaintcore-loops, add a CompMask algorithm helper-class,
    which provides access to the mask buffer used for compositing, to
    be used by the DO_LAYER_BLEND algorithm instead of the image mask
    buffer.
    
    CompMask itself doesn't provide the storage for the mask; this is
    rather the responsibility of the algorithms that use it.  The
    TempCompMask algorithm helper-class provides temporary storage for
    the compositing mask, and can be used by algorithms that need a
    temporary mask.

 app/paint/gimppaintcore-loops.cc | 154 +++++++++++++++++++++++++++++++++++----
 1 file changed, 141 insertions(+), 13 deletions(-)
---
diff --git a/app/paint/gimppaintcore-loops.cc b/app/paint/gimppaintcore-loops.cc
index 2b22b3f655..1fd6ce8fa7 100644
--- a/app/paint/gimppaintcore-loops.cc
+++ b/app/paint/gimppaintcore-loops.cc
@@ -97,9 +97,11 @@ extern "C"
 
 enum
 {
-  ALGORITHM_PAINT_BUF  = 1u << 31,
-  ALGORITHM_PAINT_MASK = 1u << 30,
-  ALGORITHM_STIPPLE    = 1u << 29
+  ALGORITHM_PAINT_BUF      = 1u << 31,
+  ALGORITHM_PAINT_MASK     = 1u << 30,
+  ALGORITHM_STIPPLE        = 1u << 29,
+  ALGORITHM_COMP_MASK      = 1u << 28,
+  ALGORITHM_TEMP_COMP_MASK = 1u << 27
 };
 
 
@@ -607,6 +609,130 @@ struct DispatchStipple
 } static dispatch_stipple;
 
 
+/* CompMask, dispatch_comp_mask(), has_comp_mask(), comp_mask_data():
+ *
+ * An algorithm helper class, providing access to the mask used for
+ * compositing.  When this class is part of the hierarchy, 'DoLayerBlend' uses
+ * this buffer as the mask, instead of the input parameters' 'mask_buffer'.
+ * Algorithms that use the compositing mask should specify
+ * 'dispatch_comp_mask()' as a dependency, and access 'CompMask' members
+ * through their base type/subobject.
+ *
+ * Note that 'CompMask' only provides *access* to the compositing mask, but
+ * doesn't provide its actual *storage*.  This is the responsibility of the
+ * algorithms that use 'CompMask'.  Algorithms that need temporary storage for
+ * the compositing mask can use 'TempCompMask'.
+ *
+ * The 'has_comp_mask()' constexpr function determines if a given algorithm
+ * hierarchy uses the compositing mask.
+ *
+ * The 'comp_mask_data()' function returns a pointer to the compositing mask
+ * data for the current row if the hierarchy uses the compositing mask, or NULL
+ * otherwise.
+ */
+
+template <class Base>
+struct CompMask : Base
+{
+  /* Component type of the compositing mask. */
+  using comp_mask_type = gfloat;
+
+  static constexpr guint filter = Base::filter | ALGORITHM_COMP_MASK;
+
+  using Base::Base;
+
+  template <class Derived>
+  struct State : Base::template State<Derived>
+  {
+    /* Pointer to the compositing mask data for the current row. */
+    comp_mask_type *comp_mask_data;
+  };
+};
+
+static BasicDispatch<CompMask, ALGORITHM_COMP_MASK> dispatch_comp_mask;
+
+template <class Base>
+static constexpr gboolean
+has_comp_mask (const CompMask<Base> *algorithm)
+{
+  return TRUE;
+}
+
+static constexpr gboolean
+has_comp_mask (const AlgorithmBase *algorithm)
+{
+  return FALSE;
+}
+
+template <class Base,
+          class State>
+static gfloat *
+comp_mask_data (const CompMask<Base> *algorithm,
+                State                *state)
+{
+  return state->comp_mask_data;
+}
+
+template <class State>
+static gfloat *
+comp_mask_data (const AlgorithmBase *algorithm,
+                State               *state)
+{
+  return NULL;
+}
+
+
+/* TempCompMask, dispatch_temp_comp_mask():
+ *
+ * An algorithm helper class, providing temporary storage for the compositing
+ * mask.  Algorithms that need a temporary compositing mask should specify
+ * 'dispatch_temp_comp_mask()' as a dependency, which itself includes
+ * 'dispatch_comp_mask()' as a dependency.
+ */
+
+template <class Base>
+struct TempCompMask : Base
+{
+  static constexpr guint filter = Base::filter | ALGORITHM_TEMP_COMP_MASK;
+
+  using Base::Base;
+
+  template <class Derived>
+  using State = typename Base::template State<Derived>;
+
+  template <class Derived>
+  void
+  init_step (const GimpPaintCoreLoopsParams *params,
+             State<Derived>                 *state,
+             GeglBufferIterator             *iter,
+             const GeglRectangle            *roi,
+             const GeglRectangle            *area,
+             const GeglRectangle            *rect) const
+  {
+    Base::init_step (params, state, iter, roi, area, rect);
+
+    state->comp_mask_data = gegl_scratch_new (gfloat, rect->width);
+  }
+
+
+  template <class Derived>
+  void
+  finalize_step (const GimpPaintCoreLoopsParams *params,
+                 State<Derived>                 *state) const
+  {
+    gegl_scratch_free (state->comp_mask_data);
+
+    Base::finalize_step (params, state);
+  }
+};
+
+static BasicDispatch<
+  TempCompMask,
+  ALGORITHM_TEMP_COMP_MASK,
+  decltype (dispatch_comp_mask)
+> dispatch_temp_comp_mask;
+
+
 /* CanvasBufferIterator:
  *
  * An algorithm helper class, providing iterator-access to the canvas buffer.
@@ -1093,11 +1219,6 @@ struct DoLayerBlend : Base
   {
     Base::init (params, state, iter, roi, area);
 
-    GeglRectangle mask_area = *area;
-
-    mask_area.x -= params->mask_offset_x;
-    mask_area.y -= params->mask_offset_y;
-
     state->iterator_base = gegl_buffer_iterator_add (iter, params->dest_buffer,
                                                      area, 0, iterator_format,
                                                      GEGL_ACCESS_WRITE,
@@ -1107,12 +1228,19 @@ struct DoLayerBlend : Base
                               iterator_format,
                               GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
 
-    if (params->mask_buffer)
+    if (! has_comp_mask (this) && params->mask_buffer)
       {
+        GeglRectangle mask_area = *area;
+
+        mask_area.x -= params->mask_offset_x;
+        mask_area.y -= params->mask_offset_y;
+
         gegl_buffer_iterator_add (iter, params->mask_buffer, &mask_area, 0,
                                   babl_format ("Y float"),
                                   GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
       }
+
+    state->mask_pixel = NULL;
   }
 
   template <class Derived>
@@ -1128,13 +1256,12 @@ struct DoLayerBlend : Base
 
     state->out_pixel  = (gfloat *) iter->items[state->iterator_base + 0].data;
     state->in_pixel   = (gfloat *) iter->items[state->iterator_base + 1].data;
-    state->mask_pixel = NULL;
 
     state->paint_pixel = this->paint_data                        +
                          (rect->y - roi->y) * this->paint_stride +
                          (rect->x - roi->x) * 4;
 
-    if (params->mask_buffer)
+    if (! has_comp_mask (this) && params->mask_buffer)
       state->mask_pixel = (gfloat *) iter->items[state->iterator_base + 2].data;
 
     state->process_roi.x      = rect->x;
@@ -1159,7 +1286,8 @@ struct DoLayerBlend : Base
     layer_mode.function ((GeglOperation*) &layer_mode,
                          state->in_pixel,
                          state->paint_pixel,
-                         state->mask_pixel,
+                         has_comp_mask (this) ? comp_mask_data (this, state) :
+                                                state->mask_pixel,
                          state->out_pixel,
                          rect->width,
                          &state->process_roi,
@@ -1167,7 +1295,7 @@ struct DoLayerBlend : Base
 
     state->in_pixel     += rect->width * 4;
     state->out_pixel    += rect->width * 4;
-    if (params->mask_buffer)
+    if (! has_comp_mask (this) && state->mask_pixel)
       state->mask_pixel += rect->width;
     state->paint_pixel  += this->paint_stride;
   }


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