Exemple #1
0
void
gimp_source_core_motion (GimpSourceCore   *source_core,
                         GimpDrawable     *drawable,
                         GimpPaintOptions *paint_options,
                         const GimpCoords *coords)

{
  GimpPaintCore     *paint_core   = GIMP_PAINT_CORE (source_core);
  GimpSourceOptions *options      = GIMP_SOURCE_OPTIONS (paint_options);
  GimpDynamics      *dynamics     = GIMP_BRUSH_CORE (paint_core)->dynamics;
  GimpImage         *image        = gimp_item_get_image (GIMP_ITEM (drawable));
  GimpPickable      *src_pickable = NULL;
  GeglBuffer        *src_buffer   = NULL;
  GeglRectangle      src_rect;
  gint               src_offset_x;
  gint               src_offset_y;
  GeglBuffer        *paint_buffer;
  gint               paint_buffer_x;
  gint               paint_buffer_y;
  gint               paint_area_offset_x;
  gint               paint_area_offset_y;
  gint               paint_area_width;
  gint               paint_area_height;
  gdouble            fade_point;
  gdouble            opacity;

  fade_point = gimp_paint_options_get_fade (paint_options, image,
                                            paint_core->pixel_dist);

  opacity = gimp_dynamics_get_linear_value (dynamics,
                                            GIMP_DYNAMICS_OUTPUT_OPACITY,
                                            coords,
                                            paint_options,
                                            fade_point);
  if (opacity == 0.0)
    return;

  src_offset_x = source_core->offset_x;
  src_offset_y = source_core->offset_y;

  if (gimp_source_core_use_source (source_core, options))
    {
      src_pickable = GIMP_PICKABLE (source_core->src_drawable);

      if (options->sample_merged)
        {
          GimpImage *src_image = gimp_pickable_get_image (src_pickable);
          gint       off_x, off_y;

          src_pickable = GIMP_PICKABLE (src_image);

          gimp_item_get_offset (GIMP_ITEM (source_core->src_drawable),
                                &off_x, &off_y);

          src_offset_x += off_x;
          src_offset_y += off_y;
        }

      gimp_pickable_flush (src_pickable);
    }

  paint_buffer = gimp_paint_core_get_paint_buffer (paint_core, drawable,
                                                   paint_options, coords,
                                                   &paint_buffer_x,
                                                   &paint_buffer_y);
  if (! paint_buffer)
    return;

  paint_area_offset_x = 0;
  paint_area_offset_y = 0;
  paint_area_width    = gegl_buffer_get_width  (paint_buffer);
  paint_area_height   = gegl_buffer_get_height (paint_buffer);

  if (gimp_source_core_use_source (source_core, options))
    {
      src_buffer =
        GIMP_SOURCE_CORE_GET_CLASS (source_core)->get_source (source_core,
                                                              drawable,
                                                              paint_options,
                                                              src_pickable,
                                                              src_offset_x,
                                                              src_offset_y,
                                                              paint_buffer,
                                                              paint_buffer_x,
                                                              paint_buffer_y,
                                                              &paint_area_offset_x,
                                                              &paint_area_offset_y,
                                                              &paint_area_width,
                                                              &paint_area_height,
                                                              &src_rect);
      if (! src_buffer)
        return;
    }

  /*  Set the paint buffer to transparent  */
  gegl_buffer_clear (paint_buffer, NULL);

  GIMP_SOURCE_CORE_GET_CLASS (source_core)->motion (source_core,
                                                    drawable,
                                                    paint_options,
                                                    coords,
                                                    opacity,
                                                    src_pickable,
                                                    src_buffer,
                                                    &src_rect,
                                                    src_offset_x,
                                                    src_offset_y,
                                                    paint_buffer,
                                                    paint_buffer_x,
                                                    paint_buffer_y,
                                                    paint_area_offset_x,
                                                    paint_area_offset_y,
                                                    paint_area_width,
                                                    paint_area_height);

  if (src_buffer)
    g_object_unref (src_buffer);
}
void
gimp_source_core_motion (GimpSourceCore   *source_core,
                         GimpDrawable     *drawable,
                         GimpPaintOptions *paint_options,
                         GimpSymmetry     *sym)

