[gtk/path-ops: 23/27] path: Add gsk_path_reverse




commit 0e506e70d0ac695b2b8eda1f0d77080eacd815a6
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Mar 25 16:48:09 2022 -0400

    path: Add gsk_path_reverse
    
    This is a natural operation, and useful for debugging things.

 gsk/gskcontour.c        | 87 ++++++++++++++++++++++++++++++++++++++++++++++++-
 gsk/gskcontourprivate.h |  2 ++
 gsk/gskpath.c           | 22 +++++++++++++
 gsk/gskpath.h           |  3 ++
 4 files changed, 113 insertions(+), 1 deletion(-)
---
diff --git a/gsk/gskcontour.c b/gsk/gskcontour.c
index dc6d66b3d4..8bc4ea5e78 100644
--- a/gsk/gskcontour.c
+++ b/gsk/gskcontour.c
@@ -100,6 +100,7 @@ struct _GskContourClass
                                                  float                   miter_limit);
   GskConvexity          (* get_convexity)       (const GskContour       *contour);
   GskConvexity          (* compute_convexity)   (const GskContour       *contour);
+  GskContour *          (* reverse)             (const GskContour       *contour);
 };
 
 static gsize
@@ -572,6 +573,17 @@ gsk_rect_contour_get_convexity (const GskContour *contour)
   return GSK_CONVEXITY_CONVEX;
 }
 
+static GskContour *
+gsk_rect_contour_reverse (const GskContour *contour)
+{
+  const GskRectContour *self = (const GskRectContour *) contour;
+
+  return gsk_rect_contour_new (&GRAPHENE_RECT_INIT (self->x + self->width,
+                                                    self->y,
+                                                    - self->width,
+                                                    self->height));
+}
+
 static const GskContourClass GSK_RECT_CONTOUR_CLASS =
 {
   sizeof (GskRectContour),
@@ -595,6 +607,7 @@ static const GskContourClass GSK_RECT_CONTOUR_CLASS =
   gsk_rect_contour_offset,
   gsk_rect_contour_get_convexity,
   gsk_rect_contour_get_convexity,
+  gsk_rect_contour_reverse,
 };
 
 GskContour *
@@ -981,6 +994,17 @@ gsk_circle_contour_get_convexity (const GskContour *contour)
   return GSK_CONVEXITY_CONVEX;
 }
 
+static GskContour *
+gsk_circle_contour_reverse (const GskContour *contour)
+{
+  const GskCircleContour *self = (const GskCircleContour *) contour;
+
+  return gsk_circle_contour_new (&self->center,
+                                 self->radius,
+                                 self->end_angle,
+                                 self->start_angle);
+}
+
 static const GskContourClass GSK_CIRCLE_CONTOUR_CLASS =
 {
   sizeof (GskCircleContour),
@@ -1004,6 +1028,7 @@ static const GskContourClass GSK_CIRCLE_CONTOUR_CLASS =
   gsk_circle_contour_offset,
   gsk_circle_contour_get_convexity,
   gsk_circle_contour_get_convexity,
+  gsk_circle_contour_reverse,
 };
 
 GskContour *
@@ -1762,7 +1787,7 @@ gsk_standard_contour_offset (const GskContour *contour,
 static GskConvexity
 gsk_standard_contour_get_convexity (const GskContour *contour)
 {
-  GskStandardContour *self = (GskStandardContour *) contour;
+  const GskStandardContour *self = (const GskStandardContour *) contour;
 
   return self->convexity;
 }
@@ -1780,6 +1805,59 @@ gsk_standard_contour_compute_convexity (const GskContour *contour)
   return self->convexity;
 }
 
