[gimp/wip/alxsa/mypaint-brush-v2: 59/66] Connecting new parameters to paint output




commit 6d8ea71d9387576a566341b2abcc874c58995103
Author: Alx Sa <cmyk student gmail com>
Date:   Tue Oct 4 10:43:27 2022 +0000

    Connecting new parameters to paint output

 app/paint/gimpmybrushcore.c    |  37 +++---
 app/paint/gimpmybrushsurface.c | 266 +++++++++++++++++++++++++++++++++++++++--
 2 files changed, 276 insertions(+), 27 deletions(-)
---
diff --git a/app/paint/gimpmybrushcore.c b/app/paint/gimpmybrushcore.c
index c8d6c618ef..9fb2f19da7 100644
--- a/app/paint/gimpmybrushcore.c
+++ b/app/paint/gimpmybrushcore.c
@@ -80,7 +80,10 @@ static void      gimp_mybrush_core_motion         (GimpPaintCore     *paint_core
                                                    GimpDrawable      *drawable,
                                                    GimpPaintOptions  *paint_options,
                                                    GimpSymmetry      *sym,
-                                                   guint32            time);
+                                                   guint32            time,
+                                                   gfloat             view_zoom,
+                                                   gfloat             view_rotation,
+                                                   gfloat             barrel_rotation);
 static void      gimp_mybrush_core_create_brushes (GimpMybrushCore   *mybrush,
                                                    GimpDrawable      *drawable,
                                                    GimpPaintOptions  *paint_options,
@@ -231,12 +234,11 @@ gimp_mybrush_core_paint (GimpPaintCore    *paint_core,
 
     case GIMP_PAINT_STATE_MOTION:
       gimp_mybrush_core_motion (paint_core, drawables->data, paint_options,
-                                sym, time);
+                                sym, time, 1.0f, 0.0f, 0.0f);
       break;
 
     case GIMP_PAINT_STATE_FINISH:
       gimp_symmetry_set_stateful (sym, FALSE);
-      /*mypaint_surface_unref ((MyPaintSurface *) mybrush->private->surface);*/
       mybrush->private->surface = NULL;
 
       g_list_free_full (mybrush->private->brushes,
@@ -251,10 +253,14 @@ gimp_mybrush_core_motion (GimpPaintCore    *paint_core,
                           GimpDrawable     *drawable,
                           GimpPaintOptions *paint_options,
                           GimpSymmetry     *sym,
-                          guint32           time)
+                          guint32           time,
+                          gfloat            view_zoom,
+                          gfloat            view_rotation,
+                          gfloat            barrel_rotation)
 {
   GimpMybrushCore  *mybrush = GIMP_MYBRUSH_CORE (paint_core);
   MyPaintRectangle  rect;
+  MyPaintRectangles rects = {1, &rect};
   GList            *iter;
   gdouble           dt = 0.0;
   gint              off_x, off_y;
@@ -272,7 +278,8 @@ gimp_mybrush_core_motion (GimpPaintCore    *paint_core,
       gimp_mybrush_core_create_brushes (mybrush, drawable, paint_options, sym);
     }
 
-  /*mypaint_surface_begin_atomic ((MyPaintSurface2 *) mybrush->private->surface);*/
+  mypaint_surface_begin_atomic (mypaint_surface2_to_surface (
+                                (MyPaintSurface2 *) mybrush->private->surface));
 
   if (mybrush->private->last_time < 0)
     {
@@ -292,7 +299,7 @@ gimp_mybrush_core_motion (GimpPaintCore    *paint_core,
                                      coords.xtilt,
                                      coords.ytilt,
                                      1.0f, /* Pretend the cursor hasn't moved in a while */
-                                     1.0f, 1.0f, 1.0f);
+                                     view_zoom, view_rotation, barrel_rotation);
         }
 
       dt = 0.015;
@@ -325,22 +332,22 @@ gimp_mybrush_core_motion (GimpPaintCore    *paint_core,
                                  coords.xtilt,
                                  coords.ytilt,
                                  dt,
-                                 1.0f, 1.0f, 1.0f);
+                                 view_zoom, view_rotation, barrel_rotation);
     }
 
   mybrush->private->last_time = time;
 
