[gimp] app: in gimppaintcore-loops, add MaskBufferIterator algorithm helper-class



commit 44281ce2c47c7d4dfc16fbb9c1bd359993e53571
Author: Ell <ell_se yahoo com>
Date:   Tue Feb 12 05:16:16 2019 -0500

    app: in gimppaintcore-loops, add MaskBufferIterator algorithm helper-class
    
    In gimppaintcore-loops, add a MaskBufferIterator algorithm helper-
    class, which provides read-only iterator access to the mask buffer,
    if one is used.
    
    Use the new class in DoLayerBlend, instead of manually managing the
    mask-buffer iterator.

 app/paint/gimppaintcore-loops.cc | 152 ++++++++++++++++++++++++++++++++-------
 1 file changed, 126 insertions(+), 26 deletions(-)
---
diff --git a/app/paint/gimppaintcore-loops.cc b/app/paint/gimppaintcore-loops.cc
index 1fd6ce8fa7..db0b3282ca 100644
--- a/app/paint/gimppaintcore-loops.cc
+++ b/app/paint/gimppaintcore-loops.cc
@@ -97,11 +97,12 @@ extern "C"
 
 enum
 {
-  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
+  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,
+  ALGORITHM_MASK_BUFFER_ITERATOR = 1u << 26
 };
 
 
@@ -733,6 +734,107 @@ static BasicDispatch<
dispatch_temp_comp_mask;
 
 
+/* MaskBufferIterator, mask_buffer_iterator_dispatch(),
+ * has_mask_buffer_iterator():
+ *
+ * An algorithm helper class, providing read-only iterator-access to the mask
+ * buffer.  Algorithms that iterate over the mask buffer should specify
+ * 'dispatch_mask_buffer_iterator()' as a dependency, and access
+ * 'MaskBufferIterator' members through their base type/subobject.
+ *
+ * The 'has_mask_buffer_iterator()' constexpr function determines if a given
+ * algorithm hierarchy uses has a mask-buffer iterator.
+ *
+ * The 'mask_buffer_iterator()' function returns the index of the mask-buffer
+ * iterator if the hierarchy has one, or -1 otherwise.
+ */
+
+template <class Base>
+struct MaskBufferIterator : Base
+{
+  static constexpr guint filter = Base::filter | ALGORITHM_MASK_BUFFER_ITERATOR;
+
+  static constexpr gint max_n_iterators = Base::max_n_iterators + 1;
+
+  using Base::Base;
+
+  template <class Derived>
+  struct State : Base::template State<Derived>
+  {
+    gint mask_buffer_iterator;
+  };
+
+  template <class Derived>
+  void
+  init (const GimpPaintCoreLoopsParams *params,
+        State<Derived>                 *state,
+        GeglBufferIterator             *iter,
+        const GeglRectangle            *roi,
+        const GeglRectangle            *area) const
+  {
+    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->mask_buffer_iterator = gegl_buffer_iterator_add (
+      iter, params->mask_buffer, &mask_area, 0, babl_format ("Y float"),
+      GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
+  }
+};
+
+struct DispatchMaskBufferIterator
+{
+  static constexpr guint mask = ALGORITHM_MASK_BUFFER_ITERATOR;
+
+  template <class Visitor,
+            class Algorithm>
+  void
+  operator () (Visitor                         visitor,
+               const GimpPaintCoreLoopsParams *params,
+               GimpPaintCoreLoopsAlgorithm     algorithms,
+               identity<Algorithm>             algorithm) const
+  {
+    if (params->mask_buffer)
+      visitor (identity<MaskBufferIterator<Algorithm>> ());
+    else
+      visitor (algorithm);
+  }
+} static dispatch_mask_buffer_iterator;
+
+template <class Base>
+static constexpr gboolean
+has_mask_buffer_iterator (const MaskBufferIterator<Base> *algorithm)
+{
+  return TRUE;
+}
+
+static constexpr gboolean
+has_mask_buffer_iterator (const AlgorithmBase *algorithm)
+{
+  return FALSE;
+}
+
+template <class Base,
+          class State>
+static gint
+mask_buffer_iterator (const MaskBufferIterator<Base> *algorithm,
+                      State                          *state)
+{
+  return state->mask_buffer_iterator;
+}
+
+template <class State>
+static gint
+mask_buffer_iterator (const AlgorithmBase *algorithm,
+                      State               *state)
+{
+  return -1;
+}
+
+
 /* CanvasBufferIterator:
  *
  * An algorithm helper class, providing iterator-access to the canvas buffer.
@@ -1170,7 +1272,7 @@ struct DoLayerBlend : Base
     Base::filter |
     GIMP_PAINT_CORE_LOOPS_ALGORITHM_DO_LAYER_BLEND;
 
-  static constexpr gint max_n_iterators = Base::max_n_iterators + 3;
+  static constexpr gint max_n_iterators = Base::max_n_iterators + 2;
 
   const Babl             *iterator_format;
   GimpOperationLayerMode  layer_mode;
@@ -1227,20 +1329,6 @@ struct DoLayerBlend : Base
     gegl_buffer_iterator_add (iter, params->src_buffer, area, 0,
                               iterator_format,
                               GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
-
-    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>
@@ -1261,8 +1349,11 @@ struct DoLayerBlend : Base
                          (rect->y - roi->y) * this->paint_stride +
                          (rect->x - roi->x) * 4;
 
-    if (! has_comp_mask (this) && params->mask_buffer)
-      state->mask_pixel = (gfloat *) iter->items[state->iterator_base + 2].data;
+    if (! has_comp_mask (this) && has_mask_buffer_iterator (this))
+      {
+        state->mask_pixel =
+          (gfloat *) iter->items[mask_buffer_iterator (this, state)].data;
+      }
 
     state->process_roi.x      = rect->x;
     state->process_roi.width  = rect->width;
@@ -1281,13 +1372,21 @@ struct DoLayerBlend : Base
   {
     Base::process_row (params, state, iter, roi, area, rect, y);
 
+    gfloat *mask_pixel;
+
+    if (has_comp_mask (this))
+      mask_pixel = comp_mask_data (this, state);
+    else if (has_mask_buffer_iterator (this))
+      mask_pixel = state->mask_pixel;
+    else
+      mask_pixel = NULL;
+
     state->process_roi.y = y;
 
     layer_mode.function ((GeglOperation*) &layer_mode,
                          state->in_pixel,
                          state->paint_pixel,
-                         has_comp_mask (this) ? comp_mask_data (this, state) :
-                                                state->mask_pixel,
+                         mask_pixel,
                          state->out_pixel,
                          rect->width,
                          &state->process_roi,
@@ -1295,7 +1394,7 @@ struct DoLayerBlend : Base
 
     state->in_pixel     += rect->width * 4;
     state->out_pixel    += rect->width * 4;
-    if (! has_comp_mask (this) && state->mask_pixel)
+    if (! has_comp_mask (this) && has_mask_buffer_iterator (this))
       state->mask_pixel += rect->width;
     state->paint_pixel  += this->paint_stride;
   }
@@ -1304,7 +1403,8 @@ struct DoLayerBlend : Base
 static AlgorithmDispatch<
   DoLayerBlend,
   GIMP_PAINT_CORE_LOOPS_ALGORITHM_DO_LAYER_BLEND,
-  decltype (dispatch_paint_buf)
+  decltype (dispatch_paint_buf),
+  decltype (dispatch_mask_buffer_iterator)

 dispatch_do_layer_blend;
 


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