app: IScissors: add struct ICurve for the entire curve and its state

This commit is contained in:
Michael Natterer 2015-03-27 21:37:57 +01:00
parent e6fe3ed3b0
commit 565b0af74d
2 changed files with 75 additions and 41 deletions

View File

@ -104,6 +104,13 @@ struct _ISegment
GPtrArray *points;
};
struct _ICurve
{
GQueue *segments;
gboolean first_point;
gboolean connected;
};
/* local function prototypes */
@ -198,6 +205,10 @@ static ISegment * isegment_new (gint x1,
gint y2);
static void isegment_free (ISegment *segment);
static ICurve * icurve_new (void);
static void icurve_clear (ICurve *curve);
static void icurve_free (ICurve *curve);
/* static variables */
@ -316,9 +327,9 @@ gimp_iscissors_tool_init (GimpIscissorsTool *iscissors)
gimp_tool_control_set_tool_cursor (tool->control,
GIMP_TOOL_CURSOR_ISCISSORS);
iscissors->op = ISCISSORS_OP_NONE;
iscissors->curves = g_queue_new ();
iscissors->state = NO_ACTION;
iscissors->op = ISCISSORS_OP_NONE;
iscissors->curve = icurve_new ();
iscissors->state = NO_ACTION;
}
static void
@ -326,7 +337,8 @@ gimp_iscissors_tool_finalize (GObject *object)
{
GimpIscissorsTool *iscissors = GIMP_ISCISSORS_TOOL (object);
g_queue_free (iscissors->curves);
icurve_free (iscissors->curve);
iscissors->curve = NULL;
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@ -410,7 +422,7 @@ gimp_iscissors_tool_button_press (GimpTool *tool,
gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
}
/* If the iscissors is connected, check if the click was inside */
else if (iscissors->connected && iscissors->mask &&
else if (iscissors->curve->connected && iscissors->mask &&
gimp_pickable_get_opacity_at (GIMP_PICKABLE (iscissors->mask),
iscissors->x,
iscissors->y))
@ -418,7 +430,7 @@ gimp_iscissors_tool_button_press (GimpTool *tool,
gimp_tool_control (tool, GIMP_TOOL_ACTION_COMMIT, display);
gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display);
}
else if (! iscissors->connected)
else if (! iscissors->curve->connected)
{
/* if we're not connected, we're adding a new point */
@ -446,7 +458,7 @@ iscissors_convert (GimpIscissorsTool *iscissors,
sc = gimp_scan_convert_new ();
for (list = g_queue_peek_tail_link (iscissors->curves);
for (list = g_queue_peek_tail_link (iscissors->curve->segments);
list;
list = g_list_previous (list))
{
@ -459,7 +471,7 @@ iscissors_convert (GimpIscissorsTool *iscissors,
n_total_points = 0;
/* go over the segments in reverse order, adding the points we have */
for (list = g_queue_peek_tail_link (iscissors->curves);
for (list = g_queue_peek_tail_link (iscissors->curve->segments);
list;
list = g_list_previous (list))
{
@ -524,12 +536,12 @@ gimp_iscissors_tool_button_release (GimpTool *tool,
{
case SEED_PLACEMENT:
/* Add a new segment */
if (! iscissors->first_point)
if (! iscissors->curve->first_point)
{
/* Determine if we're connecting to the first point */
if (! g_queue_is_empty (iscissors->curves))
if (! g_queue_is_empty (iscissors->curve->segments))
{
ISegment *segment = g_queue_peek_head (iscissors->curves);
ISegment *segment = g_queue_peek_head (iscissors->curve->segments);
if (gimp_draw_tool_on_handle (GIMP_DRAW_TOOL (tool), display,
iscissors->x, iscissors->y,
@ -541,7 +553,7 @@ gimp_iscissors_tool_button_release (GimpTool *tool,
{
iscissors->x = segment->x1;
iscissors->y = segment->y1;
iscissors->connected = TRUE;
iscissors->curve->connected = TRUE;
}
}
@ -557,14 +569,14 @@ gimp_iscissors_tool_button_release (GimpTool *tool,
iscissors->ix = iscissors->x;
iscissors->iy = iscissors->y;
g_queue_push_tail (iscissors->curves, segment);
g_queue_push_tail (iscissors->curve->segments, segment);
calculate_segment (iscissors, segment);
}
}
else /* this was our first point */
{
iscissors->first_point = FALSE;
iscissors->curve->first_point = FALSE;
}
break;
@ -597,7 +609,7 @@ gimp_iscissors_tool_button_release (GimpTool *tool,
gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
/* convert the curves into a region */
if (iscissors->connected)
if (iscissors->curve->connected)
iscissors_convert (iscissors, display);
}
@ -630,7 +642,7 @@ gimp_iscissors_tool_motion (GimpTool *tool,
iscissors->x = CLAMP (iscissors->x, 0, gimp_image_get_width (image) - 1);
iscissors->y = CLAMP (iscissors->y, 0, gimp_image_get_height (image) - 1);
if (iscissors->first_point)
if (iscissors->curve->first_point)
{
iscissors->ix = iscissors->x;
iscissors->iy = iscissors->y;
@ -674,7 +686,7 @@ gimp_iscissors_tool_draw (GimpDrawTool *draw_tool)
GIMP_HANDLE_ANCHOR_CENTER);
/* Draw a line boundary */
if (! iscissors->first_point)
if (! iscissors->curve->first_point)
{
if (! options->interactive)
{
@ -708,12 +720,12 @@ gimp_iscissors_tool_draw (GimpDrawTool *draw_tool)
}
}
if (! iscissors->first_point)
if (! iscissors->curve->first_point)
{
GList *list;
/* Draw a point at the init point coordinates */
if (! iscissors->connected)
if (! iscissors->curve->connected)
{
gimp_draw_tool_add_handle (draw_tool,
GIMP_HANDLE_FILLED_CIRCLE,
@ -725,7 +737,7 @@ gimp_iscissors_tool_draw (GimpDrawTool *draw_tool)
}
/* Go through the list of isegments, and render each one... */
for (list = g_queue_peek_head_link (iscissors->curves);
for (list = g_queue_peek_head_link (iscissors->curve->segments);
list;
list = g_list_next (list))
{
@ -844,7 +856,7 @@ gimp_iscissors_tool_oper_update (GimpTool *tool,
}
else if (mouse_over_segment (iscissors, coords->x, coords->y))
{
ISegment *segment = g_queue_peek_head (iscissors->curves);
ISegment *segment = g_queue_peek_head (iscissors->curve->segments);
if (gimp_draw_tool_on_handle (GIMP_DRAW_TOOL (tool), display,
RINT (coords->x), RINT (coords->y),
@ -865,7 +877,7 @@ gimp_iscissors_tool_oper_update (GimpTool *tool,
iscissors->op = ISCISSORS_OP_ADD_POINT;
}
}
else if (iscissors->connected && iscissors->mask)
else if (iscissors->curve->connected && iscissors->mask)
{
if (gimp_pickable_get_opacity_at (GIMP_PICKABLE (iscissors->mask),
RINT (coords->x),
@ -992,7 +1004,7 @@ gimp_iscissors_tool_key_press (GimpTool *tool,
case GDK_KEY_Return:
case GDK_KEY_KP_Enter:
case GDK_KEY_ISO_Enter:
if (iscissors->connected && iscissors->mask)
if (iscissors->curve->connected && iscissors->mask)
{
gimp_tool_control (tool, GIMP_TOOL_ACTION_COMMIT, display);
gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display);
@ -1013,11 +1025,8 @@ static void
gimp_iscissors_tool_halt (GimpIscissorsTool *iscissors,
GimpDisplay *display)
{
/* Free and reset the curve list */
while (! g_queue_is_empty (iscissors->curves))
{
isegment_free (g_queue_pop_head (iscissors->curves));
}
/* Free and reset the curve */
icurve_clear (iscissors->curve);
/* free mask */
if (iscissors->mask)
@ -1033,11 +1042,9 @@ gimp_iscissors_tool_halt (GimpIscissorsTool *iscissors,
iscissors->gradient_map = NULL;
}
iscissors->segment1 = NULL;
iscissors->segment2 = NULL;
iscissors->first_point = TRUE;
iscissors->connected = FALSE;
iscissors->state = NO_ACTION;
iscissors->segment1 = NULL;
iscissors->segment2 = NULL;
iscissors->state = NO_ACTION;
/* Reset the dp buffers */
if (iscissors->dp_buf)
@ -1055,7 +1062,7 @@ gimp_iscissors_tool_commit (GimpIscissorsTool *iscissors,
GimpSelectionOptions *options = GIMP_SELECTION_TOOL_GET_OPTIONS (tool);
GimpImage *image = gimp_display_get_image (display);
if (iscissors->connected && iscissors->mask)
if (iscissors->curve->connected && iscissors->mask)
{
gimp_channel_select_channel (gimp_image_get_mask (image),
tool->tool_info->blurb,
@ -1088,7 +1095,7 @@ mouse_over_vertex (GimpIscissorsTool *iscissors,
iscissors->segment1 = iscissors->segment2 = NULL;
for (list = g_queue_peek_head_link (iscissors->curves);
for (list = g_queue_peek_head_link (iscissors->curve->segments);
list;
list = g_list_next (list))
{
@ -1158,7 +1165,7 @@ mouse_over_segment (GimpIscissorsTool *iscissors,
/* traverse through the list, returning the curve segment's list element
* if the current cursor position is on a curve...
*/
for (list = g_queue_peek_head_link (iscissors->curves);
for (list = g_queue_peek_head_link (iscissors->curve->segments);
list;
list = g_list_next (list))
{
@ -1220,7 +1227,7 @@ clicked_on_segment (GimpIscissorsTool *iscissors,
segment->y2 = iscissors->y;
/* Create the new link and supply the new segment as data */
g_queue_insert_after (iscissors->curves, list, new_segment);
g_queue_insert_after (iscissors->curve->segments, list, new_segment);
iscissors->segment1 = new_segment;
iscissors->segment2 = segment;
@ -1727,3 +1734,32 @@ isegment_free (ISegment *segment)
g_slice_free (ISegment, segment);
}
static ICurve *
icurve_new (void)
{
ICurve *curve = g_slice_new0 (ICurve);
curve->segments = g_queue_new ();
curve->first_point = TRUE;
return curve;
}
static void
icurve_clear (ICurve *curve)
{
while (! g_queue_is_empty (curve->segments))
isegment_free (g_queue_pop_head (curve->segments));
curve->first_point = TRUE;
curve->connected = FALSE;
}
static void
icurve_free (ICurve *curve)
{
g_queue_free_full (curve->segments, (GDestroyNotify) isegment_free);
g_slice_free (ICurve, curve);
}

View File

@ -43,6 +43,7 @@ typedef enum
} IscissorsOps;
typedef struct _ISegment ISegment;
typedef struct _ICurve ICurve;
#define GIMP_TYPE_ISCISSORS_TOOL (gimp_iscissors_tool_get_type ())
@ -75,10 +76,7 @@ struct _GimpIscissorsTool
ISegment *segment1; /* 1st segment connected to current point */
ISegment *segment2; /* 2nd segment connected to current point */
GQueue *curves; /* the list of segments */
gboolean first_point; /* is this the first point? */
gboolean connected; /* is the region closed? */
ICurve *curve; /* the curve */
IscissorsState state; /* state of iscissors */