[gtk/path-ops: 2/8] path: Add gsk_path_reverse
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/path-ops: 2/8] path: Add gsk_path_reverse
- Date: Thu, 7 Apr 2022 03:21:50 +0000 (UTC)
commit 67c4833d2c84d7468db456ae133e260eb957bedb
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 | 98 +++++++++++++++++++++++++++++++++++++++++++++----
gsk/gskcontourprivate.h | 2 +
gsk/gskpath.c | 22 +++++++++++
gsk/gskpath.h | 3 ++
4 files changed, 118 insertions(+), 7 deletions(-)
---
diff --git a/gsk/gskcontour.c b/gsk/gskcontour.c
index c978e91401..f90e4cea21 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
@@ -328,7 +329,7 @@ gsk_rect_contour_get_closest_point (const GskContour *contour,
const GskRectContour *self = (const GskRectContour *) contour;
graphene_point_t t, p;
float distance;
-
+
/* offset coords to be relative to rectangle */
t.x = point->x - self->x;
t.y = point->y - self->y;
@@ -385,7 +386,7 @@ gsk_rect_contour_get_closest_point (const GskContour *contour,
*out_pos = p;
if (out_offset)
- *out_offset = (t.x == 0.0 && self->width > 0 ? 2 - t.y : t.y) * ABS (self->height) +
+ *out_offset = (t.x == 0.0 && self->width > 0 ? 2 - t.y : t.y) * ABS (self->height) +
(t.y == 1.0 ? 2 - t.x : t.x) * ABS (self->width);
if (out_tangent)
@@ -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 *
@@ -965,6 +978,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),
@@ -985,7 +1009,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 *
@@ -1445,7 +1470,7 @@ gsk_standard_contour_get_closest_point (const GskContour *contour,
dist = test_dist;
}
//g_print ("!!! %zu: (%g-%g @ %g) dist %g\n", i, measure->start_progress, measure->end_progress,
progress, dist);
- /* double check that the point actually is closer */
+ /* double check that the point actually is closer */
if (dist <= threshold)
{
if (out_distance)
@@ -1555,7 +1580,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++)
@@ -1740,6 +1765,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),
@@ -1760,7 +1838,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,
@@ -1977,3 +2056,8 @@ gsk_contour_dup (const GskContour *src)
return copy;
}
+GskContour *
+gsk_contour_reverse (const GskContour *src)
+{
+ return src->klass->reverse (src);
+}
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 4d5961bf94..deac50531e 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]