[gimp] app: cleanup in GimpSeamlessCloneTool
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: cleanup in GimpSeamlessCloneTool
- Date: Thu, 16 May 2013 22:56:31 +0000 (UTC)
commit 775ba72d7e80751e8d24e540cc99bc01363690b6
Author: Michael Natterer <mitch gimp org>
Date: Fri May 17 00:53:55 2013 +0200
app: cleanup in GimpSeamlessCloneTool
- fix some leaks
- actually free the op, seems to cause a crash
- formatting cleanup
- remove lots of comments
app/tools/gimpseamlessclonetool.c | 237 ++++++++++---------------------------
1 files changed, 60 insertions(+), 177 deletions(-)
---
diff --git a/app/tools/gimpseamlessclonetool.c b/app/tools/gimpseamlessclonetool.c
index daed880..ed73cb1 100644
--- a/app/tools/gimpseamlessclonetool.c
+++ b/app/tools/gimpseamlessclonetool.c
@@ -42,6 +42,7 @@
#include "core/gimplayer.h"
#include "core/gimpprogress.h"
#include "core/gimpprojection.h"
+#include "core/gimptoolinfo.h"
#include "widgets/gimphelp-ids.h"
#include "widgets/gimpclipboard.h"
@@ -179,7 +180,8 @@ static void gimp_seamless_clone_tool_create_render_node (GimpSeamlessClone
static void gimp_seamless_clone_tool_render_node_update (GimpSeamlessCloneTool *sc);
-G_DEFINE_TYPE (GimpSeamlessCloneTool, gimp_seamless_clone_tool, GIMP_TYPE_DRAW_TOOL)
+G_DEFINE_TYPE (GimpSeamlessCloneTool, gimp_seamless_clone_tool,
+ GIMP_TYPE_DRAW_TOOL)
#define parent_class gimp_seamless_clone_tool_parent_class
@@ -219,57 +221,26 @@ gimp_seamless_clone_tool_class_init (GimpSeamlessCloneToolClass *klass)
draw_tool_class->draw = gimp_seamless_clone_tool_draw;
}
-/**
- * gimp_seamless_clone_tool_init:
- * @self: The instance of the tool to initialize
- *
- * Initialize all the pointers to NULL, initialize the state machine,
- * moust cursor and the tool control object. This function will be
- * called on the first time the tool is being switched to.
- */
static void
gimp_seamless_clone_tool_init (GimpSeamlessCloneTool *self)
{
GimpTool *tool = GIMP_TOOL (self);
- /* TODO: If we want our tool to be invalidated by something, enable
- * the following line. Note that the enum of the dirty properties is
- * GimpDirtyMask which is located under app/core/core-enums.h */
-
-// gimp_tool_control_set_dirty_mask (tool->control,
-// GIMP_DIRTY_IMAGE |
-// GIMP_DIRTY_IMAGE_STRUCTURE |
-// GIMP_DIRTY_DRAWABLE |
-// GIMP_DIRTY_SELECTION);
-
- /* TODO: We do need click events, but so do all tools. What's this? */
- gimp_tool_control_set_wants_click (tool->control, TRUE);
+ gimp_tool_control_set_dirty_mask (tool->control,
+ GIMP_DIRTY_IMAGE |
+ GIMP_DIRTY_IMAGE_STRUCTURE |
+ GIMP_DIRTY_DRAWABLE |
+ GIMP_DIRTY_SELECTION);
gimp_tool_control_set_tool_cursor (tool->control,
GIMP_TOOL_CURSOR_MOVE);
- /* In order to achieve as much instant reponse as possible, only care
- * about the location of the mouse at present (while it's being moved)
- * and ignore motion events that happened while we were dealing with
- * previous motion events */
- gimp_tool_control_set_motion_mode (tool->control, GIMP_MOTION_MODE_COMPRESS);
-
- self->paste = NULL;
-
- self->render_node = NULL;
- self->sc_node = NULL;
+ gimp_tool_control_set_motion_mode (tool->control,
+ GIMP_MOTION_MODE_COMPRESS);
- self->tool_state = SC_STATE_INIT;
- self->image_map = NULL;
-
- self->xoff = self->yoff = self->width = self->height = 0;
+ self->tool_state = SC_STATE_INIT;
}
-/* This function is called when the tool should pause and resume it's
- * action, and when it should halt (i.e. stop and free all resources).
- * We are interested in this mainly because we want to free resources
- * when the tool terminates, and nothing else...
- */
static void
gimp_seamless_clone_tool_control (GimpTool *tool,
GimpToolAction action,
@@ -284,14 +255,9 @@ gimp_seamless_clone_tool_control (GimpTool *tool,
break;
case GIMP_TOOL_ACTION_HALT:
- /* We only have what to stop if we are active on some display */
- if (tool->display != NULL)
+ if (tool->display)
gimp_seamless_clone_tool_stop (sc, FALSE);
- /* Now, mark that we have no display, so any needed initialization
- * will happen on the next time a display is picked */
- tool->display = NULL;
-
/* TODO: If we have any tool options that should be reset, here is
* a good place to do so.
*/
@@ -302,47 +268,6 @@ gimp_seamless_clone_tool_control (GimpTool *tool,
}
/**
- * paste_to_gegl_buf:
- * @tool: The GimpTool which wishes to acquire the paste
- *
- * This function takes a GimpTool as a parameter, and using it's Gimp
- * object, it will convert the current buffer in the clipboard into a
- * GeglBuffer.
- *
- * Returns: A GeglBuffer* object representing the active paste in Gimp's
- * clipboard, or NULL if the clipboard does not contain image
- * data
- */
-static GeglBuffer*
-paste_to_gegl_buf (GimpTool *tool)
-{
- /* Here is a textual description of the graph we are going to create:
- *
- * +--------------------------------------+
- * |<tilemanager-source> <- paste |
- * | |output |
- * | +-----+------------+ |
- * | |input |input |
- * |<buffer-sink> <seamless-clone-prepare>|
- * | | | |
- * | v v |
- * | paste abstract_cache |
- * +--------------------------------------+
- */
- GimpContext *context = & gimp_tool_get_options (tool) -> parent_instance;
- GimpBuffer *buffer = gimp_clipboard_get_buffer (context->gimp);
- GeglBuffer *result = NULL;
-
- if (buffer)
- {
- result = gegl_buffer_dup (gimp_buffer_get_buffer (buffer));
-
- g_object_unref (buffer);
- }
-
- return result;
-}
-/**
* gimp_seamless_clone_tool_start:
* @sc: The GimpSeamlessCloneTool to initialize for usage on the given
* display
@@ -364,33 +289,30 @@ gimp_seamless_clone_tool_start (GimpSeamlessCloneTool *sc,
GimpDrawable *drawable = gimp_image_get_active_drawable (image);
/* First handle the paste - we need to make sure we have one in order
- * to do anything else. */
+ * to do anything else.
+ */
if (sc->paste == NULL)
{
- sc->paste = paste_to_gegl_buf (GIMP_TOOL (sc));
+ GimpBuffer *buffer = gimp_clipboard_get_buffer (tool->tool_info->gimp);
- if (sc->paste == NULL)
- {
- /* TODO: prompt for some error message */
- return;
- }
- else
- {
- sc->width = gegl_buffer_get_width (sc->paste);
- sc->height = gegl_buffer_get_height (sc->paste);
- }
+ if (! buffer)
+ /* TODO: prompt for some error message */
+ return;
+
+ sc->paste = gegl_buffer_dup (gimp_buffer_get_buffer (buffer));
+ g_object_unref (buffer);
+
+ sc->width = gegl_buffer_get_width (sc->paste);
+ sc->height = gegl_buffer_get_height (sc->paste);
}
/* Free resources which are relevant only for the previous display */
gimp_seamless_clone_tool_stop (sc, TRUE);
- /* Set the new tool display */
tool->display = display;
- /* Initialize the image map preview */
gimp_seamless_clone_tool_create_image_map (sc, drawable);
- /* Now call the start method of the draw tool */
gimp_draw_tool_start (GIMP_DRAW_TOOL (sc), display);
sc->tool_state = SC_STATE_RENDER_WAIT;
@@ -423,10 +345,7 @@ gimp_seamless_clone_tool_stop (GimpSeamlessCloneTool *sc,
if (! display_change_only)
{
- sc->render_node = NULL;
- sc->sc_node = NULL;
-
- sc->tool_state = SC_STATE_INIT;
+ sc->tool_state = SC_STATE_INIT;
if (sc->paste)
{
@@ -436,39 +355,21 @@ gimp_seamless_clone_tool_stop (GimpSeamlessCloneTool *sc,
if (sc->render_node)
{
- /* When the parent render_node is unreffed completly, it will
- * also free all of it's child nodes */
g_object_unref (sc->render_node);
sc->render_node = NULL;
- sc->sc_node = NULL;
+ sc->sc_node = NULL;
}
}
/* This should always happen, even when we just switch a display */
if (sc->image_map)
{
- /* This line makes sure the tool won't be aborted when the
- * active drawable is being switched.
- * Now, the question is why? We are currently handling an
- * abort signal, so unless somehow we can have two of these in
- * parallel, I don't see any reason to be afraid. Not that it
- * does any harm, but still.
- * TODO: check this?! */
-// gimp_tool_control_set_preserve (tool->control, TRUE);
-
- /* Stop the computation of the live preview, and mark it not
- * to be committed. Then free the image map object. */
gimp_image_map_abort (sc->image_map);
g_object_unref (sc->image_map);
sc->image_map = NULL;
- /* Revert the previous set_preserve */
-// gimp_tool_control_set_preserve (tool->control, FALSE);
-
if (GIMP_TOOL (sc)->display)
- {
- gimp_image_flush (gimp_display_get_image (GIMP_TOOL (sc)->display));
- }
+ gimp_image_flush (gimp_display_get_image (GIMP_TOOL (sc)->display));
}
gimp_draw_tool_stop (GIMP_DRAW_TOOL (sc));
@@ -479,20 +380,15 @@ gimp_seamless_clone_tool_options_notify (GimpTool *tool,
GimpToolOptions *options,
const GParamSpec *pspec)
{
- // GimpSeamlessCloneTool *sc = GIMP_SEAMLESS_CLONE_TOOL (tool);
-
GIMP_TOOL_CLASS (parent_class)->options_notify (tool, options, pspec);
if (! tool->display)
return;
- /* Pause the tool before modifying the tool data, so that drawing
- * won't be done using data in intermidiate states */
gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
/* TODO: Modify data here */
- /* Done modifying data? If so, now restore the tool drawing */
gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
}
@@ -521,7 +417,7 @@ gimp_seamless_clone_tool_key_press (GimpTool *tool,
* rectangle each time (in the update function) or by
* invalidating and re-rendering all now (expensive and
* perhaps useless */
- gimp_image_map_commit (sct->image_map, NULL);
+ gimp_image_map_commit (sct->image_map, GIMP_PROGRESS (tool));
g_object_unref (sct->image_map);
sct->image_map = NULL;
@@ -529,11 +425,13 @@ gimp_seamless_clone_tool_key_press (GimpTool *tool,
gimp_image_flush (gimp_display_get_image (display));
- gimp_seamless_clone_tool_control (tool, GIMP_TOOL_ACTION_HALT, display);
+ gimp_seamless_clone_tool_control (tool, GIMP_TOOL_ACTION_HALT,
+ display);
break;
case GDK_KEY_Escape:
- gimp_seamless_clone_tool_control (tool, GIMP_TOOL_ACTION_HALT, display);
+ gimp_seamless_clone_tool_control (tool, GIMP_TOOL_ACTION_HALT,
+ display);
break;
default:
@@ -552,13 +450,10 @@ gimp_seamless_clone_tool_motion (GimpTool *tool,
GdkModifierType state,
GimpDisplay *display)
{
- GimpSeamlessCloneTool *sc = GIMP_SEAMLESS_CLONE_TOOL (tool);
+ GimpSeamlessCloneTool *sc = GIMP_SEAMLESS_CLONE_TOOL (tool);
- /* Pause the tool before modifying the tool data, so that drawing
- * won't be done using data in intermidiate states */
gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
- /* There is nothing to do, unless we were actually moving a paste */
if (sc->tool_state == SC_STATE_RENDER_MOTION)
{
gimp_draw_tool_pause (GIMP_DRAW_TOOL (sc));
@@ -571,7 +466,6 @@ gimp_seamless_clone_tool_motion (GimpTool *tool,
gimp_seamless_clone_tool_image_map_update (sc);
}
- /* Done modifying data? If so, now restore the tool drawing */
gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
}
@@ -582,13 +476,10 @@ gimp_seamless_clone_tool_oper_update (GimpTool *tool,
gboolean proximity,
GimpDisplay *display)
{
- /* Pause the tool before modifying the tool data, so that drawing
- * won't be done using data in intermidiate states */
gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
/* TODO: Modify data here */
- /* Done modifying data? If so, now restore the tool drawing */
gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
}
@@ -605,23 +496,26 @@ gimp_seamless_clone_tool_button_press (GimpTool *tool,
if (display != tool->display)
{
gimp_seamless_clone_tool_start (sc, display);
+
/* Center the paste on the mouse */
sc->xoff = (gint) coords->x - sc->width / 2;
sc->yoff = (gint) coords->y - sc->height / 2;
}
- if (sc->tool_state == SC_STATE_RENDER_WAIT
- && gimp_seamless_clone_tool_is_in_paste_c (sc, coords))
+ if (sc->tool_state == SC_STATE_RENDER_WAIT &&
+ gimp_seamless_clone_tool_is_in_paste_c (sc, coords))
{
gimp_draw_tool_pause (GIMP_DRAW_TOOL (sc));
/* Record previous location, in case the user cancel's the
- * movement */
+ * movement
+ */
sc->xoff_p = sc->xoff;
sc->yoff_p = sc->yoff;
/* Record the mouse location, so that the dragging offset can be
- * calculated */
+ * calculated
+ */
sc->xclick = coords->x;
sc->yclick = coords->y;
@@ -631,7 +525,8 @@ gimp_seamless_clone_tool_button_press (GimpTool *tool,
sc->tool_state = SC_STATE_RENDER_MOTION;
/* In order to receive motion events from the current click, we must
- * activate the tool control */
+ * activate the tool control
+ */
gimp_tool_control_activate (tool->control);
}
}
@@ -644,12 +539,11 @@ gimp_seamless_clone_tool_button_release (GimpTool *tool,
GimpButtonReleaseType release_type,
GimpDisplay *display)
{
- GimpSeamlessCloneTool *sc = GIMP_SEAMLESS_CLONE_TOOL (tool);
+ GimpSeamlessCloneTool *sc = GIMP_SEAMLESS_CLONE_TOOL (tool);
/* There is nothing to do, unless we were actually moving a paste */
if (sc->tool_state == SC_STATE_RENDER_MOTION)
{
- /* Now, halt the tool control */
gimp_tool_control_halt (tool->control);
gimp_draw_tool_pause (GIMP_DRAW_TOOL (sc));
@@ -691,11 +585,14 @@ gimp_seamless_clone_tool_cursor_update (GimpTool *tool,
if (tool->display)
{
if (sc->tool_state == SC_STATE_RENDER_MOTION)
- modifier = GIMP_CURSOR_MODIFIER_MOVE;
-
- else if (sc->tool_state == SC_STATE_RENDER_WAIT
- && gimp_seamless_clone_tool_is_in_paste_c (sc, coords))
- modifier = GIMP_CURSOR_MODIFIER_NONE;
+ {
+ modifier = GIMP_CURSOR_MODIFIER_MOVE;
+ }
+ else if (sc->tool_state == SC_STATE_RENDER_WAIT &&
+ gimp_seamless_clone_tool_is_in_paste_c (sc, coords))
+ {
+ modifier = GIMP_CURSOR_MODIFIER_NONE;
+ }
gimp_tool_control_set_cursor_modifier (tool->control, modifier);
}
@@ -703,17 +600,16 @@ gimp_seamless_clone_tool_cursor_update (GimpTool *tool,
GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display);
}
-/* Draw any required on canvas interaction. For now, this is kept empty.
- * It's a place holder for the future of this tool, for some more
- * advanced features that may be added later */
static void
gimp_seamless_clone_tool_draw (GimpDrawTool *draw_tool)
{
GimpSeamlessCloneTool *sc = GIMP_SEAMLESS_CLONE_TOOL (draw_tool);
- if (sc->tool_state == SC_STATE_RENDER_WAIT || sc->tool_state == SC_STATE_RENDER_MOTION)
+ if (sc->tool_state == SC_STATE_RENDER_WAIT ||
+ sc->tool_state == SC_STATE_RENDER_MOTION)
{
- gimp_draw_tool_add_rectangle (draw_tool, FALSE, sc->xoff, sc->yoff, sc->width, sc->height);
+ gimp_draw_tool_add_rectangle (draw_tool, FALSE,
+ sc->xoff, sc->yoff, sc->width, sc->height);
}
}
@@ -798,25 +694,21 @@ gimp_seamless_clone_tool_render_node_update (GimpSeamlessCloneTool *sc)
/* Now we should also take into consideration the fact that
* we should work with coordinates relative to the background
- * buffer */
+ * buffer
+ */
gimp_item_get_offset (GIMP_ITEM (bg), &xoff, &yoff);
- /* The only thing to update right now, is the location of the paste */
gegl_node_set (sc->sc_node,
"xoff", (gint) sc->xoff - xoff,
"yoff", (gint) sc->yoff - yoff,
NULL);
}
-/* Create an image map to render the operation of the current tool with
- * a preview on the given drawable */
static void
gimp_seamless_clone_tool_create_image_map (GimpSeamlessCloneTool *sc,
GimpDrawable *drawable)
{
- /* First, make sure we actually have the GEGL graph needed to render
- * the operation's result */
- if (!sc->render_node)
+ if (! sc->render_node)
gimp_seamless_clone_tool_create_render_node (sc);
sc->image_map = gimp_image_map_new (drawable,
@@ -829,25 +721,15 @@ gimp_seamless_clone_tool_create_image_map (GimpSeamlessCloneTool *sc,
sc);
}
-/* Flush (Refresh) the image map preview */
static void
gimp_seamless_clone_tool_image_map_flush (GimpImageMap *image_map,
GimpTool *tool)
{
GimpImage *image = gimp_display_get_image (tool->display);
- gimp_projection_flush_now (gimp_image_get_projection (image));
- gimp_display_flush_now (tool->display);
+ gimp_projection_flush (gimp_image_get_projection (image));
}
-/**
- * gimp_seamless_clone_tool_image_map_update:
- * @sc: A GimpSeamlessCloneTool to update
- *
- * This functions updates the image map preview displayed by a given
- * GimpSeamlessCloneTool. The image_map must be initialized prior to the
- * call to this function!
- */
static void
gimp_seamless_clone_tool_image_map_update (GimpSeamlessCloneTool *sc)
{
@@ -891,6 +773,7 @@ gimp_seamless_clone_tool_image_map_update (GimpSeamlessCloneTool *sc)
* 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_image_map_apply (sc->image_map);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]