From 924f036667165dd70c53174ace4048246dada390 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sat, 28 Nov 2020 06:46:26 +0100 Subject: [PATCH] pathbuilder: Redo semantics for starting curves We now always have a "current point" which is either the last point an operation was made to, or (0, 0) if no drawing operation has been made yet. Adding a contour of any kind to the builder will always update the current point to that contour's end point. --- gsk/gskpath.c | 56 ++++++++++++++++++++++++++++++++++++++++++++ gsk/gskpathbuilder.c | 41 +++++++++++++++++++------------- gsk/gskpathprivate.h | 3 +++ 3 files changed, 84 insertions(+), 16 deletions(-) diff --git a/gsk/gskpath.c b/gsk/gskpath.c index 7c86ccaf50..ab3c84e0bf 100644 --- a/gsk/gskpath.c +++ b/gsk/gskpath.c @@ -44,6 +44,9 @@ struct _GskContourClass GString *string); gboolean (* get_bounds) (const GskContour *contour, graphene_rect_t *bounds); + void (* get_start_end) (const GskContour *self, + graphene_point_t *start, + graphene_point_t *end); gboolean (* foreach) (const GskContour *contour, float tolerance, GskPathForeachFunc func, @@ -211,6 +214,20 @@ gsk_rect_contour_get_bounds (const GskContour *contour, return TRUE; } +static void +gsk_rect_contour_get_start_end (const GskContour *contour, + graphene_point_t *start, + graphene_point_t *end) +{ + const GskRectContour *self = (const GskRectContour *) contour; + + if (start) + *start = GRAPHENE_POINT_INIT (self->x, self->y); + + if (end) + *end = GRAPHENE_POINT_INIT (self->x, self->y); +} + static gboolean gsk_rect_contour_foreach (const GskContour *contour, float tolerance, @@ -469,6 +486,7 @@ static const GskContourClass GSK_RECT_CONTOUR_CLASS = gsk_rect_contour_get_flags, gsk_rect_contour_print, gsk_rect_contour_get_bounds, + gsk_rect_contour_get_start_end, gsk_rect_contour_foreach, gsk_rect_contour_init_measure, gsk_rect_contour_free_measure, @@ -561,6 +579,20 @@ gsk_circle_contour_get_bounds (const GskContour *contour, return TRUE; } +static void +gsk_circle_contour_get_start_end (const GskContour *contour, + graphene_point_t *start, + graphene_point_t *end) +{ + const GskCircleContour *self = (const GskCircleContour *) contour; + + if (start) + *start = GSK_CIRCLE_POINT_INIT (self, self->start_angle); + + if (end) + *end = GSK_CIRCLE_POINT_INIT (self, self->end_angle); +} + typedef struct { GskPathForeachFunc func; @@ -755,6 +787,7 @@ static const GskContourClass GSK_CIRCLE_CONTOUR_CLASS = gsk_circle_contour_get_flags, gsk_circle_contour_print, gsk_circle_contour_get_bounds, + gsk_circle_contour_get_start_end, gsk_circle_contour_foreach, gsk_circle_contour_init_measure, gsk_circle_contour_free_measure, @@ -941,6 +974,20 @@ gsk_standard_contour_get_bounds (const GskContour *contour, return bounds->size.width > 0 && bounds->size.height > 0; } +static void +gsk_standard_contour_get_start_end (const GskContour *contour, + graphene_point_t *start, + graphene_point_t *end) +{ + const GskStandardContour *self = (const GskStandardContour *) contour; + + if (start) + *start = self->points[0]; + + if (end) + *end = self->points[self->n_points - 1]; +} + typedef struct { float start; @@ -1395,6 +1442,7 @@ static const GskContourClass GSK_STANDARD_CONTOUR_CLASS = gsk_standard_contour_get_flags, gsk_standard_contour_print, gsk_standard_contour_get_bounds, + gsk_standard_contour_get_start_end, gsk_standard_contour_foreach, gsk_standard_contour_init_measure, gsk_standard_contour_free_measure, @@ -1481,6 +1529,14 @@ gsk_contour_free_measure (GskPath *path, self->klass->free_measure (self, data); } +void +gsk_contour_get_start_end (const GskContour *self, + graphene_point_t *start, + graphene_point_t *end) +{ + self->klass->get_start_end (self, start, end); +} + void gsk_contour_get_point (GskPath *path, gsize i, diff --git a/gsk/gskpathbuilder.c b/gsk/gskpathbuilder.c index f296959dde..05bbc3b7b5 100644 --- a/gsk/gskpathbuilder.c +++ b/gsk/gskpathbuilder.c @@ -68,6 +68,7 @@ struct _GskPathBuilder GSList *contours; /* (reverse) list of already recorded contours */ GskPathFlags flags; /* flags for the current path */ + graphene_point_t current_point; /* the point all drawing ops start from */ GArray *ops; /* operations for current contour - size == 0 means no current contour */ GArray *points; /* points for the operations */ }; @@ -97,6 +98,10 @@ gsk_path_builder_new (void) builder->ops = g_array_new (FALSE, FALSE, sizeof (GskStandardOperation)); builder->points = g_array_new (FALSE, FALSE, sizeof (graphene_point_t)); + + /* Be explicit here */ + builder->current_point = GRAPHENE_POINT_INIT (0, 0); + return builder; } @@ -123,18 +128,29 @@ gsk_path_builder_ref (GskPathBuilder *builder) return builder; } +static void +gsk_path_builder_ensure_current (GskPathBuilder *builder) +{ + if (builder->ops->len != 0) + return; + + builder->flags = GSK_PATH_FLAT; + g_array_append_vals (builder->ops, &(GskStandardOperation) { GSK_PATH_MOVE, 0 }, 1); + g_array_append_val (builder->points, builder->current_point); +} + static void gsk_path_builder_append_current (GskPathBuilder *builder, GskPathOperation op, gsize n_points, const graphene_point_t *points) { - g_assert (builder->ops->len > 0); - g_assert (builder->points->len > 0); - g_assert (n_points > 0); + gsk_path_builder_ensure_current (builder); g_array_append_vals (builder->ops, &(GskStandardOperation) { op, builder->points->len - 1 }, 1); g_array_append_vals (builder->points, points, n_points); + + builder->current_point = points[n_points - 1]; } static void @@ -303,6 +319,8 @@ gsk_path_builder_add_rect (GskPathBuilder *builder, contour = gsk_rect_contour_new (rect); gsk_path_builder_add_contour (builder, contour); + + gsk_contour_get_start_end (contour, NULL, &builder->current_point); } /** @@ -349,9 +367,9 @@ gsk_path_builder_move_to (GskPathBuilder *builder, gsk_path_builder_end_current (builder); - builder->flags = GSK_PATH_FLAT; - g_array_append_vals (builder->ops, &(GskStandardOperation) { GSK_PATH_MOVE, 0 }, 1); - g_array_append_val (builder->points, GRAPHENE_POINT_INIT(x, y)); + builder->current_point = GRAPHENE_POINT_INIT(x, y); + + gsk_path_builder_ensure_current (builder); } /** @@ -370,14 +388,8 @@ gsk_path_builder_line_to (GskPathBuilder *builder, { g_return_if_fail (builder != NULL); - if (builder->ops->len == 0) - { - gsk_path_builder_move_to (builder, x, y); - return; - } - /* skip the line if it goes to the same point */ - if (graphene_point_equal (&g_array_index (builder->points, graphene_point_t, builder->points->len - 1), + if (graphene_point_equal (&builder->current_point, &GRAPHENE_POINT_INIT (x, y))) return; @@ -413,9 +425,6 @@ gsk_path_builder_curve_to (GskPathBuilder *builder, { g_return_if_fail (builder != NULL); - if (builder->ops->len == 0) - gsk_path_builder_move_to (builder, x1, y1); - builder->flags &= ~GSK_PATH_FLAT; gsk_path_builder_append_current (builder, GSK_PATH_CURVE, diff --git a/gsk/gskpathprivate.h b/gsk/gskpathprivate.h index d987c90fc1..cdb4a76243 100644 --- a/gsk/gskpathprivate.h +++ b/gsk/gskpathprivate.h @@ -73,6 +73,9 @@ gpointer gsk_contour_init_measure (GskPath void gsk_contour_free_measure (GskPath *path, gsize i, gpointer data); +void gsk_contour_get_start_end (const GskContour *self, + graphene_point_t *start, + graphene_point_t *end); void gsk_contour_get_point (GskPath *path, gsize i, gpointer measure_data,