static void gimp_drawable_bucket_fill_internal (GimpDrawable *drawable, GimpFillType fill_type, gint paint_mode, gdouble opacity, gboolean fill_transparent, GimpSelectCriterion fill_criterion, gdouble threshold, gboolean sample_merged, gboolean diagonal_neighbors, gdouble x, gdouble y, const GimpRGB *color, GimpPattern *pattern) { GimpImage *image; GimpPickable *pickable; GeglBuffer *buffer; GeglBuffer *mask_buffer; gint x1, y1, x2, y2; gint mask_offset_x = 0; gint mask_offset_y = 0; gboolean selection; g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable))); g_return_if_fail (fill_type != GIMP_FILL_PATTERN || GIMP_IS_PATTERN (pattern)); g_return_if_fail (fill_type == GIMP_FILL_PATTERN || color != NULL); image = gimp_item_get_image (GIMP_ITEM (drawable)); selection = gimp_item_mask_bounds (GIMP_ITEM (drawable), &x1, &y1, &x2, &y2); if ((x1 == x2) || (y1 == y2)) return; gimp_set_busy (image->gimp); if (sample_merged) pickable = GIMP_PICKABLE (image); else pickable = GIMP_PICKABLE (drawable); /* Do a seed bucket fill...To do this, calculate a new * contiguous region. If there is a selection, calculate the * intersection of this region with the existing selection. */ mask_buffer = gimp_pickable_contiguous_region_by_seed (pickable, TRUE, threshold, fill_transparent, fill_criterion, diagonal_neighbors, (gint) x, (gint) y); if (selection) { GimpDrawable *sel; gint off_x = 0; gint off_y = 0; if (! sample_merged) gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y); sel = GIMP_DRAWABLE (gimp_image_get_mask (image)); gimp_gegl_mask_combine_buffer (mask_buffer, gimp_drawable_get_buffer (sel), GIMP_CHANNEL_OP_INTERSECT, -off_x, -off_y); } gimp_gegl_mask_bounds (mask_buffer, &x1, &y1, &x2, &y2); /* make sure we handle the mask correctly if it was sample-merged */ if (sample_merged) { GimpItem *item = GIMP_ITEM (drawable); gint off_x, off_y; /* Limit the channel bounds to the drawable's extents */ gimp_item_get_offset (item, &off_x, &off_y); x1 = CLAMP (x1, off_x, (off_x + gimp_item_get_width (item))); y1 = CLAMP (y1, off_y, (off_y + gimp_item_get_height (item))); x2 = CLAMP (x2, off_x, (off_x + gimp_item_get_width (item))); y2 = CLAMP (y2, off_y, (off_y + gimp_item_get_height (item))); mask_offset_x = x1; mask_offset_y = y1; /* translate mask bounds to drawable coords */ x1 -= off_x; y1 -= off_y; x2 -= off_x; y2 -= off_y; } else { mask_offset_x = x1; mask_offset_y = y1; } buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, x2 - x1, y2 - y1), gimp_drawable_get_format_with_alpha (drawable)); switch (fill_type) { case GIMP_FILL_FOREGROUND: case GIMP_FILL_BACKGROUND: case GIMP_FILL_WHITE: case GIMP_FILL_TRANSPARENT: { GeglColor *gegl_color = gimp_gegl_color_new (color); gegl_buffer_set_color (buffer, NULL, gegl_color); g_object_unref (gegl_color); } break; case GIMP_FILL_PATTERN: { GeglBuffer *pattern_buffer = gimp_pattern_create_buffer (pattern); gegl_buffer_set_pattern (buffer, NULL, pattern_buffer, -x1, -y1); g_object_unref (pattern_buffer); } break; } gimp_gegl_apply_opacity (buffer, NULL, NULL, buffer, mask_buffer, -mask_offset_x, -mask_offset_y, 1.0); g_object_unref (mask_buffer); /* Apply it to the image */ gimp_drawable_apply_buffer (drawable, buffer, GEGL_RECTANGLE (0, 0, x2 - x1, y2 - y1), TRUE, C_("undo-type", "Bucket Fill"), opacity, paint_mode, NULL, x1, y1); g_object_unref (buffer); gimp_drawable_update (drawable, x1, y1, x2 - x1, y2 - y1); gimp_unset_busy (image->gimp); }
gboolean gimp_edit_fill_full (GimpImage *image, GimpDrawable *drawable, const GimpRGB *color, GimpPattern *pattern, gdouble opacity, GimpLayerModeEffects paint_mode, const gchar *undo_desc) { GeglBuffer *dest_buffer; const Babl *format; gint x, y, width, height; g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE); g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE); g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), FALSE); g_return_val_if_fail (color != NULL || pattern != NULL, FALSE); if (! gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height)) return TRUE; /* nothing to do, but the fill succeeded */ if (pattern && babl_format_has_alpha (gimp_temp_buf_get_format (pattern->mask)) && ! gimp_drawable_has_alpha (drawable)) { format = gimp_drawable_get_format_with_alpha (drawable); } else { format = gimp_drawable_get_format (drawable); } dest_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, width, height), format); if (pattern) { GeglBuffer *src_buffer = gimp_pattern_create_buffer (pattern); gegl_buffer_set_pattern (dest_buffer, NULL, src_buffer, 0, 0); g_object_unref (src_buffer); } else { GeglColor *gegl_color = gimp_gegl_color_new (color); gegl_buffer_set_color (dest_buffer, NULL, gegl_color); g_object_unref (gegl_color); } gimp_drawable_apply_buffer (drawable, dest_buffer, GEGL_RECTANGLE (0, 0, width, height), TRUE, undo_desc, opacity, paint_mode, NULL, x, y); g_object_unref (dest_buffer); gimp_drawable_update (drawable, x, y, width, height); return TRUE; }
void gimp_edit_fill (GimpImage *image, GimpDrawable *drawable, GimpFillOptions *options, const gchar *undo_desc) { GeglBuffer *dest_buffer; GimpPattern *pattern = NULL; GimpRGB color; const Babl *format; gint x, y, width, height; g_return_if_fail (GIMP_IS_IMAGE (image)); g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable))); g_return_if_fail (GIMP_IS_FILL_OPTIONS (options)); if (! gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height)) return; /* nothing to do, but the fill succeeded */ switch (gimp_fill_options_get_style (options)) { case GIMP_FILL_STYLE_SOLID: gimp_context_get_foreground (GIMP_CONTEXT (options), &color); break; case GIMP_FILL_STYLE_PATTERN: pattern = gimp_context_get_pattern (GIMP_CONTEXT (options)); break; } if (pattern && babl_format_has_alpha (gimp_temp_buf_get_format (pattern->mask)) && ! gimp_drawable_has_alpha (drawable)) { format = gimp_drawable_get_format_with_alpha (drawable); } else { format = gimp_drawable_get_format (drawable); } dest_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, width, height), format); if (pattern) { GeglBuffer *src_buffer = gimp_pattern_create_buffer (pattern); gegl_buffer_set_pattern (dest_buffer, NULL, src_buffer, 0, 0); g_object_unref (src_buffer); } else { GeglColor *gegl_color = gimp_gegl_color_new (&color); gegl_buffer_set_color (dest_buffer, NULL, gegl_color); g_object_unref (gegl_color); } if (! undo_desc) undo_desc = gimp_fill_options_get_undo_desc (options); gimp_drawable_apply_buffer (drawable, dest_buffer, GEGL_RECTANGLE (0, 0, width, height), TRUE, undo_desc, gimp_context_get_opacity (GIMP_CONTEXT (options)), gimp_context_get_paint_mode (GIMP_CONTEXT (options)), NULL, x, y); g_object_unref (dest_buffer); gimp_drawable_update (drawable, x, y, width, height); }
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); }