[gimp] app/vectors: implement stroke_reverse and stroke_shift_start



commit 44a7e929674fda7433fcdf378369ccbad3137c15
Author: Simon Budig <simon budig de>
Date:   Fri May 15 03:03:03 2020 +0200

    app/vectors: implement stroke_reverse and stroke_shift_start

 app/vectors/gimpbezierstroke.c | 64 ++++++++++++++++++++++++++++++++++++++++++
 app/vectors/gimpstroke.c       | 62 ++++++++++++++++++++++++++++++++++++++++
 app/vectors/gimpstroke.h       |  8 ++++++
 3 files changed, 134 insertions(+)
---
diff --git a/app/vectors/gimpbezierstroke.c b/app/vectors/gimpbezierstroke.c
index 0fd1256bed..113664575e 100644
--- a/app/vectors/gimpbezierstroke.c
+++ b/app/vectors/gimpbezierstroke.c
@@ -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,
diff --git a/app/vectors/gimpstroke.c b/app/vectors/gimpstroke.c
index 6d1f1159fa..a9725c5de6 100644
--- a/app/vectors/gimpstroke.c
+++ b/app/vectors/gimpstroke.c
@@ -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)
diff --git a/app/vectors/gimpstroke.h b/app/vectors/gimpstroke.h
index b220d77f35..69e14de74a 100644
--- a/app/vectors/gimpstroke.h
+++ b/app/vectors/gimpstroke.h
@@ -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,


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