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); }
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); }
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); }
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); }
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); }
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); }
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; }
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); }