From f166ec5bc960d1089b452d217dd1bb6e7a075367 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 26 Dec 2020 23:59:16 -0500 Subject: [PATCH] path: Add gsk_path_offset Add a function that takes a path, and offsets it by some distance, applying line-join parameters as needed. This commit just adds the api, the implementation will be in the following commit. --- gsk/gskcontour.c | 55 +++++++++++++++++++++++++++++++++++++---- gsk/gskcontourprivate.h | 6 +++++ gsk/gskpath.c | 33 +++++++++++++++++++++++++ gsk/gskpath.h | 6 +++++ 4 files changed, 95 insertions(+), 5 deletions(-) diff --git a/gsk/gskcontour.c b/gsk/gskcontour.c index bac756bf28..59e3015c2e 100644 --- a/gsk/gskcontour.c +++ b/gsk/gskcontour.c @@ -89,6 +89,11 @@ struct _GskContourClass void (* add_stroke) (const GskContour *contour, GskPathBuilder *builder, GskStroke *stroke); + void (* offset) (const GskContour *contour, + GskPathBuilder *builder, + float distance, + GskLineJoin line_join, + float miter_limit); }; static gsize @@ -498,8 +503,8 @@ gsk_rect_contour_get_stroke_bounds (const GskContour *contour, static gboolean stroke_is_simple (GskStroke *stroke) { - if (stroke->line_join != GSK_LINE_JOIN_MITER && - stroke->line_join != GSK_LINE_JOIN_MITER_CLIP) + if (stroke->line_join == GSK_LINE_JOIN_ROUND || + stroke->line_join == GSK_LINE_JOIN_BEVEL) return FALSE; if (stroke->miter_limit < 1.5) @@ -536,6 +541,15 @@ gsk_rect_contour_add_stroke (const GskContour *contour, gsk_contour_default_add_stroke (contour, builder, stroke); } +static void +gsk_rect_contour_offset (const GskContour *contour, + GskPathBuilder *builder, + float distance, + GskLineJoin line_join, + float miter_limit) +{ +} + static const GskContourClass GSK_RECT_CONTOUR_CLASS = { sizeof (GskRectContour), @@ -554,7 +568,8 @@ static const GskContourClass GSK_RECT_CONTOUR_CLASS = gsk_rect_contour_add_segment, gsk_rect_contour_get_winding, gsk_rect_contour_get_stroke_bounds, - gsk_rect_contour_add_stroke + gsk_rect_contour_add_stroke, + gsk_rect_contour_offset }; GskContour * @@ -912,6 +927,15 @@ gsk_circle_contour_add_stroke (const GskContour *contour, gsk_contour_default_add_stroke (contour, builder, stroke); } +static void +gsk_circle_contour_offset (const GskContour *contour, + GskPathBuilder *builder, + float distance, + GskLineJoin line_join, + float miter_limit) +{ +} + static const GskContourClass GSK_CIRCLE_CONTOUR_CLASS = { sizeof (GskCircleContour), @@ -930,7 +954,8 @@ static const GskContourClass GSK_CIRCLE_CONTOUR_CLASS = gsk_circle_contour_add_segment, gsk_circle_contour_get_winding, gsk_circle_contour_get_stroke_bounds, - gsk_circle_contour_add_stroke + gsk_circle_contour_add_stroke, + gsk_circle_contour_offset }; GskContour * @@ -1644,6 +1669,15 @@ gsk_standard_contour_add_stroke (const GskContour *contour, gsk_contour_default_add_stroke (contour, builder, stroke); } +static void +gsk_standard_contour_offset (const GskContour *contour, + GskPathBuilder *builder, + float distance, + GskLineJoin line_join, + float miter_limit) +{ +} + static const GskContourClass GSK_STANDARD_CONTOUR_CLASS = { sizeof (GskStandardContour), @@ -1662,7 +1696,8 @@ static const GskContourClass GSK_STANDARD_CONTOUR_CLASS = gsk_standard_contour_add_segment, gsk_standard_contour_get_winding, gsk_standard_contour_get_stroke_bounds, - gsk_standard_contour_add_stroke + gsk_standard_contour_add_stroke, + gsk_standard_contour_offset }; /* You must ensure the contour has enough size allocated, @@ -1843,6 +1878,16 @@ gsk_contour_add_stroke (const GskContour *self, self->klass->add_stroke (self, builder, stroke); } +void +gsk_contour_offset (const GskContour *self, + GskPathBuilder *builder, + float distance, + GskLineJoin line_join, + float miter_limit) +{ + self->klass->offset (self, builder, distance, line_join, miter_limit); +} + void gsk_contour_copy (GskContour *dest, const GskContour *src) diff --git a/gsk/gskcontourprivate.h b/gsk/gskcontourprivate.h index 1145df7076..e415b02d09 100644 --- a/gsk/gskcontourprivate.h +++ b/gsk/gskcontourprivate.h @@ -107,6 +107,12 @@ void gsk_contour_default_add_stroke (const GskContou GskPathBuilder *builder, GskStroke *stroke); +void gsk_contour_offset (const GskContour *contour, + GskPathBuilder *builder, + float distance, + GskLineJoin line_join, + float miter_limit); + G_END_DECLS #endif /* __GSK_CONTOUR_PRIVATE_H__ */ diff --git a/gsk/gskpath.c b/gsk/gskpath.c index b44f00abd9..5bdb628acd 100644 --- a/gsk/gskpath.c +++ b/gsk/gskpath.c @@ -1264,3 +1264,36 @@ gsk_path_stroke (GskPath *self, return gsk_path_builder_free_to_path (builder); } + +/** + * gsk_path_offset: + * @self: a `GskPath` + * @distance: the distance to offset the path by + * @line_join: how joins are supposed to be drawn + * @miter_limit: miter limit for joins + * + * Create a new path that is offset from @self by @distance. + * + * The offset can be positive (to the right) or negative. + * The @line_join and @miter_limit arguments influence how + * joins between the offset path segments are made. + * + * Returns: a new `GskPath` + */ +GskPath * +gsk_path_offset (GskPath *self, + float distance, + GskLineJoin line_join, + float miter_limit) +{ + GskPathBuilder *builder; + + builder = gsk_path_builder_new (); + + for (int i = 0; i < self->n_contours; i++) + gsk_contour_offset (gsk_path_get_contour (self, i), builder, distance, line_join, miter_limit); + + return gsk_path_builder_free_to_path (builder); +} + + diff --git a/gsk/gskpath.h b/gsk/gskpath.h index 50a4c85ccd..1f208ae339 100644 --- a/gsk/gskpath.h +++ b/gsk/gskpath.h @@ -113,6 +113,12 @@ GDK_AVAILABLE_IN_ALL GskPath * gsk_path_stroke (GskPath *self, GskStroke *stroke); +GDK_AVAILABLE_IN_ALL +GskPath * gsk_path_offset (GskPath *self, + float distance, + GskLineJoin line_join, + float miter_limit); + G_END_DECLS