app: change most of Iscissors to use a GimpPickable not a GimpImage

This is just cleanup and enables adding a mode that doesn't behave like
"sample merged".
This commit is contained in:
Michael Natterer 2016-10-07 01:18:16 +02:00
parent fbb6b5d425
commit 152c5a2c44
3 changed files with 81 additions and 66 deletions

View File

@ -164,14 +164,14 @@ static void gimp_iscissors_tool_push_undo (GimpIscissorsTool *
static void gimp_iscissors_tool_pop_undo (GimpIscissorsTool *iscissors); static void gimp_iscissors_tool_pop_undo (GimpIscissorsTool *iscissors);
static void gimp_iscissors_tool_free_redo (GimpIscissorsTool *iscissors); static void gimp_iscissors_tool_free_redo (GimpIscissorsTool *iscissors);
static void gimp_iscissors_tool_halt (GimpIscissorsTool *iscissors, static void gimp_iscissors_tool_halt (GimpIscissorsTool *iscissors,
GimpDisplay *display); GimpDisplay *display);
static void gimp_iscissors_tool_commit (GimpIscissorsTool *iscissors, static void gimp_iscissors_tool_commit (GimpIscissorsTool *iscissors,
GimpDisplay *display); GimpDisplay *display);
static void iscissors_convert (GimpIscissorsTool *iscissors, static void iscissors_convert (GimpIscissorsTool *iscissors,
GimpDisplay *display); GimpDisplay *display);
static GeglBuffer * gradient_map_new (GimpImage *image); static GeglBuffer * gradient_map_new (GimpPickable *pickable);
static void find_optimal_path (GeglBuffer *gradient_map, static void find_optimal_path (GeglBuffer *gradient_map,
GimpTempBuf *dp_buf, GimpTempBuf *dp_buf,
@ -182,7 +182,7 @@ static void find_optimal_path (GeglBuffer *gradient_map,
gint xs, gint xs,
gint ys); gint ys);
static void find_max_gradient (GimpIscissorsTool *iscissors, static void find_max_gradient (GimpIscissorsTool *iscissors,
GimpImage *image, GimpPickable *pickable,
gint *x, gint *x,
gint *y); gint *y);
static void calculate_segment (GimpIscissorsTool *iscissors, static void calculate_segment (GimpIscissorsTool *iscissors,
@ -418,7 +418,7 @@ gimp_iscissors_tool_button_press (GimpTool *tool,
iscissors->state = SEED_PLACEMENT; iscissors->state = SEED_PLACEMENT;
if (! (state & gimp_get_extend_selection_mask ())) if (! (state & gimp_get_extend_selection_mask ()))
find_max_gradient (iscissors, image, find_max_gradient (iscissors, GIMP_PICKABLE (image),
&iscissors->x, &iscissors->y); &iscissors->x, &iscissors->y);
iscissors->x = CLAMP (iscissors->x, 0, gimp_image_get_width (image) - 1); iscissors->x = CLAMP (iscissors->x, 0, gimp_image_get_width (image) - 1);
@ -743,7 +743,7 @@ gimp_iscissors_tool_motion (GimpTool *tool,
/* Hold the shift key down to disable the auto-edge snap feature */ /* Hold the shift key down to disable the auto-edge snap feature */
if (! (state & gimp_get_extend_selection_mask ())) if (! (state & gimp_get_extend_selection_mask ()))
find_max_gradient (iscissors, image, find_max_gradient (iscissors, GIMP_PICKABLE (image),
&iscissors->x, &iscissors->y); &iscissors->x, &iscissors->y);
iscissors->x = CLAMP (iscissors->x, 0, gimp_image_get_width (image) - 1); iscissors->x = CLAMP (iscissors->x, 0, gimp_image_get_width (image) - 1);
@ -1481,13 +1481,22 @@ static void
calculate_segment (GimpIscissorsTool *iscissors, calculate_segment (GimpIscissorsTool *iscissors,
ISegment *segment) ISegment *segment)
{ {
GimpDisplay *display = GIMP_TOOL (iscissors)->display; GimpDisplay *display = GIMP_TOOL (iscissors)->display;
GimpImage *image = gimp_display_get_image (display); GimpPickable *pickable = GIMP_PICKABLE (gimp_display_get_image (display));
gint x, y, dir; gint width;
gint xs, ys, xe, ye; gint height;
gint x1, y1, x2, y2; gint xs, ys, xe, ye;
gint width, height; gint x1, y1, x2, y2;
gint ewidth, eheight; gint ewidth, eheight;
/* Initialise the gradient map buffer for this pickable if we don't
* already have one.
*/
if (! iscissors->gradient_map)
iscissors->gradient_map = gradient_map_new (pickable);
width = gegl_buffer_get_width (iscissors->gradient_map);
height = gegl_buffer_get_height (iscissors->gradient_map);
/* Calculate the lowest cost path from one vertex to the next as specified /* Calculate the lowest cost path from one vertex to the next as specified
* by the parameter "segment". * by the parameter "segment".
@ -1500,10 +1509,10 @@ calculate_segment (GimpIscissorsTool *iscissors,
*/ */
/* Get the bounding box */ /* Get the bounding box */
xs = CLAMP (segment->x1, 0, gimp_image_get_width (image) - 1); xs = CLAMP (segment->x1, 0, width - 1);
ys = CLAMP (segment->y1, 0, gimp_image_get_height (image) - 1); ys = CLAMP (segment->y1, 0, height - 1);
xe = CLAMP (segment->x2, 0, gimp_image_get_width (image) - 1); xe = CLAMP (segment->x2, 0, width - 1);
ye = CLAMP (segment->y2, 0, gimp_image_get_height (image) - 1); ye = CLAMP (segment->y2, 0, height - 1);
x1 = MIN (xs, xe); x1 = MIN (xs, xe);
y1 = MIN (ys, ye); y1 = MIN (ys, ye);
x2 = MAX (xs, xe) + 1; /* +1 because if xe = 199 & xs = 0, x2 - x1, width = 200 */ x2 = MAX (xs, xe) + 1; /* +1 because if xe = 199 & xs = 0, x2 - x1, width = 200 */
@ -1520,12 +1529,12 @@ calculate_segment (GimpIscissorsTool *iscissors,
eheight = (y2 - y1) * EXTEND_BY + FIXED; eheight = (y2 - y1) * EXTEND_BY + FIXED;
if (xe >= xs) if (xe >= xs)
x2 += CLAMP (ewidth, 0, gimp_image_get_width (image) - x2); x2 += CLAMP (ewidth, 0, width - x2);
else else
x1 -= CLAMP (ewidth, 0, x1); x1 -= CLAMP (ewidth, 0, x1);
if (ye >= ys) if (ye >= ys)
y2 += CLAMP (eheight, 0, gimp_image_get_height (image) - y2); y2 += CLAMP (eheight, 0, height - y2);
else else
y1 -= CLAMP (eheight, 0, y1); y1 -= CLAMP (eheight, 0, y1);
@ -1536,22 +1545,18 @@ calculate_segment (GimpIscissorsTool *iscissors,
segment->points = NULL; segment->points = NULL;
} }
/* If the bounding box has width and height... */
if ((x2 - x1) && (y2 - y1)) if ((x2 - x1) && (y2 - y1))
{ {
width = (x2 - x1); /* If the bounding box has width and height... */
height = (y2 - y1);
/* Initialise the gradient map tile manager for this image if we gint bb_width = (x2 - x1);
* don't already have one. */ gint bb_height = (y2 - y1);
if (! iscissors->gradient_map)
iscissors->gradient_map = gradient_map_new (image);
/* allocate the dynamic programming array */ /* allocate the dynamic programming array */
if (iscissors->dp_buf) if (iscissors->dp_buf)
gimp_temp_buf_unref (iscissors->dp_buf); gimp_temp_buf_unref (iscissors->dp_buf);
iscissors->dp_buf = gimp_temp_buf_new (width, height, iscissors->dp_buf = gimp_temp_buf_new (bb_width, bb_height,
babl_format ("Y u32")); babl_format ("Y u32"));
/* find the optimal path of pixels from (x1, y1) to (x2, y2) */ /* find the optimal path of pixels from (x1, y1) to (x2, y2) */
@ -1562,12 +1567,14 @@ calculate_segment (GimpIscissorsTool *iscissors,
segment->points = plot_pixels (iscissors, iscissors->dp_buf, segment->points = plot_pixels (iscissors, iscissors->dp_buf,
x1, y1, xs, ys, xe, ye); x1, y1, xs, ys, xe, ye);
} }
/* If the bounding box has no width */
else if ((x2 - x1) == 0) else if ((x2 - x1) == 0)
{ {
/* If the bounding box has no width */
/* plot a vertical line */ /* plot a vertical line */
y = ys; gint y = ys;
dir = (ys > ye) ? -1 : 1; gint dir = (ys > ye) ? -1 : 1;
segment->points = g_ptr_array_new (); segment->points = g_ptr_array_new ();
while (y != ye) while (y != ye)
{ {
@ -1575,12 +1582,14 @@ calculate_segment (GimpIscissorsTool *iscissors,
y += dir; y += dir;
} }
} }
/* If the bounding box has no height */
else if ((y2 - y1) == 0) else if ((y2 - y1) == 0)
{ {
/* If the bounding box has no height */
/* plot a horizontal line */ /* plot a horizontal line */
x = xs; gint x = xs;
dir = (xs > xe) ? -1 : 1; gint dir = (xs > xe) ? -1 : 1;
segment->points = g_ptr_array_new (); segment->points = g_ptr_array_new ();
while (x != xe) while (x != xe)
{ {
@ -1853,25 +1862,27 @@ find_optimal_path (GeglBuffer *gradient_map,
} }
static GeglBuffer * static GeglBuffer *
gradient_map_new (GimpImage *image) gradient_map_new (GimpPickable *pickable)
{ {
GeglBuffer *buffer; GeglBuffer *buffer;
GeglTileHandler *handler; GeglTileHandler *handler;
buffer = gimp_pickable_get_buffer (pickable);
buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
gimp_image_get_width (image), gegl_buffer_get_width (buffer),
gimp_image_get_height (image)), gegl_buffer_get_height (buffer)),
babl_format_n (babl_type ("u8"), 2)); babl_format_n (babl_type ("u8"), 2));
handler = gimp_tile_handler_iscissors_new (image); handler = gimp_tile_handler_iscissors_new (pickable);
gimp_tile_handler_validate_assign (GIMP_TILE_HANDLER_VALIDATE (handler), gimp_tile_handler_validate_assign (GIMP_TILE_HANDLER_VALIDATE (handler),
buffer); buffer);
gimp_tile_handler_validate_invalidate (GIMP_TILE_HANDLER_VALIDATE (handler), gimp_tile_handler_validate_invalidate (GIMP_TILE_HANDLER_VALIDATE (handler),
0, 0, 0, 0,
gimp_image_get_width (image), gegl_buffer_get_width (buffer),
gimp_image_get_height (image)); gegl_buffer_get_height (buffer));
g_object_unref (handler); g_object_unref (handler);
@ -1880,32 +1891,37 @@ gradient_map_new (GimpImage *image)
static void static void
find_max_gradient (GimpIscissorsTool *iscissors, find_max_gradient (GimpIscissorsTool *iscissors,
GimpImage *image, GimpPickable *pickable,
gint *x, gint *x,
gint *y) gint *y)
{ {
GeglBufferIterator *iter; GeglBufferIterator *iter;
GeglRectangle *roi; GeglRectangle *roi;
gint width;
gint height;
gint radius; gint radius;
gint cx, cy; gint cx, cy;
gint x1, y1, x2, y2; gint x1, y1, x2, y2;
gfloat max_gradient; gfloat max_gradient;
/* Initialise the gradient map buffer for this image if we don't /* Initialise the gradient map buffer for this pickable if we don't
* already have one. * already have one.
*/ */
if (! iscissors->gradient_map) if (! iscissors->gradient_map)
iscissors->gradient_map = gradient_map_new (image); iscissors->gradient_map = gradient_map_new (pickable);
width = gegl_buffer_get_width (iscissors->gradient_map);
height = gegl_buffer_get_height (iscissors->gradient_map);
radius = GRADIENT_SEARCH >> 1; radius = GRADIENT_SEARCH >> 1;
/* calculate the extent of the search */ /* calculate the extent of the search */
cx = CLAMP (*x, 0, gimp_image_get_width (image)); cx = CLAMP (*x, 0, width);
cy = CLAMP (*y, 0, gimp_image_get_height (image)); cy = CLAMP (*y, 0, height);
x1 = CLAMP (cx - radius, 0, gimp_image_get_width (image)); x1 = CLAMP (cx - radius, 0, width);
y1 = CLAMP (cy - radius, 0, gimp_image_get_height (image)); y1 = CLAMP (cy - radius, 0, height);
x2 = CLAMP (cx + radius, 0, gimp_image_get_width (image)); x2 = CLAMP (cx + radius, 0, width);
y2 = CLAMP (cy + radius, 0, gimp_image_get_height (image)); y2 = CLAMP (cy + radius, 0, height);
/* calculate the factor to multiply the distance from the cursor by */ /* calculate the factor to multiply the distance from the cursor by */
max_gradient = 0; max_gradient = 0;

View File

@ -28,7 +28,6 @@
#include "gegl/gimp-gegl-loops.h" #include "gegl/gimp-gegl-loops.h"
#include "core/gimpimage.h"
#include "core/gimppickable.h" #include "core/gimppickable.h"
#include "gimptilehandleriscissors.h" #include "gimptilehandleriscissors.h"
@ -37,7 +36,7 @@
enum enum
{ {
PROP_0, PROP_0,
PROP_IMAGE PROP_PICKABLE
}; };
@ -78,9 +77,9 @@ gimp_tile_handler_iscissors_class_init (GimpTileHandlerIscissorsClass *klass)
validate_class->validate = gimp_tile_handler_iscissors_validate; validate_class->validate = gimp_tile_handler_iscissors_validate;
g_object_class_install_property (object_class, PROP_IMAGE, g_object_class_install_property (object_class, PROP_PICKABLE,
g_param_spec_object ("image", NULL, NULL, g_param_spec_object ("pickable", NULL, NULL,
GIMP_TYPE_IMAGE, GIMP_TYPE_PICKABLE,
GIMP_PARAM_READWRITE | GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY)); G_PARAM_CONSTRUCT_ONLY));
} }
@ -95,10 +94,10 @@ gimp_tile_handler_iscissors_finalize (GObject *object)
{ {
GimpTileHandlerIscissors *iscissors = GIMP_TILE_HANDLER_ISCISSORS (object); GimpTileHandlerIscissors *iscissors = GIMP_TILE_HANDLER_ISCISSORS (object);
if (iscissors->image) if (iscissors->pickable)
{ {
g_object_unref (iscissors->image); g_object_unref (iscissors->pickable);
iscissors->image = NULL; iscissors->pickable = NULL;
} }
G_OBJECT_CLASS (parent_class)->finalize (object); G_OBJECT_CLASS (parent_class)->finalize (object);
@ -114,8 +113,8 @@ gimp_tile_handler_iscissors_set_property (GObject *object,
switch (property_id) switch (property_id)
{ {
case PROP_IMAGE: case PROP_PICKABLE:
iscissors->image = g_value_dup_object (value); iscissors->pickable = g_value_dup_object (value);
break; break;
default: default:
@ -134,8 +133,8 @@ gimp_tile_handler_iscissors_get_property (GObject *object,
switch (property_id) switch (property_id)
{ {
case PROP_IMAGE: case PROP_PICKABLE:
g_value_set_object (value, iscissors->image); g_value_set_object (value, iscissors->pickable);
break; break;
default: default:
@ -197,9 +196,9 @@ gimp_tile_handler_iscissors_validate (GimpTileHandlerValidate *validate,
rect->height); rect->height);
#endif #endif
gimp_pickable_flush (GIMP_PICKABLE (iscissors->image)); gimp_pickable_flush (iscissors->pickable);
src = gimp_pickable_get_buffer (GIMP_PICKABLE (iscissors->image)); src = gimp_pickable_get_buffer (iscissors->pickable);
temp0 = gegl_buffer_new (GEGL_RECTANGLE (0, 0, temp0 = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
rect->width, rect->width,
@ -321,12 +320,12 @@ gimp_tile_handler_iscissors_validate (GimpTileHandlerValidate *validate,
} }
GeglTileHandler * GeglTileHandler *
gimp_tile_handler_iscissors_new (GimpImage *image) gimp_tile_handler_iscissors_new (GimpPickable *pickable)
{ {
g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), NULL);
return g_object_new (GIMP_TYPE_TILE_HANDLER_ISCISSORS, return g_object_new (GIMP_TYPE_TILE_HANDLER_ISCISSORS,
"whole-tile", TRUE, "whole-tile", TRUE,
"image", image, "pickable", pickable,
NULL); NULL);
} }

View File

@ -42,7 +42,7 @@ struct _GimpTileHandlerIscissors
{ {
GimpTileHandlerValidate parent_instance; GimpTileHandlerValidate parent_instance;
GimpImage *image; GimpPickable *pickable;
}; };
struct _GimpTileHandlerIscissorsClass struct _GimpTileHandlerIscissorsClass
@ -53,7 +53,7 @@ struct _GimpTileHandlerIscissorsClass
GType gimp_tile_handler_iscissors_get_type (void) G_GNUC_CONST; GType gimp_tile_handler_iscissors_get_type (void) G_GNUC_CONST;
GeglTileHandler * gimp_tile_handler_iscissors_new (GimpImage *image); GeglTileHandler * gimp_tile_handler_iscissors_new (GimpPickable *pickable);
#endif /* __GIMP_TILE_HANDLER_ISCISSORS_H__ */ #endif /* __GIMP_TILE_HANDLER_ISCISSORS_H__ */