[gtk/wip/otte/lottie: 40/86] pathbuilder: Redo semantics for starting curves




commit 6a3afd9808fca82a75f573538b6bd1c892fdb299
Author: Benjamin Otte <otte redhat com>
Date:   Sat Nov 28 06:46:26 2020 +0100

    pathbuilder: Redo semantics for starting curves
    
    We now always have a "current point" which is either the last point an
    operation was made to, or (0, 0) if no drawing operation has
    been made yet.
    
    Adding a contour of any kind to the builder will always update the
    current point to that contour's end point.

 gsk/gskpath.c        | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 gsk/gskpathbuilder.c | 41 +++++++++++++++++++++++---------------
 gsk/gskpathprivate.h |  3 +++
 3 files changed, 84 insertions(+), 16 deletions(-)
---
diff --git a/gsk/gskpath.c b/gsk/gskpath.c
index 95a92a8998..bee9f2601c 100644
--- a/gsk/gskpath.c
+++ b/gsk/gskpath.c
@@ -54,6 +54,9 @@ struct _GskContourClass
                                                  GString                *string);
   gboolean              (* get_bounds)          (const GskContour       *contour,
                                                  graphene_rect_t        *bounds);
+  void                  (* get_start_end)       (const GskContour       *self,
+                                                 graphene_point_t       *start,
+                                                 graphene_point_t       *end);
   gboolean              (* foreach)             (const GskContour       *contour,
                                                  float                   tolerance,
                                                  GskPathForeachFunc      func,
@@ -214,6 +217,20 @@ gsk_rect_contour_get_bounds (const GskContour *contour,
   return TRUE;
 }
 
+static void
+gsk_rect_contour_get_start_end (const GskContour *contour,
+                                graphene_point_t *start,
+                                graphene_point_t *end)
+{
+  const GskRectContour *self = (const GskRectContour *) contour;
+
+  if (start)
+    *start = GRAPHENE_POINT_INIT (self->x, self->y);
+
+  if (end)
+    *end = GRAPHENE_POINT_INIT (self->x, self->y);
+}
+
 static gboolean
 gsk_rect_contour_foreach (const GskContour   *contour,
                           float               tolerance,
@@ -472,6 +489,7 @@ static const GskContourClass GSK_RECT_CONTOUR_CLASS =
   gsk_rect_contour_get_flags,
   gsk_rect_contour_print,
   gsk_rect_contour_get_bounds,
+  gsk_rect_contour_get_start_end,
   gsk_rect_contour_foreach,
   gsk_rect_contour_init_measure,
   gsk_rect_contour_free_measure,
@@ -564,6 +582,20 @@ gsk_circle_contour_get_bounds (const GskContour *contour,
   return TRUE;
 }
 
+static void
+gsk_circle_contour_get_start_end (const GskContour *contour,
+                                  graphene_point_t *start,
+                                  graphene_point_t *end)
+{
+  const GskCircleContour *self = (const GskCircleContour *) contour;
+
+  if (start)
+    *start = GSK_CIRCLE_POINT_INIT (self, self->start_angle);
+
+  if (end)
+    *end = GSK_CIRCLE_POINT_INIT (self, self->end_angle);
+}
+
 typedef struct
 {
   GskPathForeachFunc func;
@@ -758,6 +790,7 @@ static const GskContourClass GSK_CIRCLE_CONTOUR_CLASS =
   gsk_circle_contour_get_flags,
   gsk_circle_contour_print,
   gsk_circle_contour_get_bounds,
+  gsk_circle_contour_get_start_end,
   gsk_circle_contour_foreach,
   gsk_circle_contour_init_measure,
   gsk_circle_contour_free_measure,
@@ -944,6 +977,20 @@ gsk_standard_contour_get_bounds (const GskContour *contour,
   return bounds->size.width > 0 && bounds->size.height > 0;
 }
 
+static void
+gsk_standard_contour_get_start_end (const GskContour *contour,
+                                    graphene_point_t *start,
+                                    graphene_point_t *end)
+{
+  const GskStandardContour *self = (const GskStandardContour *) contour;
+
+  if (start)
+    *start = self->points[0];
+
+  if (end)
+    *end = self->points[self->n_points - 1];
+}
+
 typedef struct
 {
   float start;
@@ -1398,6 +1445,7 @@ static const GskContourClass GSK_STANDARD_CONTOUR_CLASS =
   gsk_standard_contour_get_flags,
   gsk_standard_contour_print,
   gsk_standard_contour_get_bounds,
+  gsk_standard_contour_get_start_end,
   gsk_standard_contour_foreach,
   gsk_standard_contour_init_measure,
   gsk_standard_contour_free_measure,
@@ -1484,6 +1532,14 @@ gsk_contour_free_measure (GskPath  *path,
   self->klass->free_measure (self, data);
 }
 
+void
+gsk_contour_get_start_end (const GskContour *self,
+                           graphene_point_t *start,
+                           graphene_point_t *end)
+{
+  self->klass->get_start_end (self, start, end);
+}
+
 void
 gsk_contour_get_point (GskPath          *path,
                        gsize             i,
diff --git a/gsk/gskpathbuilder.c b/gsk/gskpathbuilder.c
index b985f09e37..90672bd1f9 100644
--- a/gsk/gskpathbuilder.c
+++ b/gsk/gskpathbuilder.c
@@ -77,6 +77,7 @@ struct _GskPathBuilder
   GSList *contours; /* (reverse) list of already recorded contours */
 
   GskPathFlags flags; /* flags for the current path */
+  graphene_point_t current_point; /* the point all drawing ops start from */
   GArray *ops; /* operations for current contour - size == 0 means no current contour */
   GArray *points; /* points for the operations */
 };
@@ -106,6 +107,10 @@ gsk_path_builder_new (void)
 
   builder->ops = g_array_new (FALSE, FALSE, sizeof (GskStandardOperation));
   builder->points = g_array_new (FALSE, FALSE, sizeof (graphene_point_t));
+
+  /* Be explicit here */
+  builder->current_point = GRAPHENE_POINT_INIT (0, 0);
+
   return builder;
 }
 
@@ -132,18 +137,29 @@ gsk_path_builder_ref (GskPathBuilder *builder)
   return builder;
 }
 
+static void
+gsk_path_builder_ensure_current (GskPathBuilder *builder)
+{
+  if (builder->ops->len != 0)
+    return;
+
+  builder->flags = GSK_PATH_FLAT;
+  g_array_append_vals (builder->ops, &(GskStandardOperation) { GSK_PATH_MOVE, 0 }, 1);
+  g_array_append_val (builder->points, builder->current_point);
+}
+
 static void
 gsk_path_builder_append_current (GskPathBuilder         *builder,
                                  GskPathOperation        op,
                                  gsize                   n_points,
                                  const graphene_point_t *points)
 {
-  g_assert (builder->ops->len > 0);
-  g_assert (builder->points->len > 0);
-  g_assert (n_points > 0);
+  gsk_path_builder_ensure_current (builder);
 
   g_array_append_vals (builder->ops, &(GskStandardOperation) { op, builder->points->len - 1 }, 1);
   g_array_append_vals (builder->points, points, n_points);
+
+  builder->current_point = points[n_points - 1];
 }
 
 static void
@@ -314,6 +330,8 @@ gsk_path_builder_add_rect (GskPathBuilder        *builder,
 
   contour = gsk_rect_contour_new (rect);
   gsk_path_builder_add_contour (builder, contour);
+
+  gsk_contour_get_start_end (contour, NULL, &builder->current_point);
 }
 
 /**
@@ -360,9 +378,9 @@ gsk_path_builder_move_to (GskPathBuilder *builder,
 
   gsk_path_builder_end_current (builder);
 
-  builder->flags = GSK_PATH_FLAT;
-  g_array_append_vals (builder->ops, &(GskStandardOperation) { GSK_PATH_MOVE, 0 }, 1);
-  g_array_append_val (builder->points, GRAPHENE_POINT_INIT(x, y));
+  builder->current_point = GRAPHENE_POINT_INIT(x, y);
+
+  gsk_path_builder_ensure_current (builder);
 }
 
 /**
@@ -381,14 +399,8 @@ gsk_path_builder_line_to (GskPathBuilder *builder,
 {
   g_return_if_fail (builder != NULL);
 
-  if (builder->ops->len == 0)
-    {
-      gsk_path_builder_move_to (builder, x, y);
-      return;
-    }
-
   /* skip the line if it goes to the same point */
-  if (graphene_point_equal (&g_array_index (builder->points, graphene_point_t, builder->points->len - 1),
+  if (graphene_point_equal (&builder->current_point,
                             &GRAPHENE_POINT_INIT (x, y)))
     return;
 
@@ -424,9 +436,6 @@ gsk_path_builder_curve_to (GskPathBuilder *builder,
 {
   g_return_if_fail (builder != NULL);
 
-  if (builder->ops->len == 0)
-    gsk_path_builder_move_to (builder, x1, y1);
-
   builder->flags &= ~GSK_PATH_FLAT;
   gsk_path_builder_append_current (builder,
                                    GSK_PATH_CURVE,
diff --git a/gsk/gskpathprivate.h b/gsk/gskpathprivate.h
index d987c90fc1..cdb4a76243 100644
--- a/gsk/gskpathprivate.h
+++ b/gsk/gskpathprivate.h
@@ -73,6 +73,9 @@ gpointer                gsk_contour_init_measure                (GskPath
 void                    gsk_contour_free_measure                (GskPath              *path,
                                                                  gsize                 i,
                                                                  gpointer              data);
+void                    gsk_contour_get_start_end               (const GskContour       *self,
+                                                                 graphene_point_t       *start,
+                                                                 graphene_point_t       *end);
 void                    gsk_contour_get_point                   (GskPath              *path,
                                                                  gsize                 i,
                                                                  gpointer              measure_data,


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