-  /*mypaint_surface_end_atomic ((MyPaintSurface2 *) mybrush->private->surface,
-                              &rect);*/
+  mypaint_surface2_end_atomic ((MyPaintSurface2 *) mybrush->private->surface,
+                               &rects);
 
-  if (rect.width > 0 && rect.height > 0)
+  if (rects.rectangles[0].width > 0 && rects.rectangles[0].height > 0)
     {
-      paint_core->x1 = MIN (paint_core->x1, rect.x);
-      paint_core->y1 = MIN (paint_core->y1, rect.y);
-      paint_core->x2 = MAX (paint_core->x2, rect.x + rect.width);
-      paint_core->y2 = MAX (paint_core->y2, rect.y + rect.height);
+      paint_core->x1 = MIN (paint_core->x1, rects.rectangles[0].x);
+      paint_core->y1 = MIN (paint_core->y1, rects.rectangles[0].y);
+      paint_core->x2 = MAX (paint_core->x2, rects.rectangles[0].x + rects.rectangles[0].width);
+      paint_core->y2 = MAX (paint_core->y2, rects.rectangles[0].y + rects.rectangles[0].height);
 
-      gimp_drawable_update (drawable, rect.x, rect.y, rect.width, rect.height);
+      gimp_drawable_update (drawable, rects.rectangles[0].x, rects.rectangles[0].y, 
rects.rectangles[0].width, rects.rectangles[0].height);
     }
 }
 
