[gimp] app: allow gimp_stroke_transform() to result in multiple strokes



commit d9ec9386ce57c0e4fd0993221cbe759241089940
Author: Ell <ell_se yahoo com>
Date:   Sat Feb 3 05:08:32 2018 -0500

    app: allow gimp_stroke_transform() to result in multiple strokes
    
    The next commit is going to perform clipping when transforming
    Bezier strokes.  When parts of the stroke get clipped, the result
    consists of multiple strokes.
    
    Adapt gimp_stroke_transform() in preparation, to allow for the
    transformation to result in multiple strokes, by adding a GQueue*
    parameter that receives the transformed strokes.
    
    For convenience, we allow passing NULL as the argument, in which
    case the current behavior is maintained.  However, NULL should only
    be passed when clipping is known to be unnecessary.
    
    Adapt the rest of the code for the change.
    
    Note that this technically affects public API: existing stroke
    object IDs now become invalid after transforming their containing
    vectors object.  However, this is unlikely to affect code in
    practice.

 app/vectors/gimpstroke.c         |   35 ++++++++++++++++++++++++++++-------
 app/vectors/gimpstroke.h         |    6 ++++--
 app/vectors/gimpvectors-import.c |    2 +-
 app/vectors/gimpvectors.c        |   30 ++++++++++++++++++++++++++----
 4 files changed, 59 insertions(+), 14 deletions(-)
---
diff --git a/app/vectors/gimpstroke.c b/app/vectors/gimpstroke.c
index 150f558..b5a6554 100644
--- a/app/vectors/gimpstroke.c
+++ b/app/vectors/gimpstroke.c
@@ -153,7 +153,8 @@ static void         gimp_stroke_real_flip_free       (GimpStroke       *stroke,
                                                       gdouble           x2,
                                                       gdouble           y2);
 static void         gimp_stroke_real_transform       (GimpStroke        *stroke,
-                                                      const GimpMatrix3 *matrix);
+                                                      const GimpMatrix3 *matrix,
+                                                      GQueue            *ret_strokes);
 
 static GList    * gimp_stroke_real_get_draw_anchors  (GimpStroke       *stroke);
 static GList    * gimp_stroke_real_get_draw_controls (GimpStroke       *stroke);
@@ -1098,7 +1099,7 @@ gimp_stroke_real_rotate (GimpStroke *stroke,
   gimp_matrix3_identity (&matrix);
   gimp_transform_matrix_rotate_center (&matrix, center_x, center_y, angle);
 
-  gimp_stroke_transform (stroke, &matrix);
+  gimp_stroke_transform (stroke, &matrix, NULL);
 }
 
 void
@@ -1120,7 +1121,7 @@ gimp_stroke_real_flip (GimpStroke          *stroke,
 
   gimp_matrix3_identity (&matrix);
   gimp_transform_matrix_flip (&matrix, flip_type, axis);
-  gimp_stroke_transform (stroke, &matrix);
+  gimp_stroke_transform (stroke, &matrix, NULL);
 }
 
 void
@@ -1148,21 +1149,34 @@ gimp_stroke_real_flip_free (GimpStroke *stroke,
   gimp_matrix3_identity (&matrix);
   gimp_transform_matrix_flip_free (&matrix, x1, y1, x2, y2);
 
-  gimp_stroke_transform (stroke, &matrix);
+  gimp_stroke_transform (stroke, &matrix, NULL);
 }
 
+/* transforms 'stroke' by 'matrix'.  due to clipping, the transformation may
+ * result in multiple strokes.
+ *
+ * if 'ret_strokes' is not NULL, the transformed strokes are appended to the
+ * queue, and 'stroke' is left in an unspecified state.  one of the resulting
+ * strokes may alias 'stroke'.
+ *
+ * if 'ret_strokes' is NULL, the transformation is performed in-place.  if the
+ * transformation results in multiple strokes (which, atm, can only happen for
+ * non-affine transformation), the result is undefined.
+ */
 void
 gimp_stroke_transform (GimpStroke        *stroke,
-                       const GimpMatrix3 *matrix)
+                       const GimpMatrix3 *matrix,
+                       GQueue            *ret_strokes)
 {
   g_return_if_fail (GIMP_IS_STROKE (stroke));
 
-  GIMP_STROKE_GET_CLASS (stroke)->transform (stroke, matrix);
+  GIMP_STROKE_GET_CLASS (stroke)->transform (stroke, matrix, ret_strokes);
 }
 
 static void
 gimp_stroke_real_transform (GimpStroke        *stroke,
-                            const GimpMatrix3 *matrix)
+                            const GimpMatrix3 *matrix,
+                            GQueue            *ret_strokes)
 {
   GList *list;
 
@@ -1176,6 +1190,13 @@ gimp_stroke_real_transform (GimpStroke        *stroke,
                                     &anchor->position.x,
                                     &anchor->position.y);
     }
