[gtk/path-ops: 5/8] path: Add gsk_path_transform
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/path-ops: 5/8] path: Add gsk_path_transform
- Date: Thu, 7 Apr 2022 03:21:50 +0000 (UTC)
commit 20022682e48bc8dbe99ca352031b0a13e8c08acb
Author: Matthias Clasen <mclasen redhat com>
Date: Wed Apr 6 22:27:55 2022 -0400
path: Add gsk_path_transform
This is an obvious operation to want for paths.
gsk/gskpath.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
gsk/gskpath.h | 4 +++
2 files changed, 112 insertions(+)
---
diff --git a/gsk/gskpath.c b/gsk/gskpath.c
index 0762ceab1e..0dbbbbb468 100644
--- a/gsk/gskpath.c
+++ b/gsk/gskpath.c
@@ -24,6 +24,7 @@
#include "gskcurveprivate.h"
#include "gskpathbuilder.h"
#include "gskstrokeprivate.h"
+#include "gsktransform.h"
#include "gdk/gdk-private.h"
@@ -1290,6 +1291,113 @@ gsk_path_is_convex (GskPath *self)
return gsk_contour_is_convex (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);
+}
+
+typedef struct
+{
+ GskTransform *transform;
+ GskPathBuilder *builder;
+} TransformData;
+
+static gboolean
+transform_cb (GskPathOperation op,
+ const graphene_point_t *pts,
+ gsize n_pts,
+ float weight,
+ gpointer user_data)
+{
+ TransformData *data = user_data;
+ graphene_point_t tp[4];
+
+ switch (op)
+ {
+ case GSK_PATH_CLOSE:
+ gsk_path_builder_close (data->builder);
+ break;
+
+ case GSK_PATH_MOVE:
+ gsk_transform_transform_point (data->transform, &pts[0], &tp[0]);
+ gsk_path_builder_move_to (data->builder, tp[0].x, tp[0].y);
+ break;
+
+ case GSK_PATH_LINE:
+ gsk_transform_transform_point (data->transform, &pts[1], &tp[1]);
+ gsk_path_builder_line_to (data->builder, tp[1].x, tp[1].y);
+ break;
+
+ case GSK_PATH_CURVE:
+ gsk_transform_transform_point (data->transform, &pts[1], &tp[1]);
+ gsk_transform_transform_point (data->transform, &pts[2], &tp[2]);
+ gsk_transform_transform_point (data->transform, &pts[3], &tp[3]);
+ gsk_path_builder_curve_to (data->builder,
+ tp[1].x, tp[1].y,
+ tp[2].x, tp[2].y,
+ tp[3].x, tp[3].y);
+ break;
+
+ case GSK_PATH_CONIC:
+ gsk_transform_transform_point (data->transform, &pts[1], &tp[1]);
+ gsk_transform_transform_point (data->transform, &pts[3], &tp[3]);
+ gsk_path_builder_conic_to (data->builder,
+ tp[1].x, tp[1].y,
+ tp[3].x, tp[3].y,
+ weight);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ return TRUE;
+}
+
+/**
+ * gsk_path_transform:
+ * @self: a `GskPath`
+ * @transform: the transform to apply
+ *
+ * Applies the transform to all points of @self
+ * and returns the resulting path.
+ *
+ * Returns: a new `GskPath`
+ */
+GskPath *
+gsk_path_transform (GskPath *self,
+ GskTransform *transform)
+{
+ TransformData data;
+
+ data.transform = transform;
+ data.builder = gsk_path_builder_new ();
+
+ gsk_path_foreach (self,
+ GSK_PATH_FOREACH_ALLOW_CURVE | GSK_PATH_FOREACH_ALLOW_CONIC,
+ transform_cb,
+ &data);
+
+ return gsk_path_builder_free_to_path (data.builder);
+}
+
/**
* gsk_path_stroke:
* @self: a `GskPath`
diff --git a/gsk/gskpath.h b/gsk/gskpath.h
index bbc8b39884..80159669e8 100644
--- a/gsk/gskpath.h
+++ b/gsk/gskpath.h
@@ -115,6 +115,10 @@ gboolean gsk_path_foreach (GskPath
GDK_AVAILABLE_IN_ALL
GskPath * gsk_path_reverse (GskPath *self);
+GDK_AVAILABLE_IN_ALL
+GskPath * gsk_path_transform (GskPath *self,
+ GskTransform *transform);
+
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]