{
  GimpPaintCore     *paint_core   = GIMP_PAINT_CORE (source_core);
  GimpSourceOptions *options      = GIMP_SOURCE_OPTIONS (paint_options);
  GimpDynamics      *dynamics     = GIMP_BRUSH_CORE (paint_core)->dynamics;
  GimpImage         *image        = gimp_item_get_image (GIMP_ITEM (drawable));
  GimpPickable      *src_pickable = NULL;
  GeglBuffer        *src_buffer   = NULL;
  GeglRectangle      src_rect;
  gint               base_src_offset_x;
  gint               base_src_offset_y;
  gint               src_offset_x;
  gint               src_offset_y;
  GeglBuffer        *paint_buffer;
  gint               paint_buffer_x;
  gint               paint_buffer_y;
  gint               paint_area_offset_x;
  gint               paint_area_offset_y;
  gint               paint_area_width;
  gint               paint_area_height;
  gdouble            fade_point;
  gdouble            opacity;
  GeglNode          *op;
  GimpCoords        *origin;
  GimpCoords        *coords;
  gint               n_strokes;
  gint               i;

  fade_point = gimp_paint_options_get_fade (paint_options, image,
                                            paint_core->pixel_dist);

  origin     = gimp_symmetry_get_origin (sym);
  /* Some settings are based on the original stroke. */
  opacity = gimp_dynamics_get_linear_value (dynamics,
                                            GIMP_DYNAMICS_OUTPUT_OPACITY,
                                            origin,
                                            paint_options,
                                            fade_point);
  if (opacity == 0.0)
    return;

  base_src_offset_x = source_core->offset_x;
  base_src_offset_y = source_core->offset_y;

  if (gimp_source_core_use_source (source_core, options))
    {
      src_pickable = GIMP_PICKABLE (source_core->src_drawable);

      if (options->sample_merged)
        {
          GimpImage *src_image = gimp_pickable_get_image (src_pickable);
          gint       off_x, off_y;

          src_pickable = GIMP_PICKABLE (src_image);

          gimp_item_get_offset (GIMP_ITEM (source_core->src_drawable),
                                &off_x, &off_y);

          base_src_offset_x += off_x;
          base_src_offset_y += off_y;
        }

      gimp_pickable_flush (src_pickable);
    }

  gimp_brush_core_eval_transform_dynamics (GIMP_BRUSH_CORE (paint_core),
                                           drawable,
                                           paint_options,
                                           origin);

  n_strokes  = gimp_symmetry_get_size (sym);
  for (i = 0; i < n_strokes; i++)
    {
      coords = gimp_symmetry_get_coords (sym, i);

      paint_buffer = gimp_paint_core_get_paint_buffer (paint_core, drawable,
                                                       paint_options, coords,
                                                       &paint_buffer_x,
                                                       &paint_buffer_y,
                                                       NULL, NULL);
      if (! paint_buffer)
        continue;

      paint_area_offset_x = 0;
      paint_area_offset_y = 0;
      paint_area_width    = gegl_buffer_get_width  (paint_buffer);
      paint_area_height   = gegl_buffer_get_height (paint_buffer);

      src_offset_x = base_src_offset_x;
      src_offset_y = base_src_offset_y;
      if (gimp_source_core_use_source (source_core, options))
        {
          /* When using a source, use the same for every stroke. */
          src_offset_x = src_offset_x - coords->x + origin->x;
          src_offset_y = src_offset_y - coords->y + origin->y;
          src_buffer =
            GIMP_SOURCE_CORE_GET_CLASS (source_core)->get_source (source_core,
                                                                  drawable,
                                                                  paint_options,
                                                                  src_pickable,
                                                                  src_offset_x,
                                                                  src_offset_y,
                                                                  paint_buffer,
                                                                  paint_buffer_x,
                                                                  paint_buffer_y,
                                                                  &paint_area_offset_x,
                                                                  &paint_area_offset_y,
                                                                  &paint_area_width,
                                                                  &paint_area_height,
                                                                  &src_rect);

          if (! src_buffer)
            continue;
        }

      /*  Set the paint buffer to transparent  */
      gegl_buffer_clear (paint_buffer, NULL);

      op = gimp_symmetry_get_operation (sym, i,
                                        gegl_buffer_get_width (paint_buffer),
                                        gegl_buffer_get_height (paint_buffer));
      GIMP_SOURCE_CORE_GET_CLASS (source_core)->motion (source_core,
                                                        drawable,
                                                        paint_options,
                                                        coords,
                                                        op,
                                                        opacity,
                                                        src_pickable,
                                                        src_buffer,
                                                        &src_rect,
                                                        src_offset_x,
                                                        src_offset_y,
                                                        paint_buffer,
                                                        paint_buffer_x,
                                                        paint_buffer_y,
                                                        paint_area_offset_x,
                                                        paint_area_offset_y,
                                                        paint_area_width,
                                                        paint_area_height);

      if (src_buffer)
        g_object_unref (src_buffer);
    }
}
Exemple #3
0
static void
gimp_smudge_motion (GimpPaintCore    *paint_core,
                    GimpDrawable     *drawable,
                    GimpPaintOptions *paint_options,
                    const GimpCoords *coords)
{
  GimpSmudge         *smudge   = GIMP_SMUDGE (paint_core);
  GimpSmudgeOptions  *options  = GIMP_SMUDGE_OPTIONS (paint_options);
  GimpContext        *context  = GIMP_CONTEXT (paint_options);
  GimpDynamics       *dynamics = GIMP_BRUSH_CORE (paint_core)->dynamics;
  GimpImage          *image    = gimp_item_get_image (GIMP_ITEM (drawable));
  GeglBuffer         *paint_buffer;
  gint                paint_buffer_x;
  gint                paint_buffer_y;
  gint                paint_buffer_width;
  gint                paint_buffer_height;
  gdouble             fade_point;
  gdouble             opacity;
  gdouble             rate;
  gdouble             dynamic_rate;
  gint                x, y;
  gdouble             force;
  gdouble             dyn_force;
  GimpDynamicsOutput *dyn_output = NULL;

  fade_point = gimp_paint_options_get_fade (paint_options, image,
                                            paint_core->pixel_dist);

  opacity = gimp_dynamics_get_linear_value (dynamics,
                                            GIMP_DYNAMICS_OUTPUT_OPACITY,
                                            coords,
                                            paint_options,
                                            fade_point);
  if (opacity == 0.0)
    return;

  paint_buffer = gimp_paint_core_get_paint_buffer (paint_core, drawable,
                                                   paint_options, coords,
                                                   &paint_buffer_x,
                                                   &paint_buffer_y);
  if (! paint_buffer)
    return;

  paint_buffer_width  = gegl_buffer_get_width  (paint_buffer);
  paint_buffer_height = gegl_buffer_get_height (paint_buffer);

  /*  Get the unclipped acumulator coordinates  */
  gimp_smudge_accumulator_coords (paint_core, coords, &x, &y);

  /* Enable dynamic rate */
  dynamic_rate = gimp_dynamics_get_linear_value (dynamics,
                                                 GIMP_DYNAMICS_OUTPUT_RATE,
                                                 coords,
                                                 paint_options,
                                                 fade_point);

  rate = (options->rate / 100.0) * dynamic_rate;

  /*  Smudge uses the buffer Accum.
   *  For each successive painthit Accum is built like this
   *    Accum =  rate*Accum  + (1-rate)*I.
   *  where I is the pixels under the current painthit.
   *  Then the paint area (paint_area) is built as
   *    (Accum,1) (if no alpha),
   */

  gimp_gegl_smudge_blend (smudge->accum_buffer,
                          GEGL_RECTANGLE (paint_buffer_x - x,
                                          paint_buffer_y - y,
                                          paint_buffer_width,
                                          paint_buffer_height),
                          gimp_drawable_get_buffer (drawable),
                          GEGL_RECTANGLE (paint_buffer_x,
                                          paint_buffer_y,
                                          paint_buffer_width,
                                          paint_buffer_height),
                          smudge->accum_buffer,
                          GEGL_RECTANGLE (paint_buffer_x - x,
                                          paint_buffer_y - y,
                                          paint_buffer_width,
                                          paint_buffer_height),
                          rate);

  gegl_buffer_copy (smudge->accum_buffer,
                    GEGL_RECTANGLE (paint_buffer_x - x,
                                    paint_buffer_y - y,
                                    paint_buffer_width,
                                    paint_buffer_height),
                    paint_buffer,
                    GEGL_RECTANGLE (0, 0, 0, 0));

  dyn_output = gimp_dynamics_get_output (dynamics,
                                         GIMP_DYNAMICS_OUTPUT_FORCE);

  dyn_force = gimp_dynamics_get_linear_value (dynamics,
                                              GIMP_DYNAMICS_OUTPUT_FORCE,
                                              coords,
                                              paint_options,
                                              fade_point);

  if (gimp_dynamics_output_is_enabled (dyn_output))
    force = dyn_force;
  else
    force = paint_options->brush_force;

  gimp_brush_core_replace_canvas (GIMP_BRUSH_CORE (paint_core), drawable,
                                  coords,
                                  MIN (opacity, GIMP_OPACITY_OPAQUE),
                                  gimp_context_get_opacity (context),
                                  gimp_paint_options_get_brush_mode (paint_options),
                                  force,
                                  GIMP_PAINT_INCREMENTAL);
}
Exemple #4
0
static void
gimp_convolve_motion (GimpPaintCore    *paint_core,
                      GimpDrawable     *drawable,
                      GimpPaintOptions *paint_options,
                      const GimpCoords *coords)
{
  GimpConvolve        *convolve   = GIMP_CONVOLVE (paint_core);
  GimpBrushCore       *brush_core = GIMP_BRUSH_CORE (paint_core);
  GimpConvolveOptions *options    = GIMP_CONVOLVE_OPTIONS (paint_options);
  GimpContext         *context    = GIMP_CONTEXT (paint_options);
  GimpDynamics        *dynamics   = GIMP_BRUSH_CORE (paint_core)->dynamics;
  GimpImage           *image      = gimp_item_get_image (GIMP_ITEM (drawable));
  GeglBuffer          *paint_buffer;
  gint                 paint_buffer_x;
  gint                 paint_buffer_y;
  GimpTempBuf         *temp_buf;
  GeglBuffer          *convolve_buffer;
  gdouble              fade_point;
  gdouble              opacity;
  gdouble              rate;

  fade_point = gimp_paint_options_get_fade (paint_options, image,
                                            paint_core->pixel_dist);

  opacity = gimp_dynamics_get_linear_value (dynamics,
                                            GIMP_DYNAMICS_OUTPUT_OPACITY,
                                            coords,
                                            paint_options,
                                            fade_point);
  if (opacity == 0.0)
    return;

  paint_buffer = gimp_paint_core_get_paint_buffer (paint_core, drawable,
                                                   paint_options, coords,
                                                   &paint_buffer_x,
                                                   &paint_buffer_y);
  if (! paint_buffer)
    return;

  rate = (options->rate *
          gimp_dynamics_get_linear_value (dynamics,
                                          GIMP_DYNAMICS_OUTPUT_RATE,
                                          coords,
                                          paint_options,
                                          fade_point));

  gimp_convolve_calculate_matrix (convolve, options->type,
                                  gimp_brush_get_width  (brush_core->brush) / 2,
                                  gimp_brush_get_height (brush_core->brush) / 2,
                                  rate);

  /*  need a linear buffer for gimp_gegl_convolve()  */
  temp_buf = gimp_temp_buf_new (gegl_buffer_get_width  (paint_buffer),
                                gegl_buffer_get_height (paint_buffer),
                                gegl_buffer_get_format (paint_buffer));
  convolve_buffer = gimp_temp_buf_create_buffer (temp_buf);
  gimp_temp_buf_unref (temp_buf);

  gegl_buffer_copy (gimp_drawable_get_buffer (drawable),
                    GEGL_RECTANGLE (paint_buffer_x,
                                    paint_buffer_y,
                                    gegl_buffer_get_width  (paint_buffer),
                                    gegl_buffer_get_height (paint_buffer)),
                    convolve_buffer,
                    GEGL_RECTANGLE (0, 0, 0, 0));

  gimp_gegl_convolve (convolve_buffer,
                      GEGL_RECTANGLE (0, 0,
                                      gegl_buffer_get_width  (convolve_buffer),
                                      gegl_buffer_get_height (convolve_buffer)),
                      paint_buffer,
                      GEGL_RECTANGLE (0, 0,
                                      gegl_buffer_get_width  (paint_buffer),
                                      gegl_buffer_get_height (paint_buffer)),
                      convolve->matrix, 3, convolve->matrix_divisor,
                      GIMP_NORMAL_CONVOL, TRUE);

  g_object_unref (convolve_buffer);

  gimp_brush_core_replace_canvas (brush_core, drawable,
                                  coords,
                                  MIN (opacity, GIMP_OPACITY_OPAQUE),
                                  gimp_context_get_opacity (context),
                                  gimp_paint_options_get_brush_mode (paint_options),
                                  1.0,
                                  GIMP_PAINT_INCREMENTAL);
}
Exemple #5
0
static void
gimp_dodge_burn_motion (GimpPaintCore    *paint_core,
                        GimpDrawable     *drawable,
                        GimpPaintOptions *paint_options,
                        const GimpCoords *coords)
{
  GimpDodgeBurnOptions *options   = GIMP_DODGE_BURN_OPTIONS (paint_options);
  GimpContext          *context   = GIMP_CONTEXT (paint_options);
  GimpDynamics         *dynamics  = GIMP_BRUSH_CORE (paint_core)->dynamics;
  GimpImage            *image     = gimp_item_get_image (GIMP_ITEM (drawable));
  GeglBuffer           *paint_buffer;
  gint                  paint_buffer_x;
  gint                  paint_buffer_y;
  gdouble               fade_point;
  gdouble               opacity;
  gdouble               force;

  fade_point = gimp_paint_options_get_fade (paint_options, image,
                                            paint_core->pixel_dist);

  opacity = gimp_dynamics_get_linear_value (dynamics,
                                            GIMP_DYNAMICS_OUTPUT_OPACITY,
                                            coords,
                                            paint_options,
                                            fade_point);
  if (opacity == 0.0)
    return;

  paint_buffer = gimp_paint_core_get_paint_buffer (paint_core, drawable,
                                                   paint_options, coords,
                                                   &paint_buffer_x,
                                                   &paint_buffer_y);
  if (! paint_buffer)
    return;

  /*  DodgeBurn the region  */
  gimp_gegl_dodgeburn (gimp_paint_core_get_orig_image (paint_core),
                       GEGL_RECTANGLE (paint_buffer_x,
                                       paint_buffer_y,
                                       gegl_buffer_get_width  (paint_buffer),
                                       gegl_buffer_get_height (paint_buffer)),
                       paint_buffer,
                       GEGL_RECTANGLE (0, 0, 0, 0),
                       options->exposure / 100.0,
                       options->type,
                       options->mode);

  if (gimp_dynamics_is_output_enabled (dynamics, GIMP_DYNAMICS_OUTPUT_FORCE))
    force = gimp_dynamics_get_linear_value (dynamics,
                                            GIMP_DYNAMICS_OUTPUT_FORCE,
                                            coords,
                                            paint_options,
                                            fade_point);
  else
    force = paint_options->brush_force;

  /* Replace the newly dodgedburned area (paint_area) to the image */
  gimp_brush_core_replace_canvas (GIMP_BRUSH_CORE (paint_core), drawable,
                                  coords,
                                  MIN (opacity, GIMP_OPACITY_OPAQUE),
                                  gimp_context_get_opacity (context),
                                  gimp_paint_options_get_brush_mode (paint_options),
                                  force,
                                  GIMP_PAINT_CONSTANT);
}
Exemple #6
0
void
_gimp_paintbrush_motion (GimpPaintCore    *paint_core,
                         GimpDrawable     *drawable,
                         GimpPaintOptions *paint_options,
                         const GimpCoords *coords,
                         gdouble           opacity)
{
  GimpBrushCore            *brush_core = GIMP_BRUSH_CORE (paint_core);
  GimpContext              *context    = GIMP_CONTEXT (paint_options);
  GimpDynamics             *dynamics   = brush_core->dynamics;
  GimpImage                *image;
  GimpRGB                   gradient_color;
  GeglBuffer               *paint_buffer;
  gint                      paint_buffer_x;
  gint                      paint_buffer_y;
  GimpPaintApplicationMode  paint_appl_mode;
  gdouble                   fade_point;
  gdouble                   grad_point;
  gdouble                   force;
  gdouble                   dyn_force;
  GimpDynamicsOutput       *dyn_output = NULL;

  image = gimp_item_get_image (GIMP_ITEM (drawable));

  fade_point = gimp_paint_options_get_fade (paint_options, image,
                                            paint_core->pixel_dist);

  opacity *= gimp_dynamics_get_linear_value (dynamics,
                                             GIMP_DYNAMICS_OUTPUT_OPACITY,
                                             coords,
                                             paint_options,
                                             fade_point);
  if (opacity == 0.0)
    return;

  paint_buffer = gimp_paint_core_get_paint_buffer (paint_core, drawable,
                                                   paint_options, coords,
                                                   &paint_buffer_x,
                                                   &paint_buffer_y);
  if (! paint_buffer)
    return;

  paint_appl_mode = paint_options->application_mode;

  grad_point = gimp_dynamics_get_linear_value (dynamics,
                                               GIMP_DYNAMICS_OUTPUT_COLOR,
                                               coords,
                                               paint_options,
                                               fade_point);

  if (gimp_paint_options_get_gradient_color (paint_options, image,
                                             grad_point,
                                             paint_core->pixel_dist,
                                             &gradient_color))
    {
      /* optionally take the color from the current gradient */

      GeglColor *color;

      opacity *= gradient_color.a;
      gimp_rgb_set_alpha (&gradient_color, GIMP_OPACITY_OPAQUE);

      color = gimp_gegl_color_new (&gradient_color);

      gegl_buffer_set_color (paint_buffer, NULL, color);
      g_object_unref (color);

      paint_appl_mode = GIMP_PAINT_INCREMENTAL;
    }
  else if (brush_core->brush && gimp_brush_get_pixmap (brush_core->brush))
    {
      /* otherwise check if the brush has a pixmap and use that to
       * color the area
       */
      gimp_brush_core_color_area_with_pixmap (brush_core, drawable,
                                              coords,
                                              paint_buffer,
                                              paint_buffer_x,
                                              paint_buffer_y,
                                              gimp_paint_options_get_brush_mode (paint_options));

      paint_appl_mode = GIMP_PAINT_INCREMENTAL;
    }
  else
    {
      /* otherwise fill the area with the foreground color */

      GimpRGB    foreground;
      GeglColor *color;

      gimp_context_get_foreground (context, &foreground);
      color = gimp_gegl_color_new (&foreground);

      gegl_buffer_set_color (paint_buffer, NULL, color);
      g_object_unref (color);
    }

  dyn_output = gimp_dynamics_get_output (dynamics,
                                         GIMP_DYNAMICS_OUTPUT_FORCE);

  dyn_force = gimp_dynamics_get_linear_value (dynamics,
                                              GIMP_DYNAMICS_OUTPUT_FORCE,
                                              coords,
                                              paint_options,
                                              fade_point);

  if (gimp_dynamics_output_is_enabled (dyn_output))
    force = dyn_force;
  else
    force = paint_options->brush_force;

  /* finally, let the brush core paste the colored area on the canvas */
  gimp_brush_core_paste_canvas (brush_core, drawable,
                                coords,
                                MIN (opacity, GIMP_OPACITY_OPAQUE),
                                gimp_context_get_opacity (context),
                                gimp_context_get_paint_mode (context),
                                gimp_paint_options_get_brush_mode (paint_options),
                                force,
                                paint_appl_mode);
}
Exemple #7
0
static void
gimp_clone_motion (GimpSourceCore   *source_core,
                   GimpDrawable     *drawable,
                   GimpPaintOptions *paint_options,
                   const GimpCoords *coords,
                   gdouble           opacity,
                   GimpPickable     *src_pickable,
                   GeglBuffer       *src_buffer,
                   GeglRectangle    *src_rect,
                   gint              src_offset_x,
                   gint              src_offset_y,
                   GeglBuffer       *paint_buffer,
                   gint              paint_buffer_x,
                   gint              paint_buffer_y,
                   gint              paint_area_offset_x,
                   gint              paint_area_offset_y,
                   gint              paint_area_width,
                   gint              paint_area_height)
{
  GimpPaintCore     *paint_core     = GIMP_PAINT_CORE (source_core);
  GimpCloneOptions  *options        = GIMP_CLONE_OPTIONS (paint_options);
  GimpSourceOptions *source_options = GIMP_SOURCE_OPTIONS (paint_options);
  GimpContext       *context        = GIMP_CONTEXT (paint_options);
  GimpImage         *image          = gimp_item_get_image (GIMP_ITEM (drawable));
  gdouble            fade_point;
  gdouble            force;

  if (gimp_source_core_use_source (source_core, source_options))
    {
      gegl_buffer_copy (src_buffer,
                        GEGL_RECTANGLE (src_rect->x,
                                        src_rect->y,
                                        paint_area_width,
                                        paint_area_height),
                        paint_buffer,
                        GEGL_RECTANGLE (paint_area_offset_x,
                                        paint_area_offset_y,
                                        0, 0));
    }
  else if (options->clone_type == GIMP_PATTERN_CLONE)
    {
      GimpPattern *pattern    = gimp_context_get_pattern (context);
      GeglBuffer  *src_buffer = gimp_pattern_create_buffer (pattern);

      gegl_buffer_set_pattern (paint_buffer,
                               GEGL_RECTANGLE (paint_area_offset_x,
                                               paint_area_offset_y,
                                               paint_area_width,
                                               paint_area_height),
                               src_buffer,
                               - paint_buffer_x - src_offset_x,
                               - paint_buffer_y - src_offset_y);

      g_object_unref (src_buffer);
    }
  else
    {
      g_return_if_reached ();
    }

  fade_point = gimp_paint_options_get_fade (paint_options, image,
                                            paint_core->pixel_dist);

  force = gimp_dynamics_get_linear_value (GIMP_BRUSH_CORE (paint_core)->dynamics,
                                          GIMP_DYNAMICS_OUTPUT_FORCE,
                                          coords,
                                          paint_options,
                                          fade_point);

  gimp_brush_core_paste_canvas (GIMP_BRUSH_CORE (paint_core), drawable,
                                coords,
                                MIN (opacity, GIMP_OPACITY_OPAQUE),
                                gimp_context_get_opacity (context),
                                gimp_context_get_paint_mode (context),
                                gimp_paint_options_get_brush_mode (paint_options),
                                force,

                                /* In fixed mode, paint incremental so the
                                 * individual brushes are properly applied
                                 * on top of each other.
                                 * Otherwise the stuff we paint is seamless
                                 * and we don't need intermediate masking.
                                 */
                                source_options->align_mode ==
                                GIMP_SOURCE_ALIGN_FIXED ?
                                GIMP_PAINT_INCREMENTAL : GIMP_PAINT_CONSTANT);
}