[gimp/gimp-attributes-wip: 141/148] app: increasing paint stroke speed



commit e5569c653e42122ea63db193856b1777383339ed
Author: Hartmut Kuhse <hk_priv gmx de>
Date:   Fri Jan 30 21:45:33 2015 +0100

    app: increasing paint stroke speed

 app/paint/gimppaintcore-loops.c |  353 +++++++++++++++++++++++++++++++++++++++
 app/paint/gimppaintcore-loops.h |   18 ++
 app/paint/gimppaintcore.c       |   81 ++++++----
 3 files changed, 420 insertions(+), 32 deletions(-)
---
diff --git a/app/paint/gimppaintcore-loops.c b/app/paint/gimppaintcore-loops.c
index a9c0dcb..a2266d1 100644
--- a/app/paint/gimppaintcore-loops.c
+++ b/app/paint/gimppaintcore-loops.c
@@ -27,6 +27,356 @@
 #include "operations/gimplayermodefunctions.h"
 
 void
+combine_paint_canvas_buffer (const GimpTempBuf   *paint_mask,
+                             GimpTempBuf         *paint_buf,
+                             GeglBuffer          *src_buffer,
+                             GeglBuffer          *dst_buffer,
+                             GeglBuffer          *mask_buffer,
+                             gint                 mask_x_offset,
+                             gint                 mask_y_offset,
+                             GeglBuffer          *canvas_buffer,
+                             gint                 x_offset,
+                             gint                 y_offset,
+                             gfloat               opacity,
+                             gboolean             stipple,
+                             gint                 p_mask_x_offset,
+                             gint                 p_mask_y_offset,
+                             gboolean             linear_mode,
+                             GimpLayerModeEffects paint_mode)
+{
+  GeglRectangle       roi;
+  GeglBufferIterator *iter;
+  GeglRectangle       mask_roi;
+  GeglRectangle       process_roi;
+  const Babl         *iterator_format;
+
+  const gint  mask_stride       = gimp_temp_buf_get_width (paint_mask);
+  const gint  mask_start_offset = mask_y_offset * mask_stride + mask_x_offset;
+  const Babl *mask_format       = gimp_temp_buf_get_format (paint_mask);
+
+  const guint paint_stride      = gimp_temp_buf_get_width (paint_buf);
+  gfloat     *paint_data        = (gfloat *) gimp_temp_buf_get_data (paint_buf);
+
+  const guint blend_stride      = gimp_temp_buf_get_width (paint_buf);
+  gfloat     *blend_data        = (gfloat *) gimp_temp_buf_get_data (paint_buf);
+
+  GimpLayerModeFunction apply_func = get_layer_mode_function (paint_mode);
+
+  if (linear_mode)
+    iterator_format = babl_format ("RGBA float");
+  else
+    iterator_format = babl_format ("R'G'B'A float");
+
+  roi.x = x_offset;
+  roi.y = y_offset;
+  roi.width  = gimp_temp_buf_get_width (paint_mask) - mask_x_offset;
+  roi.height = gimp_temp_buf_get_height (paint_mask) - mask_y_offset;
+
+  mask_roi.x = roi.x + p_mask_x_offset;
+  mask_roi.y = roi.y + p_mask_y_offset;
+  mask_roi.width  = roi.width;
+  mask_roi.height = roi.height;
+
+  g_return_if_fail (gimp_temp_buf_get_format (paint_buf) == iterator_format);
+
+//  g_print ("combine_paint_mask_to_canvas_mask: %d, %d, %d, %d\n", roi.x, roi.y, roi.width, roi.height);
+  iter = gegl_buffer_iterator_new (canvas_buffer, &roi, 0,
+                                   babl_format ("Y float"),
+                                   GEGL_ACCESS_READWRITE, GEGL_ABYSS_NONE);
+
+  gegl_buffer_iterator_add (iter, dst_buffer, &roi, 0,
+                            iterator_format,
+                            GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE);
+
+  gegl_buffer_iterator_add (iter, src_buffer, &roi, 0,
+                            iterator_format,
+                            GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
+
+  if (mask_buffer)
+    {
+      gegl_buffer_iterator_add (iter, mask_buffer, &mask_roi, 0,
+                                babl_format ("Y float"),
+                                GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
+    }
+
+  if (paint_mask != NULL)
+    {
+      if (stipple)
+        {
+          if (mask_format == babl_format ("Y u8"))
+            {
+              const guint8 *mask_data = (const guint8 *) gimp_temp_buf_get_data (paint_mask);
+              mask_data += mask_start_offset;
+
+              while (gegl_buffer_iterator_next (iter))
+                {
+                  gfloat *out_pixel = (gfloat *)iter->data[0];
+                  int iy, ix;
+                  gfloat *bout_pixel   = (gfloat *)iter->data[1];
+                  gfloat *bin_pixel    = (gfloat *)iter->data[2];
+                  gfloat *bmask_pixel  = NULL;
+                  gfloat *bpaint_pixel = blend_data + ((iter->roi[0].y - roi.y) * blend_stride + 
iter->roi[0].x - roi.x) * 4;
+
+                  if (mask_buffer)
+                    bmask_pixel  = (gfloat *)iter->data[3];
+
+                  process_roi.x = iter->roi[1].x;
+                  process_roi.width  = iter->roi[1].width;
+                  process_roi.height = 1;
+
+
+                  for (iy = 0; iy < iter->roi[0].height; iy++)
+                    {
+                      int mask_offset = (iy + iter->roi[0].y - roi.y) * mask_stride + iter->roi[0].x - roi.x;
+                      const guint8 *mask_pixel = &mask_data[mask_offset];
+                      int paint_offset = (iy + iter->roi[0].y - roi.y) * paint_stride + iter->roi[0].x - 
roi.x;
+                      float *paint_pixel = &paint_data[paint_offset * 4];
+
+                      for (ix = 0; ix < iter->roi[0].width; ix++)
+                        {
+                          out_pixel[0] += (1.0 - out_pixel[0]) * (*mask_pixel / 255.0f) * opacity;
+                          paint_pixel[3] *= *out_pixel;
+
+                          paint_pixel  += 4;
+                          mask_pixel += 1;
+                          out_pixel  += 1;
+                        }
+                      {
+                        process_roi.y = iter->roi[1].y + iy;
+
+                        (*apply_func) (bin_pixel,
+                            bpaint_pixel,
+                            bmask_pixel,
+                            bout_pixel,
+                            opacity,
+                            iter->roi[1].width,
+                            &process_roi,
+                            0);
+
+                        bin_pixel    += iter->roi[1].width * 4;
+                        bout_pixel   += iter->roi[1].width * 4;
+                        if (mask_buffer)
+                          bmask_pixel  += iter->roi[1].width;
+                        bpaint_pixel += blend_stride * 4;
+                      }
+
+                    }
+                }
+            }
+          else if (mask_format == babl_format ("Y float"))
+            {
+              const gfloat *mask_data = (const gfloat *) gimp_temp_buf_get_data (paint_mask);
+              mask_data += mask_start_offset;
+
+              while (gegl_buffer_iterator_next (iter))
+                {
+                  gfloat *out_pixel = (gfloat *)iter->data[0];
+                  int iy, ix;
+                  gfloat *bout_pixel   = (gfloat *)iter->data[1];
+                  gfloat *bin_pixel    = (gfloat *)iter->data[2];
+                  gfloat *bmask_pixel  = NULL;
+                  gfloat *bpaint_pixel = blend_data + ((iter->roi[0].y - roi.y) * blend_stride + 
iter->roi[0].x - roi.x) * 4;
+
+                  if (mask_buffer)
+                    bmask_pixel  = (gfloat *)iter->data[3];
+
+                  process_roi.x = iter->roi[1].x;
+                  process_roi.width  = iter->roi[1].width;
+                  process_roi.height = 1;
+
+
+                  for (iy = 0; iy < iter->roi[0].height; iy++)
+                    {
+                      int mask_offset  = (iy + iter->roi[0].y - roi.y) * mask_stride + iter->roi[0].x - 
roi.x;
+                      int paint_offset = (iy + iter->roi[0].y - roi.y) * paint_stride + iter->roi[0].x - 
roi.x;
+                      const gfloat *mask_pixel = &mask_data[mask_offset];
+                      float *paint_pixel = &paint_data[paint_offset * 4];
+
+                      for (ix = 0; ix < iter->roi[0].width; ix++)
+                        {
+                          out_pixel[0] += (1.0 - out_pixel[0]) * (*mask_pixel) * opacity;
+                          paint_pixel[3] *= *out_pixel;
+
+                          paint_pixel  += 4;
+                          mask_pixel += 1;
+                          out_pixel  += 1;
+                        }
+                      {
+                        process_roi.y = iter->roi[1].y + iy;
+
+                        (*apply_func) (bin_pixel,
+                            bpaint_pixel,
+                            bmask_pixel,
+                            bout_pixel,
+                            opacity,
+                            iter->roi[1].width,
+                            &process_roi,
+                            0);
+
+                        bin_pixel    += iter->roi[1].width * 4;
+                        bout_pixel   += iter->roi[1].width * 4;
+                        if (mask_buffer)
+                          bmask_pixel  += iter->roi[1].width;
+                        bpaint_pixel += blend_stride * 4;
+                      }
+                    }
+                }
+            }
+          else
+            {
+              g_warning("Mask format not supported: %s", babl_get_name (mask_format));
+            }
+        }
+      else
+        {
+          if (mask_format == babl_format ("Y u8"))
+            {
+              const guint8 *mask_data = (const guint8 *) gimp_temp_buf_get_data (paint_mask);
+              mask_data += mask_start_offset;
+
+              while (gegl_buffer_iterator_next (iter))
+                {
+                  gfloat *out_pixel = (gfloat *)iter->data[0];
+                  int iy, ix;
+                  gfloat *bout_pixel   = (gfloat *)iter->data[1];
+                  gfloat *bin_pixel    = (gfloat *)iter->data[2];
+                  gfloat *bmask_pixel  = NULL;
+                  gfloat *bpaint_pixel = blend_data + ((iter->roi[0].y - roi.y) * blend_stride + 
iter->roi[0].x - roi.x) * 4;
+
+                  if (mask_buffer)
+                    bmask_pixel  = (gfloat *)iter->data[3];
+
+                  process_roi.x = iter->roi[1].x;
+                  process_roi.width  = iter->roi[1].width;
+                  process_roi.height = 1;
+
+                  for (iy = 0; iy < iter->roi[0].height; iy++)
+                    {
+                      int mask_offset = (iy + iter->roi[0].y - roi.y) * mask_stride + iter->roi[0].x - roi.x;
+                      const guint8 *mask_pixel = &mask_data[mask_offset];
+                      int paint_offset = (iy + iter->roi[0].y - roi.y) * paint_stride + iter->roi[0].x - 
roi.x;
+                      float *paint_pixel = &paint_data[paint_offset * 4];
+
+                      for (ix = 0; ix < iter->roi[0].width; ix++)
+                        {
+                          if (opacity > out_pixel[0])
+                            out_pixel[0] += (opacity - out_pixel[0]) * (*mask_pixel / 255.0f) * opacity;
+
+                          paint_pixel[3] *= *out_pixel;
+
+                          paint_pixel  += 4;
+                          mask_pixel += 1;
+                          out_pixel  += 1;
+                        }
+                      {
+                        process_roi.y = iter->roi[1].y + iy;
+
+                        (*apply_func) (bin_pixel,
+                            bpaint_pixel,
+                            bmask_pixel,
+                            bout_pixel,
+                            opacity,
+                            iter->roi[1].width,
+                            &process_roi,
+                            0);
+
+                        bin_pixel    += iter->roi[1].width * 4;
+                        bout_pixel   += iter->roi[1].width * 4;
+                        if (mask_buffer)
+                          bmask_pixel  += iter->roi[1].width;
+                        bpaint_pixel += blend_stride * 4;
+                      }
+                    }
+                }
+            }
+          else if (mask_format == babl_format ("Y float"))
+            {
+              const gfloat *mask_data = (const gfloat *) gimp_temp_buf_get_data (paint_mask);
+              mask_data += mask_start_offset;
+
+              while (gegl_buffer_iterator_next (iter))
+                {
+                  gfloat *out_pixel = (gfloat *)iter->data[0];
+                  int iy, ix;
+                  gfloat *bout_pixel   = (gfloat *)iter->data[1];
+                  gfloat *bin_pixel    = (gfloat *)iter->data[2];
+                  gfloat *bmask_pixel  = NULL;
+                  gfloat *bpaint_pixel = blend_data + ((iter->roi[0].y - roi.y) * blend_stride + 
iter->roi[0].x - roi.x) * 4;
+
+                  if (mask_buffer)
+                    bmask_pixel  = (gfloat *)iter->data[3];
+
+                  process_roi.x = iter->roi[1].x;
+                  process_roi.width  = iter->roi[1].width;
+                  process_roi.height = 1;
+
+
+                  for (iy = 0; iy < iter->roi[0].height; iy++)
+                    {
+                      int mask_offset = (iy + iter->roi[0].y - roi.y) * mask_stride + iter->roi[0].x - roi.x;
+                      const gfloat *mask_pixel = &mask_data[mask_offset];
+                      int paint_offset = (iy + iter->roi[0].y - roi.y) * paint_stride + iter->roi[0].x - 
roi.x;
+                      float *paint_pixel = &paint_data[paint_offset * 4];
+
+                      for (ix = 0; ix < iter->roi[0].width; ix++)
+                        {
+                          if (opacity > out_pixel[0])
+                            out_pixel[0] += (opacity - out_pixel[0]) * (*mask_pixel) * opacity;
+
+                          paint_pixel[3] *= *out_pixel;
+
+                          paint_pixel  += 4;
+                          mask_pixel += 1;
+                          out_pixel  += 1;
+                        }
+                      {
+                        process_roi.y = iter->roi[1].y + iy;
+
+                        (*apply_func) (bin_pixel,
+                            bpaint_pixel,
+                            bmask_pixel,
+                            bout_pixel,
+                            opacity,
+                            iter->roi[1].width,
+                            &process_roi,
+                            0);
+
+                        bin_pixel    += iter->roi[1].width * 4;
+                        bout_pixel   += iter->roi[1].width * 4;
+                        if (mask_buffer)
+                          bmask_pixel  += iter->roi[1].width;
+                        bpaint_pixel += blend_stride * 4;
+                      }
+                    }
+                }
+            }
+          else
+            {
+              g_warning("Mask format not supported: %s", babl_get_name (mask_format));
+            }
+        }
+    }
+  else
+    {
+      canvas_buffer_to_paint_buf_alpha (paint_buf,
+                                        canvas_buffer,
+                                        x_offset,
+                                        y_offset);
+      do_layer_blend (src_buffer,
+                      dst_buffer,
+                      paint_buf,
+                      mask_buffer,
+                      opacity,
+                      x_offset,
+                      y_offset,
+                      mask_x_offset,
+                      mask_y_offset,
+                      linear_mode,
+                      paint_mode);
+    }
+}
+
+void
 combine_paint_mask_to_canvas_mask (const GimpTempBuf *paint_mask,
                                    gint               mask_x_offset,
                                    gint               mask_y_offset,
@@ -48,6 +398,7 @@ combine_paint_mask_to_canvas_mask (const GimpTempBuf *paint_mask,
   roi.width  = gimp_temp_buf_get_width (paint_mask) - mask_x_offset;
   roi.height = gimp_temp_buf_get_height (paint_mask) - mask_y_offset;
 
+//  g_print ("combine_paint_mask_to_canvas_mask: %d, %d, %d, %d\n", roi.x, roi.y, roi.width, roi.height);
   iter = gegl_buffer_iterator_new (canvas_buffer, &roi, 0,
                                    babl_format ("Y float"),
                                    GEGL_ACCESS_READWRITE, GEGL_ABYSS_NONE);
@@ -188,6 +539,8 @@ canvas_buffer_to_paint_buf_alpha (GimpTempBuf  *paint_buf,
   roi.width  = gimp_temp_buf_get_width (paint_buf);
   roi.height = gimp_temp_buf_get_height (paint_buf);
 
+//  g_print ("canvas_buffer_to_paint_buf_alpha: %d, %d, %d, %d\n", roi.x, roi.y, roi.width, roi.height);
+
   iter = gegl_buffer_iterator_new (canvas_buffer, &roi, 0,
                                    babl_format ("Y float"),
                                    GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
diff --git a/app/paint/gimppaintcore-loops.h b/app/paint/gimppaintcore-loops.h
index e8ceafa..154ce55 100644
--- a/app/paint/gimppaintcore-loops.h
+++ b/app/paint/gimppaintcore-loops.h
@@ -15,6 +15,24 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+void
+combine_paint_canvas_buffer             (const GimpTempBuf   *paint_mask,
+                                         GimpTempBuf         *paint_buf,
+                                         GeglBuffer          *src_buffer,
+                                         GeglBuffer          *dst_buffer,
+                                         GeglBuffer          *mask_buffer,
+                                         gint                 mask_x_offset,
+                                         gint                 mask_y_offset,
+                                         GeglBuffer          *canvas_buffer,
+                                         gint                 x_offset,
+                                         gint                 y_offset,
+                                         gfloat               opacity,
+                                         gboolean             stipple,
+                                         gint                 p_mask_x_offset,
+                                         gint                 p_mask_y_offset,
+                                         gboolean             linear_mode,
+                                         GimpLayerModeEffects paint_mode);
+
 void combine_paint_mask_to_canvas_mask  (const GimpTempBuf *paint_mask,
                                          gint               mask_x_offset,
                                          gint               mask_y_offset,
diff --git a/app/paint/gimppaintcore.c b/app/paint/gimppaintcore.c
index 87e1258..07ebebe 100644
--- a/app/paint/gimppaintcore.c
+++ b/app/paint/gimppaintcore.c
@@ -900,27 +900,44 @@ gimp_paint_core_paste (GimpPaintCore            *core,
           /* This step is skipped by the ink tool, which writes
            * directly to canvas_buffer
            */
-          if (paint_mask != NULL)
-            {
-              /* Mix paint mask and canvas_buffer */
-              combine_paint_mask_to_canvas_mask (paint_mask,
-                                                 paint_mask_offset_x,
-                                                 paint_mask_offset_y,
-                                                 core->canvas_buffer,
-                                                 core->paint_buffer_x,
-                                                 core->paint_buffer_y,
-                                                 paint_opacity,
-                                                 GIMP_IS_AIRBRUSH (core));
-            }
-
-          /* Write canvas_buffer to paint_buf */
-          canvas_buffer_to_paint_buf_alpha (paint_buf,
-                                            core->canvas_buffer,
-                                            core->paint_buffer_x,
-                                            core->paint_buffer_y);
-
-          /* undo buf -> paint_buf -> dest_buffer */
           src_buffer = core->undo_buffer;
+          combine_paint_canvas_buffer             (paint_mask,
+                                                   paint_buf,
+                                                   src_buffer,
+                                                   dest_buffer,
+                                                   core->mask_buffer,
+                                                   paint_mask_offset_x,
+                                                   paint_mask_offset_y,
+                                                   core->canvas_buffer,
+                                                   core->paint_buffer_x,
+                                                   core->paint_buffer_y,
+                                                   paint_opacity,
+                                                   GIMP_IS_AIRBRUSH (core),
+                                                   core->mask_x_offset,
+                                                   core->mask_y_offset,
+                                                   core->linear_mode,
+                                                   paint_mode);
+//          if (paint_mask != NULL)
+//            {
+//              /* Mix paint mask and canvas_buffer */
+//              combine_paint_mask_to_canvas_mask (paint_mask,
+//                                                 paint_mask_offset_x,
+//                                                 paint_mask_offset_y,
+//                                                 core->canvas_buffer,
+//                                                 core->paint_buffer_x,
+//                                                 core->paint_buffer_y,
+//                                                 paint_opacity,
+//                                                 GIMP_IS_AIRBRUSH (core));
+//            }
+//
+//          /* Write canvas_buffer to paint_buf */
+//          canvas_buffer_to_paint_buf_alpha (paint_buf,
+//                                            core->canvas_buffer,
+//                                            core->paint_buffer_x,
+//                                            core->paint_buffer_y);
+//
+          /* undo buf -> paint_buf -> dest_buffer */
+//          src_buffer = core->undo_buffer;
         }
       else
         {
@@ -935,19 +952,19 @@ gimp_paint_core_paste (GimpPaintCore            *core,
 
           /* dest_buffer -> paint_buf -> dest_buffer */
           src_buffer = dest_buffer;
-        }
 
-      do_layer_blend (src_buffer,
-                      dest_buffer,
-                      paint_buf,
-                      core->mask_buffer,
-                      image_opacity,
-                      core->paint_buffer_x,
-                      core->paint_buffer_y,
-                      core->mask_x_offset,
-                      core->mask_y_offset,
-                      core->linear_mode,
-                      paint_mode);
+          do_layer_blend (src_buffer,
+                          dest_buffer,
+                          paint_buf,
+                          core->mask_buffer,
+                          image_opacity,
+                          core->paint_buffer_x,
+                          core->paint_buffer_y,
+                          core->mask_x_offset,
+                          core->mask_y_offset,
+                          core->linear_mode,
+                          paint_mode);
+        }
 
       if (core->comp_buffer)
         {


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