[gtk/path-ops: 22/26] path: Add gsk_path_reverse
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/path-ops: 22/26] path: Add gsk_path_reverse
- Date: Mon, 4 Apr 2022 23:45:53 +0000 (UTC)
commit ed9f904e6745797b2da73e3d2ac43cc143f47d83
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 2d35112ed6..f3dce17259 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]