[gimp] app: npd-tool: add option to apply or cancel the deformation



commit 10255eddbb9de116fc79cd8ac57f74aba159d5f8
Author: Marek Dvoroznak <dvoromar gmail com>
Date:   Thu Sep 12 23:24:34 2013 +0200

    app: npd-tool: add option to apply or cancel the deformation

 app/display/gimpcanvasbufferpreview.c |   32 ++++++++----
 app/tools/gimpnpointdeformationtool.c |   90 ++++++++++++++++++++++++++-------
 app/tools/gimpnpointdeformationtool.h |    7 ++-
 3 files changed, 97 insertions(+), 32 deletions(-)
---
diff --git a/app/display/gimpcanvasbufferpreview.c b/app/display/gimpcanvasbufferpreview.c
index 9623204..b1db990 100644
--- a/app/display/gimpcanvasbufferpreview.c
+++ b/app/display/gimpcanvasbufferpreview.c
@@ -105,9 +105,9 @@ gimp_canvas_buffer_preview_init (GimpCanvasBufferPreview *transform_preview)
 
 static void
 gimp_canvas_buffer_preview_set_property (GObject      *object,
-                                            guint         property_id,
-                                            const GValue *value,
-                                            GParamSpec   *pspec)
+                                         guint         property_id,
+                                         const GValue *value,
+                                         GParamSpec   *pspec)
 {
   GimpCanvasBufferPreviewPrivate *private = GET_PRIVATE (object);
 
@@ -125,9 +125,9 @@ gimp_canvas_buffer_preview_set_property (GObject      *object,
 
 static void
 gimp_canvas_buffer_preview_get_property (GObject    *object,
-                                            guint       property_id,
-                                            GValue     *value,
-                                            GParamSpec *pspec)
+                                         guint       property_id,
+                                         GValue     *value,
+                                         GParamSpec *pspec)
 {
   GimpCanvasBufferPreviewPrivate *private = GET_PRIVATE (object);
 
@@ -147,14 +147,19 @@ static void
 gimp_canvas_buffer_preview_draw (GimpCanvasItem *item,
                                  cairo_t        *cr)
 {
-  GimpDisplayShell      *shell  = gimp_canvas_item_get_shell (item);
-  GeglBuffer            *buffer = GET_PRIVATE (item)->buffer;
+  GimpDisplayShell      *shell;
+  GeglBuffer            *buffer;
   cairo_surface_t       *area;
   guchar                *data;
   cairo_rectangle_int_t  rectangle;
   gint                   viewport_offset_x, viewport_offset_y;
   gint                   viewport_width,    viewport_height;
 
+  g_return_if_fail (GIMP_IS_CANVAS_ITEM (item));
+  shell = gimp_canvas_item_get_shell (item);
+  buffer = GET_PRIVATE (item)->buffer;
+  g_return_if_fail (GEGL_IS_BUFFER (buffer) && buffer != NULL);
+
   gimp_display_shell_scroll_get_scaled_viewport (shell,
                                                  &viewport_offset_x,
                                                  &viewport_offset_y,
@@ -174,7 +179,7 @@ gimp_canvas_buffer_preview_draw (GimpCanvasItem *item,
                                    rectangle.width,
                                    rectangle.height),
                    shell->scale_x,
-                   gegl_buffer_get_format (buffer), /* has to be cairo-ARGB32 */
+                   babl_format ("cairo-ARGB32"),
                    data,
                    cairo_image_surface_get_stride (area),
                    GEGL_ABYSS_NONE);
@@ -193,14 +198,19 @@ static void
 gimp_canvas_buffer_preview_compute_bounds (GimpCanvasItem *item,
                                            cairo_rectangle_int_t *bounds)
 {
-  GimpDisplayShell *shell  = gimp_canvas_item_get_shell (item);
-  GeglBuffer       *buffer = GET_PRIVATE (item)->buffer;
+  GimpDisplayShell *shell;
+  GeglBuffer       *buffer;
   gint              x_from, x_to;
   gint              y_from, y_to;
   gint              viewport_offset_x, viewport_offset_y;
   gint              viewport_width,    viewport_height;
   gint              width, height;
 
+  g_return_if_fail (GIMP_IS_CANVAS_ITEM (item));
+  shell = gimp_canvas_item_get_shell (item);
+  buffer = GET_PRIVATE (item)->buffer;
+  g_return_if_fail (GEGL_IS_BUFFER (buffer) && buffer != NULL);
+
   width  = gegl_buffer_get_width  (buffer);
   height = gegl_buffer_get_height (buffer);
 
diff --git a/app/tools/gimpnpointdeformationtool.c b/app/tools/gimpnpointdeformationtool.c
index 199174b..d9ed9d9 100644
--- a/app/tools/gimpnpointdeformationtool.c
+++ b/app/tools/gimpnpointdeformationtool.c
@@ -28,6 +28,8 @@
 
 #include "tools-types.h"
 
+#include "gegl/gimp-gegl-utils.h"
+
 #include "display/gimpdisplay.h"
 
 #include "core/gimp.h"
@@ -59,6 +61,7 @@
 #define GIMP_NPD_DEBUG
 #define GIMP_NPD_MAXIMUM_DEFORMATION_DELAY 100000 /* 100000 microseconds == 10 FPS */
 #define GIMP_NPD_DRAW_INTERVAL                 50 /*     50 milliseconds == 20 FPS */
+#define GIMP_NPD_STRING "N-Point Deformation"
 
 void            gimp_n_point_deformation_tool_start                   (GimpNPointDeformationTool *npd_tool,
                                                                        GimpDisplay               *display);
@@ -108,9 +111,9 @@ static void     gimp_n_point_deformation_tool_motion                  (GimpTool
                                                                        GimpDisplay               *display);
 static void     gimp_n_point_deformation_tool_clear_selected_points_list
                                                                       (GimpNPointDeformationTool *npd_tool);
-gboolean        gimp_n_point_deformation_tool_add_cp_to_selection     (GimpNPointDeformationTool *npd_tool,
+static gboolean gimp_n_point_deformation_tool_add_cp_to_selection     (GimpNPointDeformationTool *npd_tool,
                                                                        NPDControlPoint           *cp);
-gboolean        gimp_n_point_deformation_tool_is_cp_in_area           (NPDControlPoint           *cp,
+static gboolean gimp_n_point_deformation_tool_is_cp_in_area           (NPDControlPoint           *cp,
                                                                        gfloat                     x0,
                                                                        gfloat                     y0,
                                                                        gfloat                     x1,
@@ -127,6 +130,7 @@ gboolean        gimp_n_point_deformation_tool_canvas_update_thread_func
 static void     gimp_n_point_deformation_tool_perform_deformation     (GimpNPointDeformationTool *npd_tool);
 static void     gimp_n_point_deformation_tool_halt_threads            (GimpNPointDeformationTool *npd_tool);
 GimpCanvasItem *gimp_n_point_deformation_tool_add_preview             (GimpNPointDeformationTool *npd_tool);
+static void     gimp_n_point_deformation_tool_apply_deformation       (GimpNPointDeformationTool *npd_tool);
 
 #ifdef GIMP_NPD_DEBUG
 #define gimp_npd_debug(x) g_printf x
@@ -148,7 +152,7 @@ gimp_n_point_deformation_tool_register (GimpToolRegisterCallback  callback,
                 gimp_n_point_deformation_options_gui,
                 0,
                 "gimp-n-point-deformation-tool",
-                _("N-Point Deformation"),
+                _(GIMP_NPD_STRING),
                 _("N-Point Deformation Tool: Rubber-like deformation of an image using points"),
                 N_("_N-Point Deformation"), "<shift>N",
                 NULL, GIMP_HELP_TOOL_N_POINT_DEFORMATION,
@@ -185,7 +189,6 @@ gimp_n_point_deformation_tool_init (GimpNPointDeformationTool *npd_tool)
   gimp_tool_control_set_preserve             (tool->control, FALSE);
   gimp_tool_control_set_wants_click          (tool->control, TRUE);
   gimp_tool_control_set_wants_all_key_events (tool->control, TRUE);
-  gimp_tool_control_set_scroll_lock          (tool->control, TRUE);
   gimp_tool_control_set_handle_empty_image   (tool->control, FALSE);
   gimp_tool_control_set_dirty_mask           (tool->control,
                                               GIMP_DIRTY_IMAGE           |
@@ -194,7 +197,8 @@ gimp_n_point_deformation_tool_init (GimpNPointDeformationTool *npd_tool)
                                               GIMP_DIRTY_SELECTION       |
                                               GIMP_DIRTY_ACTIVE_DRAWABLE);
 
-  npd_tool->active    = FALSE;
+  npd_tool->active             = FALSE;
+  npd_tool->deformation_active = FALSE;
 }
 
 static void
@@ -243,12 +247,13 @@ gimp_n_point_deformation_tool_start (GimpNPointDeformationTool *npd_tool,
 
   npd_tool->active = TRUE;
 
-  image         = gimp_display_get_image (display);
-  drawable      = gimp_image_get_active_drawable (image);
-  source_buffer = gimp_drawable_get_buffer (drawable);
+  /* create GEGL graph */
+  image          = gimp_display_get_image (display);
+  drawable       = gimp_image_get_active_drawable (image);
+  source_buffer  = gegl_buffer_dup (gimp_drawable_get_buffer (drawable));
 
-  preview_buffer  = gegl_buffer_new (gegl_buffer_get_extent (source_buffer),
-                                     babl_format ("cairo-ARGB32"));
+  preview_buffer = gegl_buffer_new (gegl_buffer_get_extent (source_buffer),
+                                    babl_format ("cairo-ARGB32"));
 
   graph    = gegl_node_new ();
 
@@ -279,8 +284,10 @@ gimp_n_point_deformation_tool_start (GimpNPointDeformationTool *npd_tool,
   npd_tool->drawable               = drawable;
   npd_tool->graph                  = graph;
   npd_tool->model                  = model;
-  npd_tool->node                   = node;
+  npd_tool->source                 = source;
+  npd_tool->npd_node               = node;
   npd_tool->sink                   = sink;
+  npd_tool->source_buffer          = source_buffer;
   npd_tool->preview_buffer         = preview_buffer;
   npd_tool->selected_cp            = NULL;
   npd_tool->hovering_cp            = NULL;
@@ -321,6 +328,8 @@ gimp_n_point_deformation_tool_halt (GimpNPointDeformationTool *npd_tool)
 
   gimp_n_point_deformation_tool_halt_threads (npd_tool);
 
+  npd_tool->active = FALSE;
+
   if (gimp_draw_tool_is_active (draw_tool))
     gimp_draw_tool_stop (draw_tool);
 
@@ -328,6 +337,11 @@ gimp_n_point_deformation_tool_halt (GimpNPointDeformationTool *npd_tool)
     gimp_tool_control_halt (tool->control);  
   
   gimp_n_point_deformation_tool_clear_selected_points_list (npd_tool);
+
+  g_object_unref (npd_tool->graph);
+  g_object_unref (npd_tool->source_buffer);
+  g_object_unref (npd_tool->preview_buffer);
+  npd_tool->preview_buffer = NULL;
   
   if (npd_tool->model != NULL)
     npd_destroy_model (npd_tool->model);
@@ -365,7 +379,7 @@ gimp_n_point_deformation_tool_options_notify (GimpTool         *tool,
   gimp_draw_tool_pause (draw_tool);
 
   gimp_npd_debug (("npd options notify\n"));
-  gimp_n_point_deformation_tool_set_options (npd_tool->node, npd_options);
+  gimp_n_point_deformation_tool_set_options (npd_tool->npd_node, npd_options);
 
   gimp_draw_tool_resume (draw_tool);
 }
@@ -408,9 +422,10 @@ gimp_n_point_deformation_tool_key_press (GimpTool    *tool,
     case GDK_KEY_ISO_Enter:
       gimp_n_point_deformation_tool_halt_threads (npd_tool);
 
-      npd_options->mesh_visible = FALSE;
-      gimp_n_point_deformation_tool_set_options (npd_tool->node,
-                                                 npd_options);
+      gimp_tool_control_push_preserve (tool->control, TRUE);
+      gimp_n_point_deformation_tool_apply_deformation (npd_tool);
+      gimp_tool_control_pop_preserve (tool->control);
+
       gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display);
       break;
 
@@ -672,6 +687,7 @@ gimp_n_point_deformation_tool_button_release (GimpTool             *tool,
   else
   if (release_type == GIMP_BUTTON_RELEASE_CANCEL)
     {
+      gimp_npd_debug (("gimp_button_release_cancel\n"));
     }
   
   npd_tool->rubber_band = FALSE;
@@ -840,7 +856,7 @@ gimp_n_point_deformation_tool_canvas_update_thread_func (GimpNPointDeformationTo
           gtk_widget_get_window (gimp_display_get_shell (npd_tool->display)->canvas),
           FALSE);
   gimp_npd_debug (("canvas update thread stop\n"));
-  
+
   return TRUE;
 }
 
@@ -851,7 +867,9 @@ gimp_n_point_deformation_tool_deform_thread_func (gpointer data)
   GimpNPointDeformationOptions *npd_options = GIMP_N_POINT_DEFORMATION_TOOL_GET_OPTIONS (npd_tool);
   guint64                       start, duration;
 
-  while (npd_tool->active) {
+  npd_tool->deformation_active = TRUE;
+
+  while (npd_tool->deformation_active) {
     start = g_get_monotonic_time ();
 
     /* perform the deformation only if the tool hasn't been paused */
@@ -876,7 +894,7 @@ static void
 gimp_n_point_deformation_tool_perform_deformation (GimpNPointDeformationTool *npd_tool)
 {
   gimp_npd_debug (("gegl_node_invalidated\n"));
-  gegl_node_invalidated (npd_tool->node, NULL, FALSE);
+  gegl_node_invalidated (npd_tool->npd_node, NULL, FALSE);
 
   gimp_npd_debug (("gegl_node_process\n"));
   gegl_node_process (npd_tool->sink);
@@ -885,8 +903,10 @@ gimp_n_point_deformation_tool_perform_deformation (GimpNPointDeformationTool *np
 static void
 gimp_n_point_deformation_tool_halt_threads (GimpNPointDeformationTool *npd_tool)
 {
+  if (!npd_tool->deformation_active) return;
+
   gimp_npd_debug (("waiting for deform thread to finish\n"));
-  npd_tool->active = FALSE;
+  npd_tool->deformation_active = FALSE;
 
   /* wait for deformation thread to finish its work */
   g_thread_join (npd_tool->deform_thread);
@@ -902,6 +922,8 @@ gimp_n_point_deformation_tool_add_preview  (GimpNPointDeformationTool *npd_tool)
   GimpCanvasItem *item;
   GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (npd_tool);
 
+  if (!npd_tool->preview_buffer) return;
+
   item = gimp_canvas_buffer_preview_new (gimp_display_get_shell (draw_tool->display),
                                          npd_tool->preview_buffer);
 
@@ -909,4 +931,34 @@ gimp_n_point_deformation_tool_add_preview  (GimpNPointDeformationTool *npd_tool)
   g_object_unref (item);
 
   return item;
+}
+
+static void
+gimp_n_point_deformation_tool_apply_deformation (GimpNPointDeformationTool *npd_tool)
+{
+  GimpNPointDeformationOptions *npd_options = GIMP_N_POINT_DEFORMATION_TOOL_GET_OPTIONS (npd_tool);
+  GeglBuffer                   *buffer      = gimp_drawable_get_buffer(npd_tool->drawable);
+  GimpImage                    *image       = gimp_display_get_image (npd_tool->display);
+  gint                          width, height;
+
+  width  = gegl_buffer_get_width  (buffer);
+  height = gegl_buffer_get_height (buffer);
+
+  npd_options->mesh_visible = FALSE;
+  gimp_n_point_deformation_tool_set_options (npd_tool->npd_node,
+                                             npd_options);
+
+  gimp_drawable_push_undo (npd_tool->drawable, _(GIMP_NPD_STRING), NULL,
+                           0, 0, width, height);
+
+
+  gimp_gegl_apply_operation (NULL, NULL, _(GIMP_NPD_STRING),
+                             npd_tool->npd_node,
+                             gimp_drawable_get_buffer (npd_tool->drawable),
+                             NULL);
+
+  gimp_drawable_update (npd_tool->drawable,
+                        0, 0, width, height);
+
+  gimp_projection_flush (gimp_image_get_projection (image));
 }
\ No newline at end of file
diff --git a/app/tools/gimpnpointdeformationtool.h b/app/tools/gimpnpointdeformationtool.h
index e36284f..5633651 100644
--- a/app/tools/gimpnpointdeformationtool.h
+++ b/app/tools/gimpnpointdeformationtool.h
@@ -47,10 +47,12 @@ struct _GimpNPointDeformationTool
   GThread          *deform_thread;
 
   GeglNode         *graph;
-  GeglNode         *node;
+  GeglNode         *source;
+  GeglNode         *npd_node;
   GeglNode         *sink;
 
   GeglBuffer       *preview_buffer;
+  GeglBuffer       *source_buffer;
 
   GimpDrawable     *drawable;
 
@@ -74,7 +76,8 @@ struct _GimpNPointDeformationTool
   GList            *previous_cps_positions; /* list of NPDPoints holding previous
                                              * positions of control points */
 
-  volatile gboolean active;
+  gboolean          active;
+  volatile gboolean deformation_active;
   gboolean          rubber_band;
 };
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]