+
+  if (ret_strokes)
+    {
+      stroke->ID = 0;
+
+      g_queue_push_tail (ret_strokes, g_object_ref (stroke));
+    }
 }
 
 
diff --git a/app/vectors/gimpstroke.h b/app/vectors/gimpstroke.h
index 022ead0..be29c45 100644
--- a/app/vectors/gimpstroke.h
+++ b/app/vectors/gimpstroke.h
@@ -169,7 +169,8 @@ struct _GimpStrokeClass
                                           gdouble                x2,
                                           gdouble                y2);
   void          (* transform)            (GimpStroke            *stroke,
-                                          const GimpMatrix3     *matrix);
+                                          const GimpMatrix3     *matrix,
+                                          GQueue                *ret_strokes);
 
   GList       * (* get_draw_anchors)     (GimpStroke            *stroke);
   GList       * (* get_draw_controls)    (GimpStroke            *stroke);
@@ -330,7 +331,8 @@ void         gimp_stroke_flip_free            (GimpStroke            *stroke,
                                                gdouble                x2,
                                                gdouble                y2);
 void         gimp_stroke_transform            (GimpStroke            *stroke,
-                                               const GimpMatrix3     *matrix);
+                                               const GimpMatrix3     *matrix,
+                                               GQueue                *ret_strokes);
 
 
 GList      * gimp_stroke_get_draw_anchors     (GimpStroke            *stroke);
diff --git a/app/vectors/gimpvectors-import.c b/app/vectors/gimpvectors-import.c
index f56f006..ccf3d02 100644
--- a/app/vectors/gimpvectors-import.c
+++ b/app/vectors/gimpvectors-import.c
@@ -486,7 +486,7 @@ svg_parser_end_element (GMarkupParseContext  *context,
 
               for (list = path->strokes; list; list = list->next)
                 gimp_stroke_transform (GIMP_STROKE (list->data),
-                                       handler->transform);
+                                       handler->transform, NULL);
             }
 
           g_slice_free (GimpMatrix3, handler->transform);
diff --git a/app/vectors/gimpvectors.c b/app/vectors/gimpvectors.c
index 3a332c7..7cf8271 100644
--- a/app/vectors/gimpvectors.c
+++ b/app/vectors/gimpvectors.c
@@ -559,7 +559,7 @@ gimp_vectors_flip (GimpItem            *item,
     {
       GimpStroke *stroke = list->data;
 
-      gimp_stroke_transform (stroke, &matrix);
+      gimp_stroke_transform (stroke, &matrix, NULL);
     }
 
   gimp_vectors_thaw (vectors);
@@ -590,7 +590,7 @@ gimp_vectors_rotate (GimpItem         *item,
     {
       GimpStroke *stroke = list->data;
 
-      gimp_stroke_transform (stroke, &matrix);
+      gimp_stroke_transform (stroke, &matrix, NULL);
     }
 
   gimp_vectors_thaw (vectors);
@@ -607,6 +607,7 @@ gimp_vectors_transform (GimpItem               *item,
 {
   GimpVectors *vectors = GIMP_VECTORS (item);
   GimpMatrix3  local_matrix;
+  GQueue       strokes;
   GList       *list;
 
   gimp_vectors_freeze (vectors);
@@ -620,13 +621,34 @@ gimp_vectors_transform (GimpItem               *item,
   if (direction == GIMP_TRANSFORM_BACKWARD)
     gimp_matrix3_invert (&local_matrix);
 
-  for (list = vectors->strokes->head; list; list = g_list_next (list))
+  g_queue_init (&strokes);
+
+  while (! g_queue_is_empty (vectors->strokes))
+    {
+      GimpStroke *stroke = g_queue_peek_head (vectors->strokes);
+
+      g_object_ref (stroke);
+
+      gimp_vectors_stroke_remove (vectors, stroke);
+
+      gimp_stroke_transform (stroke, &local_matrix, &strokes);
+
+      g_object_unref (stroke);
+    }
+
+  vectors->last_stroke_ID = 0;
+
+  for (list = strokes.head; list; list = g_list_next (list))
     {
       GimpStroke *stroke = list->data;
 
-      gimp_stroke_transform (stroke, &local_matrix);
+      gimp_vectors_stroke_add (vectors, stroke);
+
+      g_object_unref (stroke);
     }
 
+  g_queue_clear (&strokes);
+
   gimp_vectors_thaw (vectors);
 }
 


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