+static gboolean
+add_reverse (GskPathOperation        op,
+             const graphene_point_t *pts,
+             gsize                   n_pts,
+             float                   weight,
+             gpointer                user_data)
+{
+  GskPathBuilder *builder = user_data;
+  GskCurve c, r;
+
+  if (op == GSK_PATH_MOVE)
+    return TRUE;
+
+  if (op == GSK_PATH_CLOSE)
+    op = GSK_PATH_LINE;
+
+  gsk_curve_init_foreach (&c, op, pts, n_pts, weight);
+  gsk_curve_reverse (&c, &r);
+  gsk_curve_builder_to (&r, builder);
+
+  return TRUE;
+}
+
+static GskContour *
+gsk_standard_contour_reverse (const GskContour *contour)
+{
+  const GskStandardContour *self = (const GskStandardContour *) contour;
+  GskPathBuilder *builder;
+  GskPath *path;
+  GskContour *res;
+
+  builder = gsk_path_builder_new ();
+
+  gsk_path_builder_move_to (builder, self->points[self->n_points - 1].x,
+                                     self->points[self->n_points - 1].y);
+
+  for (int i = self->n_ops - 1; i >= 0; i--)
+    gsk_pathop_foreach (self->ops[i], add_reverse, builder);
+
+  if (self->flags & GSK_PATH_CLOSED)
+    gsk_path_builder_close (builder);
+
+  path = gsk_path_builder_free_to_path (builder);
+
+  g_assert (gsk_path_get_n_contours (path) == 1);
+
+  res = gsk_contour_dup (gsk_path_get_contour (path, 0));
+
+  gsk_path_unref (path);
+
+  return res;
+}
+
 static const GskContourClass GSK_STANDARD_CONTOUR_CLASS =
 {
   sizeof (GskStandardContour),
@@ -1803,6 +1881,7 @@ static const GskContourClass GSK_STANDARD_CONTOUR_CLASS =
   gsk_standard_contour_offset,
   gsk_standard_contour_get_convexity,
   gsk_standard_contour_compute_convexity,
+  gsk_standard_contour_reverse,
 };
 
 /* You must ensure the contour has enough size allocated,
@@ -2020,6 +2099,12 @@ gsk_contour_dup (const GskContour *src)
   return copy;
 }
 
+GskContour *
+gsk_contour_reverse (const GskContour *src)
+{
+  return src->klass->reverse (src);
+}
+
 GskConvexity
 gsk_contour_get_convexity (const GskContour *contour)
 {
diff --git a/gsk/gskcontourprivate.h b/gsk/gskcontourprivate.h
index 7253036811..5b07a24b6d 100644
--- a/gsk/gskcontourprivate.h
+++ b/gsk/gskcontourprivate.h
@@ -55,6 +55,8 @@ void                    gsk_contour_copy                        (GskContour *
                                                                  const GskContour       *src);
 GskContour *            gsk_contour_dup                         (const GskContour       *src);
 
+GskContour *            gsk_contour_reverse                     (const GskContour       *src);
+
 gsize                   gsk_contour_get_size                    (const GskContour       *self);
 GskPathFlags            gsk_contour_get_flags                   (const GskContour       *self);
 void                    gsk_contour_print                       (const GskContour       *self,
diff --git a/gsk/gskpath.c b/gsk/gskpath.c
index 57df5b9bff..8bf850fdd6 100644
--- a/gsk/gskpath.c
+++ b/gsk/gskpath.c
@@ -1295,6 +1295,28 @@ gsk_path_compute_convexity (GskPath *self)
   return gsk_contour_compute_convexity (gsk_path_get_contour (self, 0));
 }
 
+/**
+ * gsk_path_reverse:
+ * @self: a `GskPath`
+ *
+ * Creates a path that traverses the same contours as
+ * @self, in the opposite direction.
+ *
+ * Returns: the reverse of @self
+ */
+GskPath *
+gsk_path_reverse (GskPath *self)
+{
+  GskPathBuilder *builder;
+
+  builder = gsk_path_builder_new ();
+
+  for (int i = self->n_contours - 1; i >= 0; i--)
+    gsk_path_builder_add_contour (builder, gsk_contour_reverse (gsk_path_get_contour (self, i)));
+
+  return gsk_path_builder_free_to_path (builder);
+}
+
 /**
  * gsk_path_stroke:
  * @self: a `GskPath`
diff --git a/gsk/gskpath.h b/gsk/gskpath.h
index 4e6a438fd0..8acc710911 100644
--- a/gsk/gskpath.h
+++ b/gsk/gskpath.h
@@ -114,6 +114,9 @@ gboolean                gsk_path_foreach                        (GskPath
                                                                  GskPathForeachFunc      func,
                                                                  gpointer                user_data);
 
+GDK_AVAILABLE_IN_ALL
+GskPath *               gsk_path_reverse                        (GskPath                *self);
+
 GDK_AVAILABLE_IN_ALL
 GskPath *               gsk_path_stroke                         (GskPath                *self,
                                                                  GskStroke              *stroke);


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