static void gimp_blend_tool_options_notify (GimpTool *tool, GimpToolOptions *options, const GParamSpec *pspec) { GimpContext *context = GIMP_CONTEXT (options); GimpBlendTool *blend_tool = GIMP_BLEND_TOOL (tool); if (! strcmp (pspec->name, "gradient")) { gimp_blend_tool_set_gradient (blend_tool, context->gradient); if (blend_tool->filter) gimp_drawable_filter_apply (blend_tool->filter, NULL); } else if (blend_tool->render_node && gegl_node_find_property (blend_tool->render_node, pspec->name)) { /* Sync any property changes on the config object that match the op */ GValue value = G_VALUE_INIT; g_value_init (&value, pspec->value_type); g_object_get_property (G_OBJECT (options), pspec->name, &value); gegl_node_set_property (blend_tool->render_node, pspec->name, &value); g_value_unset (&value); if (! strcmp (pspec->name, "gradient-type")) { if (gimp_blend_tool_is_shapeburst (blend_tool)) gimp_blend_tool_precalc_shapeburst (blend_tool); gimp_blend_tool_update_graph (blend_tool); } gimp_drawable_filter_apply (blend_tool->filter, NULL); } else if (blend_tool->filter && ! strcmp (pspec->name, "opacity")) { gimp_drawable_filter_set_opacity (blend_tool->filter, gimp_context_get_opacity (context)); } else if (blend_tool->filter && ! strcmp (pspec->name, "paint-mode")) { gimp_drawable_filter_set_mode (blend_tool->filter, gimp_context_get_paint_mode (context)); } }
static void gimp_blend_tool_active_modifier_key (GimpTool *tool, GdkModifierType key, gboolean press, GdkModifierType state, GimpDisplay *display) { GimpBlendTool *blend_tool = GIMP_BLEND_TOOL (tool); if (key == gimp_get_constrain_behavior_mask ()) { gimp_blend_tool_point_motion (blend_tool, press); gimp_tool_pop_status (tool, display); gimp_blend_tool_push_status (blend_tool, state, display); gimp_blend_tool_update_items (blend_tool); gimp_blend_tool_update_graph (blend_tool); gimp_drawable_filter_apply (blend_tool->filter, NULL); } else if (key == GDK_MOD1_MASK) { gimp_tool_pop_status (tool, display); gimp_blend_tool_push_status (blend_tool, state, display); } }
static void gimp_blend_tool_button_press (GimpTool *tool, const GimpCoords *coords, guint32 time, GdkModifierType state, GimpButtonPressType press_type, GimpDisplay *display) { GimpBlendTool *blend_tool = GIMP_BLEND_TOOL (tool); if (tool->display && display != tool->display) { gimp_tool_pop_status (tool, tool->display); gimp_blend_tool_halt (blend_tool); } blend_tool->grabbed_point = gimp_blend_tool_get_point_under_cursor (blend_tool); if (blend_tool->grabbed_point == POINT_NONE && ! gimp_draw_tool_is_active (GIMP_DRAW_TOOL (tool))) { blend_tool->start_x = coords->x; blend_tool->start_y = coords->y; if (gimp_blend_tool_is_shapeburst (blend_tool)) { blend_tool->grabbed_point = POINT_FILL_MODE; } else { blend_tool->grabbed_point = POINT_INIT_MODE; } } else if ((state & GDK_MOD1_MASK) && gimp_draw_tool_is_active (GIMP_DRAW_TOOL (tool))) { blend_tool->grabbed_point = POINT_BOTH; } gimp_blend_tool_point_motion (blend_tool, state & gimp_get_constrain_behavior_mask ()); tool->display = display; gimp_blend_tool_update_items (blend_tool); if (blend_tool->grabbed_point != POINT_FILL_MODE && blend_tool->grabbed_point != POINT_INIT_MODE) { gimp_blend_tool_update_graph (blend_tool); gimp_drawable_filter_apply (blend_tool->filter, NULL); } gimp_tool_control_activate (tool->control); gimp_blend_tool_push_status (blend_tool, state, display); }
static void gimp_blend_tool_gradient_dirty (GimpBlendTool *blend_tool) { if (! blend_tool->filter) return; /* Set a property on the node. Otherwise it will cache and refuse to update */ gegl_node_set (blend_tool->render_node, "gradient", blend_tool->gradient, NULL); /* Update the filter */ gimp_drawable_filter_apply (blend_tool->filter, NULL); }
static void gimp_blend_tool_motion (GimpTool *tool, const GimpCoords *coords, guint32 time, GdkModifierType state, GimpDisplay *display) { GimpBlendTool *blend_tool = GIMP_BLEND_TOOL (tool); /* Save the mouse coordinates from last call */ gdouble last_x = blend_tool->mouse_x; gdouble last_y = blend_tool->mouse_y; blend_tool->mouse_x = coords->x; blend_tool->mouse_y = coords->y; if (blend_tool->grabbed_point == POINT_FILL_MODE || blend_tool->grabbed_point == POINT_INIT_MODE) { blend_tool->grabbed_point = POINT_END; gimp_blend_tool_start (blend_tool, display); } /* Move the whole line if alt is pressed */ if (blend_tool->grabbed_point == POINT_BOTH) { gdouble dx = last_x - coords->x; gdouble dy = last_y - coords->y; blend_tool->start_x -= dx; blend_tool->start_y -= dy; blend_tool->end_x -= dx; blend_tool->end_y -= dy; } else { gimp_blend_tool_point_motion (blend_tool, state & gimp_get_constrain_behavior_mask ()); } gimp_tool_pop_status (tool, display); gimp_blend_tool_push_status (blend_tool, state, display); gimp_blend_tool_update_items (blend_tool); gimp_blend_tool_update_graph (blend_tool); gimp_drawable_filter_apply (blend_tool->filter, NULL); }
static void gimp_warp_tool_stroke_changed (GeglPath *path, const GeglRectangle *roi, GimpWarpTool *wt) { GimpWarpOptions *options = GIMP_WARP_TOOL_GET_OPTIONS (wt); GeglRectangle update_region = *roi; update_region.x -= options->effect_size * 0.5; update_region.y -= options->effect_size * 0.5; update_region.width += options->effect_size; update_region.height += options->effect_size; #ifdef WARP_DEBUG g_printerr ("update rect: (%d,%d), %dx%d\n", update_region.x, update_region.y, update_region.width, update_region.height); #endif gimp_drawable_filter_apply (wt->filter, &update_region); }
static void gimp_warp_tool_update_stroke (GimpWarpTool *wt, GeglNode *node) { GeglPath *stroke; gdouble size; gegl_node_get (node, "stroke", &stroke, "size", &size, NULL); if (stroke) { gdouble min_x; gdouble max_x; gdouble min_y; gdouble max_y; GeglRectangle bbox; gegl_path_get_bounds (stroke, &min_x, &max_x, &min_y, &max_y); g_object_unref (stroke); bbox.x = min_x - size * 0.5; bbox.y = min_y - size * 0.5; bbox.width = max_x - min_x + size; bbox.height = max_y - min_y + size; #ifdef WARP_DEBUG g_printerr ("update stroke: (%d,%d), %dx%d\n", bbox.x, bbox.y, bbox.width, bbox.height); #endif gimp_drawable_filter_apply (wt->filter, &bbox); } }
static void gimp_seamless_clone_tool_filter_update (GimpSeamlessCloneTool *sc) { GimpTool *tool = GIMP_TOOL (sc); GimpDisplayShell *shell = gimp_display_get_shell (tool->display); GimpItem *item = GIMP_ITEM (tool->drawable); gint x, y; gint w, h; gint off_x, off_y; GeglRectangle visible; GeglOperation *op = NULL; GimpProgress *progress; GeglNode *output; GeglProcessor *processor; gdouble value; progress = gimp_progress_start (GIMP_PROGRESS (sc), FALSE, _("Cloning the foreground object")); /* Find out at which x,y is the top left corner of the currently * displayed part */ gimp_display_shell_untransform_viewport (shell, &x, &y, &w, &h); /* Find out where is our drawable positioned */ gimp_item_get_offset (item, &off_x, &off_y); /* Create a rectangle from the intersection of the currently displayed * part with the drawable */ gimp_rectangle_intersect (x, y, w, h, off_x, off_y, gimp_item_get_width (item), gimp_item_get_height (item), &visible.x, &visible.y, &visible.width, &visible.height); /* Since the filter_apply function receives a rectangle describing * where it should update the preview, and since that rectangle should * be relative to the drawable's location, we now offset back by the * drawable's offsetts. */ visible.x -= off_x; visible.y -= off_y; g_object_get (sc->sc_node, "gegl-operation", &op, NULL); /* If any cache of the visible area was present, clear it! * We need to clear the cache in the sc_node, since that is * where the previous paste was located */ gegl_operation_invalidate (op, &visible, TRUE); g_object_unref (op); /* Now update the image map and show this area */ gimp_drawable_filter_apply (sc->filter, NULL); /* Show update progress. */ output = gegl_node_get_output_proxy (sc->render_node, "output"); processor = gegl_node_new_processor (output, NULL); while (gegl_processor_work (processor, &value)) { if (progress) gimp_progress_set_value (progress, value); } if (progress) gimp_progress_end (progress); g_object_unref (processor); }
void gimp_drawable_edit_fill (GimpDrawable *drawable, GimpFillOptions *options, const gchar *undo_desc) { GimpContext *context; gint x, y, width, height; 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 */ } context = GIMP_CONTEXT (options); if (gimp_layer_mode_is_alpha_only (gimp_context_get_paint_mode (context))) { if (! gimp_drawable_has_alpha (drawable) || ! (gimp_drawable_get_active_mask (drawable) & GIMP_COMPONENT_MASK_ALPHA)) { return; /* nothing to do, but the fill succeeded */ } } if (! undo_desc) undo_desc = gimp_fill_options_get_undo_desc (options); /* check if we can fill the drawable's buffer directly */ if (gimp_drawable_edit_can_fill_direct (drawable, options)) { gimp_drawable_edit_fill_direct (drawable, options, undo_desc); gimp_drawable_update (drawable, x, y, width, height); } else { GeglNode *operation; GimpDrawableFilter *filter; gdouble opacity; GimpLayerMode mode; GimpLayerMode composite_mode; opacity = gimp_context_get_opacity (context); mode = gimp_context_get_paint_mode (context); composite_mode = gimp_layer_mode_get_paint_composite_mode (mode); operation = gegl_node_new_child (NULL, "operation", "gimp:fill-source", "options", options, "drawable", drawable, "pattern-offset-x", -x, "pattern-offset-y", -y, NULL); filter = gimp_drawable_filter_new (drawable, undo_desc, operation, NULL); gimp_drawable_filter_set_opacity (filter, opacity); gimp_drawable_filter_set_mode (filter, mode, GIMP_LAYER_COLOR_SPACE_AUTO, GIMP_LAYER_COLOR_SPACE_AUTO, composite_mode); gimp_drawable_filter_apply (filter, NULL); gimp_drawable_filter_commit (filter, NULL, FALSE); g_object_unref (filter); g_object_unref (operation); } }
static void gimp_warp_tool_animate (GimpWarpTool *wt) { GimpTool *tool = GIMP_TOOL (wt); GimpWarpOptions *options = GIMP_WARP_TOOL_GET_OPTIONS (wt); GimpImage *orig_image; GimpImage *image; GimpLayer *layer; GimpLayer *first_layer; GeglNode *scale_node; GimpProgress *progress; GtkWidget *widget; gint i; if (! gimp_warp_tool_get_undo_desc (tool, tool->display)) { gimp_tool_message_literal (tool, tool->display, _("Please add some warp strokes first.")); return; } /* get rid of the image map so we can use wt->graph */ if (wt->filter) { gimp_drawable_filter_abort (wt->filter); g_object_unref (wt->filter); wt->filter = NULL; } gimp_progress_start (GIMP_PROGRESS (tool), FALSE, _("Rendering Frame %d"), 1); orig_image = gimp_item_get_image (GIMP_ITEM (tool->drawable)); image = gimp_create_image (orig_image->gimp, gimp_item_get_width (GIMP_ITEM (tool->drawable)), gimp_item_get_height (GIMP_ITEM (tool->drawable)), gimp_drawable_get_base_type (tool->drawable), gimp_drawable_get_precision (tool->drawable), TRUE); /* the first frame is always the unwarped image */ layer = GIMP_LAYER (gimp_item_convert (GIMP_ITEM (tool->drawable), image, GIMP_TYPE_LAYER)); gimp_object_take_name (GIMP_OBJECT (layer), g_strdup_printf (_("Frame %d"), 1)); gimp_item_set_offset (GIMP_ITEM (layer), 0, 0); gimp_item_set_visible (GIMP_ITEM (layer), TRUE, FALSE); gimp_layer_set_mode (layer, GIMP_NORMAL_MODE, FALSE); gimp_layer_set_opacity (layer, GIMP_OPACITY_OPAQUE, FALSE); gimp_image_add_layer (image, layer, NULL, 0, FALSE); first_layer = layer; scale_node = gegl_node_new_child (NULL, "operation", "gimp:scalar-multiply", "n-components", 2, NULL); gimp_warp_tool_add_op (wt, scale_node); progress = gimp_sub_progress_new (GIMP_PROGRESS (tool)); for (i = 1; i < options->n_animation_frames; i++) { gimp_progress_set_text (GIMP_PROGRESS (tool), _("Rendering Frame %d"), i + 1); gimp_sub_progress_set_step (GIMP_SUB_PROGRESS (progress), i, options->n_animation_frames); layer = GIMP_LAYER (gimp_item_duplicate (GIMP_ITEM (first_layer), GIMP_TYPE_LAYER)); gimp_object_take_name (GIMP_OBJECT (layer), g_strdup_printf (_("Frame %d"), i + 1)); gegl_node_set (scale_node, "factor", (gdouble) i / (gdouble) (options->n_animation_frames - 1), NULL); gimp_gegl_apply_operation (gimp_drawable_get_buffer (GIMP_DRAWABLE (first_layer)), progress, _("Frame"), wt->graph, gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)), NULL); gimp_image_add_layer (image, layer, NULL, 0, FALSE); } g_object_unref (progress); gimp_warp_tool_remove_op (wt, scale_node); gimp_progress_end (GIMP_PROGRESS (tool)); /* recreate the image map */ gimp_warp_tool_create_filter (wt, tool->drawable); gimp_drawable_filter_apply (wt->filter, NULL); widget = GTK_WIDGET (gimp_display_get_shell (tool->display)); gimp_create_display (orig_image->gimp, image, GIMP_UNIT_PIXEL, 1.0, G_OBJECT (gtk_widget_get_screen (widget)), gimp_widget_get_monitor (widget)); g_object_unref (image); }