app/vectors: implement stroke_reverse and stroke_shift_start

This commit is contained in:
Simon Budig 2020-05-15 03:03:03 +02:00
parent 185dd8ba2e
commit 44a7e92967
3 changed files with 134 additions and 0 deletions

View File

@ -129,6 +129,11 @@ static gboolean
GimpAnchor *anchor,
GimpStroke *extension,
GimpAnchor *neighbor);
static gboolean
gimp_bezier_stroke_reverse (GimpStroke *stroke);
static gboolean
gimp_bezier_stroke_shift_start (GimpStroke *stroke,
GimpAnchor *anchor);
static GArray *
gimp_bezier_stroke_interpolate (GimpStroke *stroke,
gdouble precision,
@ -176,6 +181,8 @@ gimp_bezier_stroke_class_init (GimpBezierStrokeClass *klass)
stroke_class->is_extendable = gimp_bezier_stroke_is_extendable;
stroke_class->extend = gimp_bezier_stroke_extend;
stroke_class->connect_stroke = gimp_bezier_stroke_connect_stroke;
stroke_class->reverse = gimp_bezier_stroke_reverse;
stroke_class->shift_start = gimp_bezier_stroke_shift_start;
stroke_class->interpolate = gimp_bezier_stroke_interpolate;
stroke_class->make_bezier = gimp_bezier_stroke_make_bezier;
stroke_class->transform = gimp_bezier_stroke_transform;
@ -1324,6 +1331,63 @@ gimp_bezier_stroke_connect_stroke (GimpStroke *stroke,
}
static gboolean
gimp_bezier_stroke_reverse (GimpStroke *stroke)
{
g_return_val_if_fail (GIMP_IS_BEZIER_STROKE (stroke), FALSE);
g_queue_reverse (stroke->anchors);
/* keep the first nodegroup the same for closed strokes */
if (stroke->closed && stroke->anchors->length >= 3)
{
g_queue_push_head_link (stroke->anchors,
g_queue_pop_tail_link (stroke->anchors));
g_queue_push_head_link (stroke->anchors,
g_queue_pop_tail_link (stroke->anchors));
g_queue_push_head_link (stroke->anchors,
g_queue_pop_tail_link (stroke->anchors));
}
return TRUE;
}
static gboolean
gimp_bezier_stroke_shift_start (GimpStroke *stroke,
GimpAnchor *new_start)
{
GList *link;
g_return_val_if_fail (GIMP_IS_BEZIER_STROKE (stroke), FALSE);
g_return_val_if_fail (new_start != NULL, FALSE);
g_return_val_if_fail (new_start->type == GIMP_ANCHOR_ANCHOR, FALSE);
link = g_queue_find (stroke->anchors, new_start);
if (!link)
return FALSE;
/* the preceding control anchor will be the new head */
link = g_list_previous (link);
if (!link)
return FALSE;
if (link == stroke->anchors->head)
return TRUE;
stroke->anchors->tail->next = stroke->anchors->head;
stroke->anchors->head->prev = stroke->anchors->tail;
stroke->anchors->tail = link->prev;
stroke->anchors->head = link;
stroke->anchors->tail->next = NULL;
stroke->anchors->head->prev = NULL;
return TRUE;
}
static void
gimp_bezier_stroke_anchor_move_relative (GimpStroke *stroke,
GimpAnchor *anchor,

View File

@ -123,6 +123,9 @@ gboolean gimp_stroke_real_connect_stroke (GimpStroke *stroke,
static gboolean gimp_stroke_real_is_empty (GimpStroke *stroke);
static gboolean gimp_stroke_real_reverse (GimpStroke *stroke);
static gboolean gimp_stroke_real_shift_start (GimpStroke *stroke,
GimpAnchor *anchor);
static gdouble gimp_stroke_real_get_length (GimpStroke *stroke,
gdouble precision);
@ -213,6 +216,8 @@ gimp_stroke_class_init (GimpStrokeClass *klass)
klass->connect_stroke = gimp_stroke_real_connect_stroke;
klass->is_empty = gimp_stroke_real_is_empty;
klass->reverse = gimp_stroke_real_reverse;
klass->shift_start = gimp_stroke_real_shift_start;
klass->get_length = gimp_stroke_real_get_length;
klass->get_distance = gimp_stroke_real_get_distance;
klass->get_point_at_dist = gimp_stroke_real_get_point_at_dist;
@ -893,6 +898,63 @@ gimp_stroke_real_is_empty (GimpStroke *stroke)
}
gboolean
gimp_stroke_reverse (GimpStroke *stroke)
{
g_return_val_if_fail (GIMP_IS_STROKE (stroke), FALSE);
return GIMP_STROKE_GET_CLASS (stroke)->reverse (stroke);
}
static gboolean
gimp_stroke_real_reverse (GimpStroke *stroke)
{
g_queue_reverse (stroke->anchors);
/* keep the first node the same for closed strokes */
if (stroke->closed && stroke->anchors->length > 0)
g_queue_push_head_link (stroke->anchors,
g_queue_pop_tail_link (stroke->anchors));
return TRUE;
}
gboolean
gimp_stroke_shift_start (GimpStroke *stroke,
GimpAnchor *new_start)
{
g_return_val_if_fail (GIMP_IS_STROKE (stroke), FALSE);
g_return_val_if_fail (new_start != NULL, FALSE);
return GIMP_STROKE_GET_CLASS (stroke)->shift_start (stroke, new_start);
}
static gboolean
gimp_stroke_real_shift_start (GimpStroke *stroke,
GimpAnchor *new_start)
{
GList *link;
link = g_queue_find (stroke->anchors, new_start);
if (!link)
return FALSE;
if (link == stroke->anchors->head)
return TRUE;
stroke->anchors->tail->next = stroke->anchors->head;
stroke->anchors->head->prev = stroke->anchors->tail;
stroke->anchors->tail = link->prev;
stroke->anchors->head = link;
stroke->anchors->tail->next = NULL;
stroke->anchors->head->prev = NULL;
return TRUE;
}
gdouble
gimp_stroke_get_length (GimpStroke *stroke,
gdouble precision)

View File

@ -132,6 +132,10 @@ struct _GimpStrokeClass
GimpAnchor *neighbor);
gboolean (* is_empty) (GimpStroke *stroke);
gboolean (* reverse) (GimpStroke *stroke);
gboolean (* shift_start) (GimpStroke *stroke,
GimpAnchor *new_start);
gdouble (* get_length) (GimpStroke *stroke,
gdouble precision);
gdouble (* get_distance) (GimpStroke *stroke,
@ -289,6 +293,10 @@ gboolean gimp_stroke_connect_stroke (GimpStroke *stroke,
gboolean gimp_stroke_is_empty (GimpStroke *stroke);
gboolean gimp_stroke_reverse (GimpStroke *stroke);
gboolean gimp_stroke_shift_start (GimpStroke *stroke,
GimpAnchor *new_start);
/* accessing the shape of the curve */
gdouble gimp_stroke_get_length (GimpStroke *stroke,