diff --git a/app/paint/gimpmybrushsurface.c b/app/paint/gimpmybrushsurface.c
index 5e4ae76195..7f0b78ac8e 100644
--- a/app/paint/gimpmybrushsurface.c
+++ b/app/paint/gimpmybrushsurface.c
@@ -593,6 +593,153 @@ gimp_mypaint_surface_draw_dab_2 (MyPaintSurface2 *base_surface,
                                 float             paint)
 {
   /* Placeholder - eventually implement here */
+  GimpMybrushSurface2 *surface = (GimpMybrushSurface2 *) base_surface;
+  GeglBufferIterator *iter;
+  GeglRectangle       dabRect;
+  GimpComponentMask   component_mask = surface->component_mask;
+
+  const float one_over_radius2 = 1.0f / (radius * radius);
+  const double angle_rad = angle / 360 * 2 * M_PI;
+  const float cs = cos(angle_rad);
+  const float sn = sin(angle_rad);
+  float normal_mode;
+  float segment1_slope;
+  float segment2_slope;
+  float r_aa_start;
+
+  hardness = CLAMP (hardness, 0.0f, 1.0f);
+  segment1_slope = -(1.0f / hardness - 1.0f);
+  segment2_slope = -hardness / (1.0f - hardness);
+  aspect_ratio = MAX (1.0f, aspect_ratio);
+
+  r_aa_start = radius - 1.0f;
+  r_aa_start = MAX (r_aa_start, 0);
+  r_aa_start = (r_aa_start * r_aa_start) / aspect_ratio;
+
+  normal_mode = opaque * (1.0f - colorize);
+  colorize = opaque * colorize;
+
+  /* FIXME: This should use the real matrix values to trim aspect_ratio dabs */
+  dabRect = calculate_dab_roi (x, y, radius);
+  gegl_rectangle_intersect (&dabRect, &dabRect, gegl_buffer_get_extent (surface->buffer));
+
+  if (dabRect.width <= 0 || dabRect.height <= 0)
+    return 0;
+
+  gegl_rectangle_bounding_box (&surface->dirty, &surface->dirty, &dabRect);
+
+  iter = gegl_buffer_iterator_new (surface->buffer, &dabRect, 0,
+                                   babl_format ("R'G'B'A float"),
+                                   GEGL_BUFFER_READWRITE,
+                                   GEGL_ABYSS_NONE, 2);
+  if (surface->paint_mask)
+    {
+      GeglRectangle mask_roi = dabRect;
+      mask_roi.x -= surface->paint_mask_x;
+      mask_roi.y -= surface->paint_mask_y;
+      gegl_buffer_iterator_add (iter, surface->paint_mask, &mask_roi, 0,
+                                babl_format ("Y float"),
+                                GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
+    }
+
+  while (gegl_buffer_iterator_next (iter))
+    {
+      float *pixel = (float *)iter->items[0].data;
+      float *mask;
+      int iy, ix;
+
+      if (surface->paint_mask)
+        mask = iter->items[1].data;
+      else
+        mask = NULL;
+
+      for (iy = iter->items[0].roi.y; iy < iter->items[0].roi.y + iter->items[0].roi.height; iy++)
+        {
+          for (ix = iter->items[0].roi.x; ix < iter->items[0].roi.x +  iter->items[0].roi.width; ix++)
+            {
+              float rr, base_alpha, alpha, dst_alpha, r, g, b, a;
+              if (radius < 3.0f)
+                rr = calculate_rr_antialiased (ix, iy, x, y, aspect_ratio, sn, cs, one_over_radius2, 
r_aa_start);
+              else
+                rr = calculate_rr (ix, iy, x, y, aspect_ratio, sn, cs, one_over_radius2);
+              base_alpha = calculate_alpha_for_rr (rr, hardness, segment1_slope, segment2_slope);
+              alpha = base_alpha * normal_mode;
+              if (mask)
+                alpha *= *mask;
+              dst_alpha = pixel[ALPHA];
+              /* a = alpha * color_a + dst_alpha * (1.0f - alpha);
+               * which converts to: */
+              a = alpha * (color_a - dst_alpha) + dst_alpha;
+              r = pixel[RED];
+              g = pixel[GREEN];
+              b = pixel[BLUE];
+
+              if (a > 0.0f)
+                {
+                  /* By definition the ratio between each color[] and pixel[] component in a 
non-pre-multipled blend always sums to 1.0f.
+                   * Originally this would have been "(color[n] * alpha * color_a + pixel[n] * dst_alpha * 
(1.0f - alpha)) / a",
+                   * instead we only calculate the cheaper term. */
+                  float src_term = (alpha * color_a) / a;
+                  float dst_term = 1.0f - src_term;
+                  r = color_r * src_term + r * dst_term;
+                  g = color_g * src_term + g * dst_term;
+                  b = color_b * src_term + b * dst_term;
+                }
+
+              if (colorize > 0.0f && base_alpha > 0.0f)
+                {
+                  alpha = base_alpha * colorize;
+                  a = alpha + dst_alpha - alpha * dst_alpha;
+                  if (a > 0.0f)
+                    {
+                      GimpHSL pixel_hsl, out_hsl;
+                      GimpRGB pixel_rgb = {color_r, color_g, color_b};
+                      GimpRGB out_rgb   = {r, g, b};
+                      float src_term = alpha / a;
+                      float dst_term = 1.0f - src_term;
+
+                      gimp_rgb_to_hsl (&pixel_rgb, &pixel_hsl);
+                      gimp_rgb_to_hsl (&out_rgb, &out_hsl);
+
+                      out_hsl.h = pixel_hsl.h;
+                      out_hsl.s = pixel_hsl.s;
+                      gimp_hsl_to_rgb (&out_hsl, &out_rgb);
+
+                      r = (float)out_rgb.r * src_term + r * dst_term;
+                      g = (float)out_rgb.g * src_term + g * dst_term;
+                      b = (float)out_rgb.b * src_term + b * dst_term;
+                    }
+                }
+
+              if (surface->options->no_erasing)
+                a = MAX (a, pixel[ALPHA]);
+
+              if (component_mask != GIMP_COMPONENT_MASK_ALL)
+                {
+                  if (component_mask & GIMP_COMPONENT_MASK_RED)
+                    pixel[RED]   = r;
+                  if (component_mask & GIMP_COMPONENT_MASK_GREEN)
+                    pixel[GREEN] = g;
+                  if (component_mask & GIMP_COMPONENT_MASK_BLUE)
+                    pixel[BLUE]  = b;
+                  if (component_mask & GIMP_COMPONENT_MASK_ALPHA)
+                    pixel[ALPHA] = a;
+                }
+              else
+                {
+                  pixel[RED]   = r;
+                  pixel[GREEN] = g;
+                  pixel[BLUE]  = b;
+                  pixel[ALPHA] = a;
+                }
+
+              pixel += 4;
+              if (mask)
+                mask += 1;
+            }
+        }
+    }
+
   return 1;
 }
 
@@ -636,6 +783,99 @@ gimp_mypaint_surface_get_color_2 (MyPaintSurface2 *base_surface,
                                   float            paint)
 {
   /* Placeholder - eventually implement here */
+  GimpMybrushSurface2 *surface = (GimpMybrushSurface2 *) base_surface;
+  GeglRectangle dabRect;
+
+  if (radius < 1.0f)
+    radius = 1.0f;
+
+  dabRect = calculate_dab_roi (x, y, radius);
+
+  *color_r = 0.0f;
+  *color_g = 0.0f;
+  *color_b = 0.0f;
+  *color_a = 0.0f;
+
+  if (dabRect.width > 0 || dabRect.height > 0)
+  {
+    const float one_over_radius2 = 1.0f / (radius * radius);
+    float sum_weight = 0.0f;
+    float sum_r = 0.0f;
+    float sum_g = 0.0f;
+    float sum_b = 0.0f;
+    float sum_a = 0.0f;
+
+     /* Read in clamp mode to avoid transparency bleeding in at the edges */
+    GeglBufferIterator *iter = gegl_buffer_iterator_new (surface->buffer, &dabRect, 0,
+                                                         babl_format ("R'aG'aB'aA float"),
+                                                         GEGL_BUFFER_READ,
+                                                         GEGL_ABYSS_CLAMP, 2);
+    if (surface->paint_mask)
+      {
+        GeglRectangle mask_roi = dabRect;
+        mask_roi.x -= surface->paint_mask_x;
+        mask_roi.y -= surface->paint_mask_y;
+        gegl_buffer_iterator_add (iter, surface->paint_mask, &mask_roi, 0,
+                                  babl_format ("Y float"),
+                                  GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
+      }
+
+    while (gegl_buffer_iterator_next (iter))
+      {
+        float *pixel = (float *)iter->items[0].data;
+        float *mask;
+        int iy, ix;
+
+        if (surface->paint_mask)
+          mask = iter->items[1].data;
+        else
+          mask = NULL;
+
+        for (iy = iter->items[0].roi.y; iy < iter->items[0].roi.y + iter->items[0].roi.height; iy++)
+          {
+            float yy = (iy + 0.5f - y);
+            for (ix = iter->items[0].roi.x; ix < iter->items[0].roi.x +  iter->items[0].roi.width; ix++)
+              {
+                /* pixel_weight == a standard dab with hardness = 0.5, aspect_ratio = 1.0, and angle = 0.0 */
+                float xx = (ix + 0.5f - x);
+                float rr = (yy * yy + xx * xx) * one_over_radius2;
+                float pixel_weight = 0.0f;
+                if (rr <= 1.0f)
+                  pixel_weight = 1.0f - rr;
+                if (mask)
+                  pixel_weight *= *mask;
+
+                sum_r += pixel_weight * pixel[RED];
+                sum_g += pixel_weight * pixel[GREEN];
+                sum_b += pixel_weight * pixel[BLUE];
+                sum_a += pixel_weight * pixel[ALPHA];
+                sum_weight += pixel_weight;
+
+                pixel += 4;
+                if (mask)
+                  mask += 1;
+              }
+          }
+      }
+
+    if (sum_a > 0.0f && sum_weight > 0.0f)
+      {
+        sum_r /= sum_weight;
+        sum_g /= sum_weight;
+        sum_b /= sum_weight;
+        sum_a /= sum_weight;
+
+        sum_r /= sum_a;
+        sum_g /= sum_a;
+        sum_b /= sum_a;
+
+        /* FIXME: Clamping is wrong because GEGL allows alpha > 1, this should probably re-multipy things */
+        *color_r = CLAMP(sum_r, 0.0f, 1.0f);
+        *color_g = CLAMP(sum_g, 0.0f, 1.0f);
+        *color_b = CLAMP(sum_b, 0.0f, 1.0f);
+        *color_a = CLAMP(sum_a, 0.0f, 1.0f);
+      }
+  }
 
 }
 
@@ -667,10 +907,10 @@ gimp_mypaint_surface_end_atomic_2 (MyPaintSurface2    *base_surface,
 
       for (gint i = 0; i < roi_rects; i++)
         {
-          roi->rectangles[i].x         = 0;
-          roi->rectangles[i].y         = 0;
-          roi->rectangles[i].width     = 0;
-          roi->rectangles[i].height    = 0;
+          roi->rectangles[i].x         = surface->dirty.x;
+          roi->rectangles[i].y         = surface->dirty.y;
+          roi->rectangles[i].width     = surface->dirty.width;
+          roi->rectangles[i].height    = surface->dirty.height;
           surface->dirty = *GEGL_RECTANGLE (0, 0, 0, 0);
         }
     }
@@ -693,17 +933,19 @@ gimp_mypaint_surface2_new (GeglBuffer         *buffer,
                            GimpMybrushOptions *options)
 {
   GimpMybrushSurface2 *surface = g_malloc0 (sizeof (GimpMybrushSurface2));
+  MyPaintSurface2 *s;
 
   mypaint_surface_init (&surface->surface.parent);
+  s = &surface->surface;
 
-  surface->surface.get_color_pigment    = gimp_mypaint_surface_get_color_2;
-  surface->surface.draw_dab_pigment     = gimp_mypaint_surface_draw_dab_2;
-  surface->surface.parent.begin_atomic  = gimp_mypaint_surface_begin_atomic;
-  surface->surface.end_atomic_multi     = gimp_mypaint_surface_end_atomic_2;
+  s->get_color_pigment    = gimp_mypaint_surface_get_color_2;
+  s->draw_dab_pigment     = gimp_mypaint_surface_draw_dab_2;
+  s->parent.begin_atomic  = gimp_mypaint_surface_begin_atomic;
+  s->end_atomic_multi     = gimp_mypaint_surface_end_atomic_2;
 
-  surface->surface.parent.draw_dab      = gimp_mypaint_surface_draw_dab_wrapper;
-  surface->surface.parent.get_color     = gimp_mypaint_surface_get_color_wrapper;
-  surface->surface.parent.end_atomic    = gimp_mypaint_surface_end_atomic_wrapper;
+  s->parent.draw_dab      = gimp_mypaint_surface_draw_dab_wrapper;
+  s->parent.get_color     = gimp_mypaint_surface_get_color_wrapper;
+  s->parent.end_atomic    = gimp_mypaint_surface_end_atomic_wrapper;
 
   surface->component_mask               = component_mask;
   surface->options                      = options;
@@ -716,4 +958,4 @@ gimp_mypaint_surface2_new (GeglBuffer         *buffer,
   surface->dirty                        = *GEGL_RECTANGLE (0, 0, 0, 0);
 
   return surface;
-}
\ No newline at end of file
+}


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