[gtk/path-work-rebased: 62/71] path: Add gsk_path_reverse




commit 3661086dcc5f392c3a541cceb725ac690c5dc5c1
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        | 93 ++++++++++++++++++++++++++++++++++++++++++++++---
 gsk/gskcontourprivate.h |  2 ++
 gsk/gskpath.c           | 22 ++++++++++++
 gsk/gskpath.h           |  3 ++
 4 files changed, 116 insertions(+), 4 deletions(-)
---
diff --git a/gsk/gskcontour.c b/gsk/gskcontour.c
index b36082a077..1f40fccda6 100644
--- a/gsk/gskcontour.c
+++ b/gsk/gskcontour.c
@@ -98,6 +98,7 @@ struct _GskContourClass
                                                  float                   distance,
                                                  GskLineJoin             line_join,
                                                  float                   miter_limit);
+  GskContour *          (* reverse)             (const GskContour       *contour);
 };
 
 static gsize
@@ -564,6 +565,17 @@ gsk_rect_contour_offset (const GskContour *contour,
   gsk_contour_default_offset (contour, builder, distance, line_join, miter_limit);
 }
 
+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),
@@ -584,7 +596,8 @@ static const GskContourClass GSK_RECT_CONTOUR_CLASS =
   gsk_rect_contour_get_winding,
   gsk_rect_contour_get_stroke_bounds,
   gsk_rect_contour_add_stroke,
-  gsk_rect_contour_offset
+  gsk_rect_contour_offset,
+  gsk_rect_contour_reverse,
 };
 
 GskContour *
@@ -966,6 +979,17 @@ gsk_circle_contour_offset (const GskContour *contour,
   gsk_contour_default_offset (contour, builder, distance, line_join, miter_limit);
 }
 
+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),
@@ -986,7 +1010,8 @@ static const GskContourClass GSK_CIRCLE_CONTOUR_CLASS =
   gsk_circle_contour_get_winding,
   gsk_circle_contour_get_stroke_bounds,
   gsk_circle_contour_add_stroke,
-  gsk_circle_contour_offset
+  gsk_circle_contour_offset,
+  gsk_circle_contour_reverse,
 };
 
 GskContour *
@@ -1557,7 +1582,7 @@ gsk_standard_contour_add_segment (const GskContour *contour,
       gsk_curve_builder_to (&cut, builder);
       i = start_measure->op + 1;
     }
-  else 
+  else
     i = emit_move_to ? 0 : 1;
 
   for (; i < (end_measure ? end_measure->op : self->n_ops - 1); i++)
@@ -1742,6 +1767,59 @@ gsk_standard_contour_offset (const GskContour *contour,
   gsk_contour_default_offset (contour, builder, distance, line_join, miter_limit);
 }
 
+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),
@@ -1762,7 +1840,8 @@ static const GskContourClass GSK_STANDARD_CONTOUR_CLASS =
   gsk_standard_contour_get_winding,
   gsk_standard_contour_get_stroke_bounds,
   gsk_standard_contour_add_stroke,
-  gsk_standard_contour_offset
+  gsk_standard_contour_offset,
+  gsk_standard_contour_reverse,
 };
 
 /* You must ensure the contour has enough size allocated,
@@ -1980,6 +2059,12 @@ gsk_contour_dup (const GskContour *src)
   return copy;
 }
 
+GskContour *
+gsk_contour_reverse (const GskContour *src)
+{
+  return src->klass->reverse (src);
+}
+
 /* }}} */
 
 /* vim:set foldmethod=marker expandtab: */
diff --git a/gsk/gskcontourprivate.h b/gsk/gskcontourprivate.h
index 5219eb448a..842e4e04a1 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 5bdb628acd..13c4f66641 100644
--- a/gsk/gskpath.c
+++ b/gsk/gskpath.c
@@ -1240,6 +1240,28 @@ gsk_path_get_stroke_bounds (GskPath         *path,
   return TRUE;
 }
 
+/**
+ * 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 1f208ae339..a94101fd80 100644
--- a/gsk/gskpath.h
+++ b/gsk/gskpath.h
@@ -109,6 +109,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]