GimpBrushApplicationMode gimp_paint_options_get_brush_mode (GimpPaintOptions *paint_options) { GimpDynamics *dynamics; GimpDynamicsOutput *force_output; gboolean dynamic_force = FALSE; g_return_val_if_fail (GIMP_IS_PAINT_OPTIONS (paint_options), GIMP_BRUSH_SOFT); if (paint_options->hard) return GIMP_BRUSH_HARD; dynamics = gimp_context_get_dynamics (GIMP_CONTEXT (paint_options)); force_output = gimp_dynamics_get_output (dynamics, GIMP_DYNAMICS_OUTPUT_FORCE); if (force_output) dynamic_force = gimp_dynamics_output_is_enabled (force_output); if (dynamic_force || (paint_options->brush_force > 0.0)) return GIMP_BRUSH_PRESSURE; return GIMP_BRUSH_SOFT; }
gboolean gimp_paint_options_get_gradient_color (GimpPaintOptions *paint_options, GimpImage *image, gdouble grad_point, gdouble pixel_dist, GimpRGB *color) { GimpGradientOptions *gradient_options; GimpGradient *gradient; GimpDynamics *dynamics; GimpDynamicsOutput *color_output; g_return_val_if_fail (GIMP_IS_PAINT_OPTIONS (paint_options), FALSE); g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE); g_return_val_if_fail (color != NULL, FALSE); gradient_options = paint_options->gradient_options; gradient = gimp_context_get_gradient (GIMP_CONTEXT (paint_options)); dynamics = gimp_context_get_dynamics (GIMP_CONTEXT (paint_options)); color_output = gimp_dynamics_get_output (dynamics, GIMP_DYNAMICS_OUTPUT_COLOR); if (gimp_dynamics_output_is_enabled (color_output)) { gimp_gradient_get_color_at (gradient, GIMP_CONTEXT (paint_options), NULL, grad_point, gradient_options->gradient_reverse, color); return TRUE; } return FALSE; }
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); }
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); }