Example #1
0
static void
gimp_eraser_motion (GimpPaintCore    *paint_core,
                    GimpDrawable     *drawable,
                    GimpPaintOptions *paint_options)
{
  GimpEraserOptions *options = GIMP_ERASER_OPTIONS (paint_options);
  GimpContext       *context = GIMP_CONTEXT (paint_options);
  GimpImage         *image;
  gdouble            opacity;
  TempBuf           *area;
  guchar             col[MAX_CHANNELS];
  gdouble            hardness;

  image = gimp_item_get_image (GIMP_ITEM (drawable));

  opacity = gimp_paint_options_get_fade (paint_options, image,
                                         paint_core->pixel_dist);
  if (opacity == 0.0)
    return;

  area = gimp_paint_core_get_paint_area (paint_core, drawable, paint_options);
  if (! area)
    return;

  gimp_image_get_background (image, context, gimp_drawable_type (drawable),
                             col);

  /*  set the alpha channel  */
  col[area->bytes - 1] = OPAQUE_OPACITY;

  /*  color the pixels  */
  color_pixels (temp_buf_data (area), col,
                area->width * area->height, area->bytes);

  opacity *= gimp_paint_options_get_dynamic_opacity (paint_options,
                                                     &paint_core->cur_coords);

  hardness = gimp_paint_options_get_dynamic_hardness (paint_options,
                                                      &paint_core->cur_coords);

  gimp_brush_core_paste_canvas (GIMP_BRUSH_CORE (paint_core), drawable,
                                MIN (opacity, GIMP_OPACITY_OPAQUE),
                                gimp_context_get_opacity (context),
                                (options->anti_erase ?
                                 GIMP_ANTI_ERASE_MODE : GIMP_ERASE_MODE),
                                gimp_paint_options_get_brush_mode (paint_options),
                                hardness,
                                paint_options->application_mode);
}
Example #2
0
static void
gimp_eraser_motion (GimpPaintCore    *paint_core,
                    GimpDrawable     *drawable,
                    GimpPaintOptions *paint_options,
                    const GimpCoords *coords)
{
  GimpEraserOptions  *options  = GIMP_ERASER_OPTIONS (paint_options);
  GimpContext        *context  = GIMP_CONTEXT (paint_options);
  GimpDynamics       *dynamics = GIMP_BRUSH_CORE (paint_core)->dynamics;
  GimpDynamicsOutput *opacity_output;
  GimpDynamicsOutput *force_output;
  GimpImage          *image;
  gdouble             fade_point;
  gdouble             opacity;
  TempBuf            *area;
  guchar              col[MAX_CHANNELS];
  gdouble             force;

  image = gimp_item_get_image (GIMP_ITEM (drawable));

  opacity_output = gimp_dynamics_get_output (dynamics,
                                             GIMP_DYNAMICS_OUTPUT_OPACITY);

  fade_point = gimp_paint_options_get_fade (paint_options,
                                            gimp_item_get_image (GIMP_ITEM (drawable)),
                                            paint_core->pixel_dist);

  opacity = gimp_dynamics_output_get_linear_value (opacity_output,
                                                   coords,
                                                   paint_options,
                                                   fade_point);
  if (opacity == 0.0)
    return;

  area = gimp_paint_core_get_paint_area (paint_core, drawable, paint_options,
                                         coords);
  if (! area)
    return;

  gimp_image_get_background (image, context, gimp_drawable_type (drawable),
                             col);

  /*  set the alpha channel  */
  col[area->bytes - 1] = OPAQUE_OPACITY;

  /*  color the pixels  */
  color_pixels (temp_buf_get_data (area), col,
                area->width * area->height, area->bytes);

  force_output = gimp_dynamics_get_output (dynamics,
                                           GIMP_DYNAMICS_OUTPUT_FORCE);

  force = gimp_dynamics_output_get_linear_value (force_output,
                                                 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),
                                (options->anti_erase ?
                                 GIMP_ANTI_ERASE_MODE : GIMP_ERASE_MODE),
                                gimp_paint_options_get_brush_mode (paint_options),
                                force,
                                paint_options->application_mode);
}
Example #3
0
static void
gimp_convolve_motion (GimpPaintCore    *paint_core,
                      GimpDrawable     *drawable,
                      GimpPaintOptions *paint_options)
{
  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);
  GimpImage           *image;
  TempBuf             *area;
  PixelRegion          srcPR;
  PixelRegion          destPR;
  PixelRegion          tempPR;
  guchar              *buffer;
  gdouble              opacity;
  gdouble              rate;
  gint                 bytes;

  image = gimp_item_get_image (GIMP_ITEM (drawable));

  if (gimp_drawable_is_indexed (drawable))
    return;

  opacity = gimp_paint_options_get_fade (paint_options, image,
                                         paint_core->pixel_dist);
  if (opacity == 0.0)
    return;

  area = gimp_paint_core_get_paint_area (paint_core, drawable, paint_options);
  if (! area)
    return;

  rate = options->rate;

  rate *= gimp_paint_options_get_dynamic_rate (paint_options,
                                               &paint_core->cur_coords);

  gimp_convolve_calculate_matrix (convolve, options->type,
                                  brush_core->brush->mask->width / 2,
                                  brush_core->brush->mask->height / 2,
                                  rate);

  /*  configure the source pixel region  */
  pixel_region_init (&srcPR, gimp_drawable_get_tiles (drawable),
                     area->x, area->y, area->width, area->height, FALSE);

  if (gimp_drawable_has_alpha (drawable))
    {
      bytes = srcPR.bytes;

      buffer = g_malloc (area->height * bytes * area->width);

      pixel_region_init_data (&tempPR, buffer,
                              bytes, bytes * area->width,
                              0, 0, area->width, area->height);

      copy_region (&srcPR, &tempPR);
    }
  else
    {
      /* note: this particular approach needlessly convolves the totally-
         opaque alpha channel. A faster approach would be to keep
         tempPR the same number of bytes as srcPR, and extend the
         paint_core_replace_canvas API to handle non-alpha images. */

      bytes = srcPR.bytes + 1;

      buffer = g_malloc (area->height * bytes * area->width);

      pixel_region_init_data (&tempPR, buffer,
                              bytes, bytes * area->width,
                              0, 0, area->width, area->height);

      add_alpha_region (&srcPR, &tempPR);
    }

  /*  Convolve the region  */
  pixel_region_init_data (&tempPR, buffer,
                          bytes, bytes * area->width,
                          0, 0, area->width, area->height);

  pixel_region_init_temp_buf (&destPR, area,
                              0, 0, area->width, area->height);

  convolve_region (&tempPR, &destPR,
                   convolve->matrix, 3, convolve->matrix_divisor,
                   GIMP_NORMAL_CONVOL, TRUE);

  g_free (buffer);

  gimp_brush_core_replace_canvas (brush_core, drawable,
                                  MIN (opacity, GIMP_OPACITY_OPAQUE),
                                  gimp_context_get_opacity (context),
                                  gimp_paint_options_get_brush_mode (paint_options),
                                  1.0,
                                  GIMP_PAINT_INCREMENTAL);
}
Example #4
0
void
gimp_source_core_motion (GimpSourceCore   *source_core,
                         GimpDrawable     *drawable,
                         GimpPaintOptions *paint_options)
{
  GimpPaintCore     *paint_core   = GIMP_PAINT_CORE (source_core);
  GimpSourceOptions *options      = GIMP_SOURCE_OPTIONS (paint_options);
  GimpImage         *image        = gimp_item_get_image (GIMP_ITEM (drawable));
  GimpPickable      *src_pickable = NULL;
  PixelRegion        srcPR;
  gint               src_offset_x;
  gint               src_offset_y;
  TempBuf           *paint_area;
  gint               paint_area_offset_x;
  gint               paint_area_offset_y;
  gint               paint_area_width;
  gint               paint_area_height;
  gdouble            opacity;

  opacity = gimp_paint_options_get_fade (paint_options, image,
                                         paint_core->pixel_dist);
  if (opacity == 0.0)
    return;

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

  if (options->use_source)
    {
      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 (gimp_image_get_projection (src_image));

          gimp_item_offsets (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_area = gimp_paint_core_get_paint_area (paint_core, drawable,
                                               paint_options);
  if (! paint_area)
    return;

  paint_area_offset_x = 0;
  paint_area_offset_y = 0;
  paint_area_width    = paint_area->width;
  paint_area_height   = paint_area->height;

  if (options->use_source &&
      ! GIMP_SOURCE_CORE_GET_CLASS (source_core)->get_source (source_core,
                                                              drawable,
                                                              paint_options,
                                                              src_pickable,
                                                              src_offset_x,
                                                              src_offset_y,
                                                              paint_area,
                                                              &paint_area_offset_x,
                                                              &paint_area_offset_y,
                                                              &paint_area_width,
                                                              &paint_area_height,
                                                              &srcPR))
    {
      return;
    }

  /*  Set the paint area to transparent  */
  temp_buf_data_clear (paint_area);

  GIMP_SOURCE_CORE_GET_CLASS (source_core)->motion (source_core,
                                                    drawable,
                                                    paint_options,
                                                    opacity,
                                                    src_pickable,
                                                    &srcPR,
                                                    src_offset_x,
                                                    src_offset_y,
                                                    paint_area,
                                                    paint_area_offset_x,
                                                    paint_area_offset_y,
                                                    paint_area_width,
                                                    paint_area_height);
}
Example #5
0
static void
gimp_ink_motion (GimpPaintCore    *paint_core,
                 GimpDrawable     *drawable,
                 GimpPaintOptions *paint_options,
                 const GimpCoords *coords,
                 guint32           time)
{
  GimpInk        *ink     = GIMP_INK (paint_core);
  GimpInkOptions *options = GIMP_INK_OPTIONS (paint_options);
  GimpContext    *context = GIMP_CONTEXT (paint_options);
  GimpImage      *image;
  GimpBlob       *blob_union = NULL;
  GimpBlob       *blob_to_render;
  TempBuf        *area;
  guchar          col[MAX_CHANNELS];
  PixelRegion     blob_maskPR;

  image = gimp_item_get_image (GIMP_ITEM (drawable));

  if (! ink->last_blob)
    {
      ink->last_blob = ink_pen_ellipse (options,
                                        coords->x,
                                        coords->y,
                                        coords->pressure,
                                        coords->xtilt,
                                        coords->ytilt,
                                        100);

      if (ink->start_blob)
        g_free (ink->start_blob);

      ink->start_blob = gimp_blob_duplicate (ink->last_blob);

      blob_to_render = ink->last_blob;
    }
  else
    {
      GimpBlob *blob = ink_pen_ellipse (options,
                                        coords->x,
                                        coords->y,
                                        coords->pressure,
                                        coords->xtilt,
                                        coords->ytilt,
                                        coords->velocity * 100);

      blob_union = gimp_blob_convex_union (ink->last_blob, blob);

      g_free (ink->last_blob);
      ink->last_blob = blob;

      blob_to_render = blob_union;
    }

  /* Get the buffer */
  ink->cur_blob = blob_to_render;
  area = gimp_paint_core_get_paint_area (paint_core, drawable, paint_options,
                                         coords);
  ink->cur_blob = NULL;

  if (! area)
    return;

  gimp_image_get_foreground (image, context, gimp_drawable_type (drawable),
                             col);

  /*  set the alpha channel  */
  col[paint_core->canvas_buf->bytes - 1] = OPAQUE_OPACITY;

  /*  color the pixels  */
  color_pixels (temp_buf_get_data (paint_core->canvas_buf), col,
                area->width * area->height, area->bytes);

  gimp_paint_core_validate_canvas_tiles (paint_core,
                                         paint_core->canvas_buf->x,
                                         paint_core->canvas_buf->y,
                                         paint_core->canvas_buf->width,
                                         paint_core->canvas_buf->height);

  /*  draw the blob directly to the canvas_tiles  */
  pixel_region_init (&blob_maskPR, paint_core->canvas_tiles,
                     paint_core->canvas_buf->x,
                     paint_core->canvas_buf->y,
                     paint_core->canvas_buf->width,
                     paint_core->canvas_buf->height,
                     TRUE);

  render_blob (blob_to_render, &blob_maskPR);

  /*  draw the canvas_buf using the just rendered canvas_tiles as mask */
  pixel_region_init (&blob_maskPR, paint_core->canvas_tiles,
                     paint_core->canvas_buf->x,
                     paint_core->canvas_buf->y,
                     paint_core->canvas_buf->width,
                     paint_core->canvas_buf->height,
                     FALSE);

  gimp_paint_core_paste (paint_core, &blob_maskPR, drawable,
                         GIMP_OPACITY_OPAQUE,
                         gimp_context_get_opacity (context),
                         gimp_context_get_paint_mode (context),
                         GIMP_PAINT_CONSTANT);

  if (blob_union)
    g_free (blob_union);
}
Example #6
0
static void
gimp_smudge_motion (GimpPaintCore    *paint_core,
                    GimpDrawable     *drawable,
                    GimpPaintOptions *paint_options)
{
  GimpSmudge          *smudge           = GIMP_SMUDGE (paint_core);
  GimpSmudgeOptions   *options          = GIMP_SMUDGE_OPTIONS (paint_options);
  GimpContext         *context          = GIMP_CONTEXT (paint_options);
  GimpPressureOptions *pressure_options = paint_options->pressure_options;
  GimpImage           *image;
  TempBuf             *area;
  PixelRegion          srcPR, destPR, tempPR;
  gdouble              rate;
  gdouble              opacity;
  gint                 x, y, w, h;

  image = gimp_item_get_image (GIMP_ITEM (drawable));

  if (gimp_drawable_is_indexed (drawable))
    return;

  opacity = gimp_paint_options_get_fade (paint_options, image,
                                         paint_core->pixel_dist);
  if (opacity == 0.0)
    return;

  /*  Get the unclipped brush coordinates  */
  gimp_smudge_brush_coords (paint_core, &x, &y, &w, &h);

  /*  Get the paint area (Smudge won't scale!)  */
  area = gimp_paint_core_get_paint_area (paint_core, drawable, paint_options);
  if (! area)
    return;

  /* srcPR will be the pixels under the current painthit from the drawable */
  pixel_region_init (&srcPR, gimp_drawable_get_tiles (drawable),
                     area->x, area->y, area->width, area->height, FALSE);

  /* Enable pressure sensitive rate */
  if (pressure_options->rate)
    rate = MIN (options->rate / 100.0 * PRESSURE_SCALE *
                paint_core->cur_coords.pressure, 1.0);
  else
    rate = options->rate / 100.0;

  /* The tempPR will be the built up buffer (for smudge) */
  pixel_region_init_data (&tempPR, smudge->accum_data,
                          smudge->accumPR.bytes,
                          smudge->accumPR.rowstride,
                          area->x - x,
                          area->y - y,
                          area->width,
                          area->height);

  /* The dest will be the paint area we got above (= canvas_buf) */
  pixel_region_init_temp_buf (&destPR, area,
                              0, 0, area->width, area->height);

  /*  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 (canvas_buf) is built as
   *    (Accum,1) (if no alpha),
   */

  blend_region (&srcPR, &tempPR, &tempPR, ROUND (rate * 255.0));

  /* re-init the tempPR */
  pixel_region_init_data (&tempPR, smudge->accum_data,
                          smudge->accumPR.bytes,
                          smudge->accumPR.rowstride,
                          area->x - x,
                          area->y - y,
                          area->width,
                          area->height);

  if (! gimp_drawable_has_alpha (drawable))
    add_alpha_region (&tempPR, &destPR);
  else
    copy_region (&tempPR, &destPR);

  if (pressure_options->opacity)
    opacity *= PRESSURE_SCALE * paint_core->cur_coords.pressure;

  gimp_brush_core_replace_canvas (GIMP_BRUSH_CORE (paint_core), drawable,
                                  MIN (opacity, GIMP_OPACITY_OPAQUE),
                                  gimp_context_get_opacity (context),
                                  gimp_paint_options_get_brush_mode (paint_options),
                                  GIMP_PAINT_INCREMENTAL);
}
Example #7
0
static gboolean
gimp_smudge_start (GimpPaintCore    *paint_core,
                   GimpDrawable     *drawable,
                   GimpPaintOptions *paint_options)
{
  GimpSmudge  *smudge = GIMP_SMUDGE (paint_core);
  GimpImage   *image;
  TempBuf     *area;
  PixelRegion  srcPR;
  gint         bytes;
  gint         x, y, w, h;

  image = gimp_item_get_image (GIMP_ITEM (drawable));

  if (gimp_drawable_is_indexed (drawable))
    return FALSE;

  area = gimp_paint_core_get_paint_area (paint_core, drawable, paint_options);
  if (! area)
    return FALSE;

  /*  adjust the x and y coordinates to the upper left corner of the brush  */
  gimp_smudge_brush_coords (paint_core, &x, &y, &w, &h);

  /*  Allocate the accumulation buffer */
  bytes = gimp_drawable_bytes (drawable);
  smudge->accum_data = g_malloc (w * h * bytes);

  /*  If clipped, prefill the smudge buffer with the color at the
   *  brush position.
   */
  if (x != area->x || y != area->y || w != area->width || h != area->height)
    {
      guchar fill[4];

      gimp_pickable_get_pixel_at (GIMP_PICKABLE (drawable),
                                  CLAMP ((gint) paint_core->cur_coords.x,
                                         0,
                                         gimp_item_width (GIMP_ITEM (drawable)) - 1),
                                  CLAMP ((gint) paint_core->cur_coords.y,
                                         0,
                                         gimp_item_height (GIMP_ITEM (drawable)) - 1),
                                  fill);

      pixel_region_init_data (&srcPR, smudge->accum_data,
                              bytes, bytes * w,
                              0, 0, w, h);

      color_region (&srcPR, fill);
    }

  pixel_region_init (&srcPR, gimp_drawable_get_tiles (drawable),
                     area->x, area->y, area->width, area->height, FALSE);

  pixel_region_init_data (&smudge->accumPR, smudge->accum_data,
                          bytes, bytes * w,
                          area->x - x,
                          area->y - y,
                          area->width,
                          area->height);

  /* copy the region under the original painthit. */
  copy_region (&srcPR, &smudge->accumPR);

  pixel_region_init_data (&smudge->accumPR, smudge->accum_data,
                          bytes, bytes * w,
                          area->x - x,
                          area->y - y,
                          area->width,
                          area->height);

  return TRUE;
}
Example #8
0
void
_gimp_paintbrush_motion (GimpPaintCore    *paint_core,
                         GimpDrawable     *drawable,
                         GimpPaintOptions *paint_options,
                         gdouble           opacity)
{
  GimpBrushCore            *brush_core       = GIMP_BRUSH_CORE (paint_core);
  GimpContext              *context          = GIMP_CONTEXT (paint_options);
  GimpPressureOptions      *pressure_options = paint_options->pressure_options;
  GimpImage                *image;
  GimpRGB                   gradient_color;
  TempBuf                  *area;
  guchar                    col[MAX_CHANNELS];
  GimpPaintApplicationMode  paint_appl_mode;

  image = gimp_item_get_image (GIMP_ITEM (drawable));

  opacity *= gimp_paint_options_get_fade (paint_options, image,
                                          paint_core->pixel_dist);
  if (opacity == 0.0)
    return;

  paint_appl_mode = paint_options->application_mode;

  area = gimp_paint_core_get_paint_area (paint_core, drawable, paint_options);
  if (! area)
    return;

  /* optionally take the color from the current gradient */
  if (gimp_paint_options_get_gradient_color (paint_options, image,
                                             paint_core->cur_coords.pressure,
                                             paint_core->pixel_dist,
                                             &gradient_color))
    {
      opacity *= gradient_color.a;

      gimp_rgb_get_uchar (&gradient_color,
                          &col[RED_PIX],
                          &col[GREEN_PIX],
                          &col[BLUE_PIX]);
      col[ALPHA_PIX] = OPAQUE_OPACITY;

      color_pixels (temp_buf_data (area), col,
                    area->width * area->height,
                    area->bytes);

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

      paint_appl_mode = GIMP_PAINT_INCREMENTAL;
    }
  /* otherwise fill the area with the foreground color */
  else
    {
      gimp_image_get_foreground (image, context, gimp_drawable_type (drawable),
                                 col);

      col[area->bytes - 1] = OPAQUE_OPACITY;

      color_pixels (temp_buf_data (area), col,
                    area->width * area->height,
                    area->bytes);
    }

  if (paint_core->use_pressure && pressure_options->opacity)
    opacity *= PRESSURE_SCALE * paint_core->cur_coords.pressure;

  /* finally, let the brush core paste the colored area on the canvas */
  gimp_brush_core_paste_canvas (brush_core, drawable,
                                MIN (opacity, GIMP_OPACITY_OPAQUE),
                                gimp_context_get_opacity (context),
                                gimp_context_get_paint_mode (context),
                                gimp_paint_options_get_brush_mode (paint_options),
                                paint_appl_mode);
}