From b533dfa0da111d341b3d51d5a7c130f176d910b4 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 5 Aug 2023 10:57:47 -0400 Subject: [PATCH] Make points stack-allocated This does the necessary reshuffling to make GskPathPoint a stack-allocated struct. --- demos/gtk-demo/path_fill.c | 29 ++++---- demos/gtk-demo/path_maze.c | 17 +++-- demos/gtk-demo/path_text.c | 56 +++++++------- gsk/gskcontour.c | 76 +++++++++---------- gsk/gskcontourprivate.h | 24 ++---- gsk/gskpath.c | 39 +++++----- gsk/gskpath.h | 5 +- gsk/gskpathbuilder.c | 1 + gsk/gskpathmeasure.c | 32 ++++---- gsk/gskpathmeasure.h | 5 +- gsk/gskpathpoint.c | 101 ++++++++++---------------- gsk/gskpathpoint.h | 24 ++++-- gsk/gskpathpointprivate.h | 6 +- gsk/gskpathprivate.h | 10 ++- testsuite/gsk/curve.c | 11 +-- testsuite/gsk/measure-special-cases.c | 41 ++++++----- testsuite/gsk/measure.c | 70 +++++++++--------- 17 files changed, 269 insertions(+), 278 deletions(-) diff --git a/demos/gtk-demo/path_fill.c b/demos/gtk-demo/path_fill.c index a65a749451..9af331af6a 100644 --- a/demos/gtk-demo/path_fill.c +++ b/demos/gtk-demo/path_fill.c @@ -274,7 +274,7 @@ update_path (GtkWidget *widget, float progress = gdk_frame_clock_get_frame_time (frame_clock) % (60 * G_USEC_PER_SEC) / (float) (30 * G_USEC_PER_SEC); GskPathBuilder *builder; GskPath *path; - GskPathPoint *point; + GskPathPoint point; graphene_point_t pos; graphene_vec2_t tangent; GskStroke *stroke; @@ -287,22 +287,23 @@ update_path (GtkWidget *widget, builder = gsk_path_builder_new (); gsk_path_dash (path, stroke, 0.2, build_path, builder); - point = gsk_path_measure_get_point (measure, - (progress > 1 ? (progress - 1) : progress) * gsk_path_measure_get_length (measure)); - gsk_path_point_get_position (point, &pos); - gsk_path_point_get_tangent (point, GSK_PATH_END, &tangent); - gsk_path_point_unref (point); + if (gsk_path_measure_get_point (measure, + (progress > 1 ? (progress - 1) : progress) * gsk_path_measure_get_length (measure), &point)) + { + gsk_path_point_get_position (&point, &pos); + gsk_path_point_get_tangent (&point, GSK_PATH_END, &tangent); - gsk_path_builder_move_to (builder, pos.x + 5 * graphene_vec2_get_x (&tangent), pos.y + 5 * graphene_vec2_get_y (&tangent)); - gsk_path_builder_line_to (builder, pos.x + 3 * graphene_vec2_get_y (&tangent), pos.y + 3 * graphene_vec2_get_x (&tangent)); - gsk_path_builder_line_to (builder, pos.x - 3 * graphene_vec2_get_y (&tangent), pos.y - 3 * graphene_vec2_get_x (&tangent)); - gsk_path_builder_close (builder); + gsk_path_builder_move_to (builder, pos.x + 5 * graphene_vec2_get_x (&tangent), pos.y + 5 * graphene_vec2_get_y (&tangent)); + gsk_path_builder_line_to (builder, pos.x + 3 * graphene_vec2_get_y (&tangent), pos.y + 3 * graphene_vec2_get_x (&tangent)); + gsk_path_builder_line_to (builder, pos.x - 3 * graphene_vec2_get_y (&tangent), pos.y - 3 * graphene_vec2_get_x (&tangent)); + gsk_path_builder_close (builder); - path = gsk_path_builder_free_to_path (builder); + path = gsk_path_builder_free_to_path (builder); - gtk_path_paintable_set_path (GTK_PATH_PAINTABLE (gtk_picture_get_paintable (GTK_PICTURE (widget))), - path); - gsk_path_unref (path); + gtk_path_paintable_set_path (GTK_PATH_PAINTABLE (gtk_picture_get_paintable (GTK_PICTURE (widget))), + path); + gsk_path_unref (path); + } return G_SOURCE_CONTINUE; } diff --git a/demos/gtk-demo/path_maze.c b/demos/gtk-demo/path_maze.c index 18bf60457e..5deef5c70c 100644 --- a/demos/gtk-demo/path_maze.c +++ b/demos/gtk-demo/path_maze.c @@ -137,21 +137,22 @@ pointer_motion (GtkEventControllerMotion *controller, double y, GtkMaze *self) { - GskPathPoint *point; + GskPathPoint point; graphene_point_t pos; if (!self->active) return; - point = gsk_path_get_closest_point (self->path, &GRAPHENE_POINT_INIT (x, y), INFINITY); - gsk_path_point_get_position (point, &pos); - gsk_path_point_unref (point); + if (gsk_path_get_closest_point (self->path, &GRAPHENE_POINT_INIT (x, y), INFINITY, &point)) + { + gsk_path_point_get_position (&point, &pos); - if (graphene_point_distance (&pos, &GRAPHENE_POINT_INIT (x, y), NULL, NULL) <= MAZE_STROKE_SIZE_ACTIVE / 2.0f) - return; + if (graphene_point_distance (&pos, &GRAPHENE_POINT_INIT (x, y), NULL, NULL) <= MAZE_STROKE_SIZE_ACTIVE / 2.0f) + return; - self->active = FALSE; - gtk_widget_queue_draw (GTK_WIDGET (self)); + self->active = FALSE; + gtk_widget_queue_draw (GTK_WIDGET (self)); + } } static void diff --git a/demos/gtk-demo/path_text.c b/demos/gtk-demo/path_text.c index 2e6355ad87..caf4e24da5 100644 --- a/demos/gtk-demo/path_text.c +++ b/demos/gtk-demo/path_text.c @@ -88,15 +88,16 @@ gtk_path_transform_point (GskPathMeasure *measure, graphene_point_t *res) { graphene_vec2_t tangent; - GskPathPoint *point; + GskPathPoint point; - point = gsk_path_measure_get_point (measure, (pt->x + offset->x) * scale); - gsk_path_point_get_position (point, res); - gsk_path_point_get_tangent (point, GSK_PATH_END, &tangent); - gsk_path_point_unref (point); + if (gsk_path_measure_get_point (measure, (pt->x + offset->x) * scale, &point)) + { + gsk_path_point_get_position (&point, res); + gsk_path_point_get_tangent (&point, GSK_PATH_END, &tangent); - res->x -= (pt->y + offset->y) * scale * graphene_vec2_get_y (&tangent); - res->y += (pt->y + offset->y) * scale * graphene_vec2_get_x (&tangent); + res->x -= (pt->y + offset->y) * scale * graphene_vec2_get_y (&tangent); + res->y += (pt->y + offset->y) * scale * graphene_vec2_get_x (&tangent); + } } static gboolean @@ -325,21 +326,22 @@ gtk_path_widget_snapshot (GtkWidget *widget, if (self->line_closest >= 0) { GskPathBuilder *builder; - GskPathPoint *point; + GskPathPoint point; graphene_point_t closest; builder = gsk_path_builder_new (); - point = gsk_path_measure_get_point (self->line_measure, self->line_closest); - gsk_path_point_get_position (point, &closest); - gsk_path_point_unref (point); - gsk_path_builder_add_circle (builder, &closest, POINT_SIZE); - path = gsk_path_builder_free_to_path (builder); + if (gsk_path_measure_get_point (self->line_measure, self->line_closest, &point)) + { + gsk_path_point_get_position (&point, &closest); + gsk_path_builder_add_circle (builder, &closest, POINT_SIZE); + path = gsk_path_builder_free_to_path (builder); - gtk_snapshot_push_fill (snapshot, path, GSK_FILL_RULE_WINDING); - gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 0, 0, 1, 1 }, &GRAPHENE_RECT_INIT (0, 0, width, height)); - gtk_snapshot_pop (snapshot); + gtk_snapshot_push_fill (snapshot, path, GSK_FILL_RULE_WINDING); + gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 0, 0, 1, 1 }, &GRAPHENE_RECT_INIT (0, 0, width, height)); + gtk_snapshot_pop (snapshot); - gsk_path_unref (path); + gsk_path_unref (path); + } } } @@ -519,17 +521,19 @@ pointer_motion (GtkEventControllerMotion *controller, double y, GtkPathWidget *self) { - GskPathPoint *point; + GskPathPoint point; graphene_point_t pos; - point = gsk_path_get_closest_point (gsk_path_measure_get_path (self->line_measure), - &GRAPHENE_POINT_INIT (x, y), - INFINITY); - gsk_path_point_get_position (point, &pos); - self->line_closest = graphene_point_distance (&pos, &GRAPHENE_POINT_INIT (x, y), NULL, NULL); - gsk_path_point_unref (point); - - gtk_widget_queue_draw (GTK_WIDGET (self)); + if (gsk_path_get_closest_point (gsk_path_measure_get_path (self->line_measure), + &GRAPHENE_POINT_INIT (x, y), + INFINITY, + &point)) + { + gsk_path_point_get_position (&point, &pos); + self->line_closest = graphene_point_distance (&pos, &GRAPHENE_POINT_INIT (x, y), NULL, NULL); + + gtk_widget_queue_draw (GTK_WIDGET (self)); + } } static void diff --git a/gsk/gskcontour.c b/gsk/gskcontour.c index 3ea2c447d0..09b0104d92 100644 --- a/gsk/gskcontour.c +++ b/gsk/gskcontour.c @@ -64,17 +64,17 @@ struct _GskContourClass gboolean (* get_closest_point) (const GskContour *contour, const graphene_point_t *point, float threshold, - GskPathPoint *result, + GskRealPathPoint *result, float *out_dist); void (* get_position) (const GskContour *contour, - GskPathPoint *point, + GskRealPathPoint *point, graphene_point_t *position); void (* get_tangent) (const GskContour *contour, - GskPathPoint *point, + GskRealPathPoint *point, GskPathDirection direction, graphene_vec2_t *tangent); float (* get_curvature) (const GskContour *contour, - GskPathPoint *point, + GskRealPathPoint *point, graphene_point_t *center); gpointer (* init_measure) (const GskContour *contour, float tolerance, @@ -90,9 +90,9 @@ struct _GskContourClass void (* get_point) (const GskContour *contour, gpointer measure_data, float offset, - GskPathPoint *result); + GskRealPathPoint *result); float (* get_distance) (const GskContour *contour, - GskPathPoint *point, + GskRealPathPoint *point, gpointer measure_data); }; @@ -731,7 +731,7 @@ static gboolean gsk_standard_contour_get_closest_point (const GskContour *contour, const graphene_point_t *point, float threshold, - GskPathPoint *result, + GskRealPathPoint *result, float *out_dist) { GskStandardContour *self = (GskStandardContour *) contour; @@ -788,7 +788,7 @@ static void gsk_standard_contour_get_point (const GskContour *contour, gpointer measure_data, float distance, - GskPathPoint *result) + GskRealPathPoint *result) { GArray *array = measure_data; unsigned int idx; @@ -818,7 +818,7 @@ gsk_standard_contour_get_point (const GskContour *contour, static void gsk_standard_contour_get_position (const GskContour *contour, - GskPathPoint *point, + GskRealPathPoint *point, graphene_point_t *position) { GskStandardContour *self = (GskStandardContour *) contour; @@ -836,7 +836,7 @@ gsk_standard_contour_get_position (const GskContour *contour, static void gsk_standard_contour_get_tangent (const GskContour *contour, - GskPathPoint *point, + GskRealPathPoint *point, GskPathDirection direction, graphene_vec2_t *tangent) { @@ -855,7 +855,7 @@ gsk_standard_contour_get_tangent (const GskContour *contour, static float gsk_standard_contour_get_curvature (const GskContour *contour, - GskPathPoint *point, + GskRealPathPoint *point, graphene_point_t *center) { GskStandardContour *self = (GskStandardContour *) contour; @@ -870,7 +870,7 @@ gsk_standard_contour_get_curvature (const GskContour *contour, static float gsk_standard_contour_get_distance (const GskContour *contour, - GskPathPoint *point, + GskRealPathPoint *point, gpointer measure_data) { GArray *array = measure_data; @@ -1389,7 +1389,7 @@ static gboolean gsk_rect_contour_get_closest_point (const GskContour *contour, const graphene_point_t *point, float threshold, - GskPathPoint *result, + GskRealPathPoint *result, float *out_dist) { const GskRectContour *self = (const GskRectContour *) contour; @@ -1408,7 +1408,7 @@ static void gsk_rect_contour_get_point (const GskContour *contour, gpointer measure_data, float offset, - GskPathPoint *result) + GskRealPathPoint *result) { const GskRectContour *self = (const GskRectContour *) contour; @@ -1417,7 +1417,7 @@ gsk_rect_contour_get_point (const GskContour *contour, static void gsk_rect_contour_get_position (const GskContour *contour, - GskPathPoint *point, + GskRealPathPoint *point, graphene_point_t *position) { const GskRectContour *self = (const GskRectContour *) contour; @@ -1427,7 +1427,7 @@ gsk_rect_contour_get_position (const GskContour *contour, static void gsk_rect_contour_get_tangent (const GskContour *contour, - GskPathPoint *point, + GskRealPathPoint *point, GskPathDirection direction, graphene_vec2_t *tangent) { @@ -1438,7 +1438,7 @@ gsk_rect_contour_get_tangent (const GskContour *contour, static float gsk_rect_contour_get_curvature (const GskContour *contour, - GskPathPoint *point, + GskRealPathPoint *point, graphene_point_t *center) { return 0; @@ -1446,7 +1446,7 @@ gsk_rect_contour_get_curvature (const GskContour *contour, static float gsk_rect_contour_get_distance (const GskContour *contour, - GskPathPoint *point, + GskRealPathPoint *point, gpointer measure_data) { return point->data.rect.distance; @@ -1831,7 +1831,7 @@ static gboolean gsk_circle_contour_get_closest_point (const GskContour *contour, const graphene_point_t *point, float threshold, - GskPathPoint *result, + GskRealPathPoint *result, float *out_dist) { const GskCircleContour *self = (const GskCircleContour *) contour; @@ -1851,7 +1851,7 @@ static void gsk_circle_contour_get_point (const GskContour *contour, gpointer measure_data, float distance, - GskPathPoint *result) + GskRealPathPoint *result) { const GskCircleContour *self = (const GskCircleContour *) contour; float delta = self->end_angle - self->start_angle; @@ -1862,7 +1862,7 @@ gsk_circle_contour_get_point (const GskContour *contour, static void gsk_circle_contour_get_position (const GskContour *contour, - GskPathPoint *point, + GskRealPathPoint *point, graphene_point_t *position) { const GskCircleContour *self = (const GskCircleContour *) contour; @@ -1872,20 +1872,20 @@ gsk_circle_contour_get_position (const GskContour *contour, static void gsk_circle_contour_get_tangent (const GskContour *contour, - GskPathPoint *point, + GskRealPathPoint *point, GskPathDirection direction, graphene_vec2_t *tangent) { const GskCircleContour *self = (const GskCircleContour *) contour; - graphene_point_t p = GSK_CIRCLE_POINT_INIT (self, point->data.circle.angle); + graphene_point_t pos = GSK_CIRCLE_POINT_INIT (self, point->data.circle.angle); - graphene_vec2_init (tangent, p.y - self->center.y, - p.x + self->center.x); + graphene_vec2_init (tangent, pos.y - self->center.y, - pos.x + self->center.x); graphene_vec2_normalize (tangent, tangent); } static float gsk_circle_contour_get_curvature (const GskContour *contour, - GskPathPoint *point, + GskRealPathPoint *point, graphene_point_t *center) { const GskCircleContour *self = (const GskCircleContour *) contour; @@ -1898,7 +1898,7 @@ gsk_circle_contour_get_curvature (const GskContour *contour, static float gsk_circle_contour_get_distance (const GskContour *contour, - GskPathPoint *point, + GskRealPathPoint *point, gpointer measure_data) { const GskCircleContour *self = (const GskCircleContour *) contour; @@ -2331,7 +2331,7 @@ static gboolean gsk_rounded_rect_contour_get_closest_point (const GskContour *contour, const graphene_point_t *point, float threshold, - GskPathPoint *result, + GskRealPathPoint *result, float *out_dist) { GskPath *path; @@ -2350,7 +2350,7 @@ static void gsk_rounded_rect_contour_get_point (const GskContour *contour, gpointer measure_data, float distance, - GskPathPoint *result) + GskRealPathPoint *result) { RoundedRectMeasureData *data = measure_data; @@ -2359,7 +2359,7 @@ gsk_rounded_rect_contour_get_point (const GskContour *contour, static void gsk_rounded_rect_contour_get_position (const GskContour *contour, - GskPathPoint *point, + GskRealPathPoint *point, graphene_point_t *position) { GskCurve curve; @@ -2370,7 +2370,7 @@ gsk_rounded_rect_contour_get_position (const GskContour *contour, static void gsk_rounded_rect_contour_get_tangent (const GskContour *contour, - GskPathPoint *point, + GskRealPathPoint *point, GskPathDirection direction, graphene_vec2_t *tangent) { @@ -2382,7 +2382,7 @@ gsk_rounded_rect_contour_get_tangent (const GskContour *contour, static float gsk_rounded_rect_contour_get_curvature (const GskContour *contour, - GskPathPoint *point, + GskRealPathPoint *point, graphene_point_t *center) { GskCurve curve; @@ -2393,7 +2393,7 @@ gsk_rounded_rect_contour_get_curvature (const GskContour *contour, static float gsk_rounded_rect_contour_get_distance (const GskContour *contour, - GskPathPoint *point, + GskRealPathPoint *point, gpointer measure_data) { RoundedRectMeasureData *data = measure_data; @@ -2555,7 +2555,7 @@ gboolean gsk_contour_get_closest_point (const GskContour *self, const graphene_point_t *point, float threshold, - GskPathPoint *result, + GskRealPathPoint *result, float *out_dist) { return self->klass->get_closest_point (self, point, threshold, result, out_dist); @@ -2565,7 +2565,7 @@ void gsk_contour_get_point (const GskContour *self, gpointer measure_data, float offset, - GskPathPoint *result) + GskRealPathPoint *result) { result->contour = self; self->klass->get_point (self, measure_data, offset, result); @@ -2573,7 +2573,7 @@ gsk_contour_get_point (const GskContour *self, void gsk_contour_get_position (const GskContour *self, - GskPathPoint *point, + GskRealPathPoint *point, graphene_point_t *pos) { self->klass->get_position (self, point, pos); @@ -2581,7 +2581,7 @@ gsk_contour_get_position (const GskContour *self, void gsk_contour_get_tangent (const GskContour *self, - GskPathPoint *point, + GskRealPathPoint *point, GskPathDirection direction, graphene_vec2_t *tangent) { @@ -2590,7 +2590,7 @@ gsk_contour_get_tangent (const GskContour *self, float gsk_contour_get_curvature (const GskContour *self, - GskPathPoint *point, + GskRealPathPoint *point, graphene_point_t *center) { return self->klass->get_curvature (self, point, center); @@ -2598,7 +2598,7 @@ gsk_contour_get_curvature (const GskContour *self, float gsk_contour_get_distance (const GskContour *self, - GskPathPoint *point, + GskRealPathPoint *point, gpointer measure_data) { return self->klass->get_distance (self, point, measure_data); diff --git a/gsk/gskcontourprivate.h b/gsk/gskcontourprivate.h index f119209786..6a9606399a 100644 --- a/gsk/gskcontourprivate.h +++ b/gsk/gskcontourprivate.h @@ -20,20 +20,12 @@ #pragma once -#include "gskpath.h" - +#include "gskpathprivate.h" +#include "gskpathpointprivate.h" #include "gskpathopprivate.h" G_BEGIN_DECLS -typedef enum -{ - GSK_PATH_FLAT, - GSK_PATH_CLOSED -} GskPathFlags; - -typedef struct _GskContour GskContour; - GskContour * gsk_rect_contour_new (const graphene_rect_t *rect); GskContour * gsk_rounded_rect_contour_new (const GskRoundedRect *rounded_rect); GskContour * gsk_circle_contour_new (const graphene_point_t *center, @@ -74,19 +66,19 @@ int gsk_contour_get_winding (const GskContou gboolean gsk_contour_get_closest_point (const GskContour *self, const graphene_point_t *point, float threshold, - GskPathPoint *result, + GskRealPathPoint *result, float *out_dist); void gsk_contour_get_position (const GskContour *self, - GskPathPoint *point, + GskRealPathPoint *point, graphene_point_t *pos); void gsk_contour_get_tangent (const GskContour *self, - GskPathPoint *point, + GskRealPathPoint *point, GskPathDirection direction, graphene_vec2_t *tangent); float gsk_contour_get_curvature (const GskContour *self, - GskPathPoint *point, + GskRealPathPoint *point, graphene_point_t *center); gpointer gsk_contour_init_measure (const GskContour *self, float tolerance, @@ -102,9 +94,9 @@ void gsk_contour_add_segment (const GskContou void gsk_contour_get_point (const GskContour *self, gpointer measure_data, float offset, - GskPathPoint *result); + GskRealPathPoint *result); float gsk_contour_get_distance (const GskContour *self, - GskPathPoint *point, + GskRealPathPoint *point, gpointer measure_data); gboolean gsk_contour_dash (const GskContour *contour, GskStroke *stroke, diff --git a/gsk/gskpath.c b/gsk/gskpath.c index 9d8accdb90..9c4a00a6f5 100644 --- a/gsk/gskpath.c +++ b/gsk/gskpath.c @@ -500,48 +500,47 @@ gsk_path_in_fill (GskPath *self, * @self: a `GskPath` * @point: the point * @threshold: maximum allowed distance + * @result: (out caller-allocates): return location for the closest point * * Computes the closest point on the path to the given point - * and returns a `GskPathPoint` for it. + * and sets the @result to it. * - * If there is no point closer than the given threshold, `NULL` - * is returned. + * If there is no point closer than the given threshold, + * `FALSE` is returned. * - * Returns: (transfer full) (nullable): the closest point - * on @self, or `NULL` if no point is closer than @threshold + * Returns: `TRUE` if @point was set to the closest point + * on @self, `FALSE` if no point is closer than @threshold * * Since: 4.14 */ -GskPathPoint * +gboolean gsk_path_get_closest_point (GskPath *self, const graphene_point_t *point, - float threshold) + float threshold, + GskPathPoint *result) { - GskPathPoint *p; + GskRealPathPoint *res = (GskRealPathPoint *) result; - g_return_val_if_fail (self != NULL, NULL); - g_return_val_if_fail (point != NULL, NULL); - g_return_val_if_fail (threshold >= 0, NULL); - - p = gsk_path_point_new (self); + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (point != NULL, FALSE); + g_return_val_if_fail (threshold >= 0, FALSE); + g_return_val_if_fail (result != NULL, FALSE); for (int i = 0; i < self->n_contours; i++) { float distance; - if (gsk_contour_get_closest_point (self->contours[i], point, threshold, p, &distance)) + if (gsk_contour_get_closest_point (self->contours[i], point, threshold, res, &distance)) { - p->contour = self->contours[i]; + res->contour = self->contours[i]; threshold = distance; } } - if (p->contour != NULL) - return p; + if (res->contour != NULL) + return TRUE; - gsk_path_point_unref (p); - - return NULL; + return FALSE; } /** diff --git a/gsk/gskpath.h b/gsk/gskpath.h index 60d934e5e1..ab43b171a7 100644 --- a/gsk/gskpath.h +++ b/gsk/gskpath.h @@ -107,9 +107,10 @@ gboolean gsk_path_in_fill (GskPath GskFillRule fill_rule); GDK_AVAILABLE_IN_4_14 -GskPathPoint * gsk_path_get_closest_point (GskPath *self, +gboolean gsk_path_get_closest_point (GskPath *self, const graphene_point_t *point, - float threshold); + float threshold, + GskPathPoint *result); GDK_AVAILABLE_IN_4_14 gboolean gsk_path_foreach (GskPath *self, diff --git a/gsk/gskpathbuilder.c b/gsk/gskpathbuilder.c index 9e96e6a1e5..445aee3551 100644 --- a/gsk/gskpathbuilder.c +++ b/gsk/gskpathbuilder.c @@ -24,6 +24,7 @@ #include "gskpathbuilder.h" #include "gskpathprivate.h" +#include "gskcontourprivate.h" /** * GskPathBuilder: diff --git a/gsk/gskpathmeasure.c b/gsk/gskpathmeasure.c index 27116cb560..c264b0a69b 100644 --- a/gsk/gskpathmeasure.c +++ b/gsk/gskpathmeasure.c @@ -338,29 +338,31 @@ gsk_path_builder_add_segment (GskPathBuilder *self, * gsk_path_measure_get_point: * @self: a `GskPathMeasure` * @distance: the distance + * @result: (out caller-allocates): return location for the result * - * Returns a `GskPathPoint` representing the point at the given - * distance into the path. + * Sets @result to the point at the given distance into the path. * - * An empty path has no points, so `NULL` is returned in that case. + * An empty path has no points, so `FALSE` is returned in that case. * - * Returns: (transfer full) (nullable): a newly allocated `GskPathPoint` + * Returns: `TRUE` if @result was set * * Since: 4.14 */ -GskPathPoint * +gboolean gsk_path_measure_get_point (GskPathMeasure *self, - float distance) + float distance, + GskPathPoint *result) { + GskRealPathPoint *res = (GskRealPathPoint *) result; gsize i; float offset; const GskContour *contour; - GskPathPoint *point; - g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (result != NULL, FALSE); if (self->n_contours == 0) - return NULL; + return FALSE; offset = gsk_path_measure_clamp_distance (self, distance); @@ -378,28 +380,28 @@ gsk_path_measure_get_point (GskPathMeasure *self, contour = gsk_path_get_contour (self->path, i); - point = gsk_path_point_new (self->path); - gsk_contour_get_point (contour, self->measures[i].contour_data, offset, point); + gsk_contour_get_point (contour, self->measures[i].contour_data, offset, res); - return point; + return TRUE; } float gsk_path_measure_get_distance (GskPathMeasure *self, GskPathPoint *point) { - const GskContour *contour = gsk_path_point_get_contour (point); + GskRealPathPoint *p = (GskRealPathPoint *)point; + const GskContour *contour = p->contour; float contour_offset = 0; g_return_val_if_fail (self != NULL, 0); g_return_val_if_fail (point != NULL, 0); - g_return_val_if_fail (self->path == point->path, 0); + g_return_val_if_fail (self->path == p->path, 0); for (gsize i = 0; i < self->n_contours; i++) { if (contour == gsk_path_get_contour (self->path, i)) return contour_offset + gsk_contour_get_distance (contour, - point, + p, self->measures[i].contour_data); contour_offset += self->measures[i].length; diff --git a/gsk/gskpathmeasure.h b/gsk/gskpathmeasure.h index 3acac0c368..4a14c89d52 100644 --- a/gsk/gskpathmeasure.h +++ b/gsk/gskpathmeasure.h @@ -53,8 +53,9 @@ GDK_AVAILABLE_IN_4_14 float gsk_path_measure_get_length (GskPathMeasure *self); GDK_AVAILABLE_IN_4_14 -GskPathPoint * gsk_path_measure_get_point (GskPathMeasure *self, - float distance); +gboolean gsk_path_measure_get_point (GskPathMeasure *self, + float distance, + GskPathPoint *point); GDK_AVAILABLE_IN_4_14 float gsk_path_measure_get_distance (GskPathMeasure *self, diff --git a/gsk/gskpathpoint.c b/gsk/gskpathpoint.c index 1685421493..26ae799b5e 100644 --- a/gsk/gskpathpoint.c +++ b/gsk/gskpathpoint.c @@ -30,93 +30,62 @@ /** * GskPathPoint: * - * `GskPathPoint` is an opaque, immutable type representing a point on a path. + * `GskPathPoint` is an opaque type representing a point on a path. * * It can be queried for properties of the path at that point, such as its * tangent or its curvature. * * To obtain a `GskPathPoint`, use [method@Gsk.Path.get_closest_point] * or [method@Gsk.PathMeasure.get_point]. + * + * Note that `GskPathPoint` structs are meant to be stack-allocated, and + * don't a reference to the path object they are obtained from. It is the + * callers responsibility to keep a reference to the path as long as the + * `GskPathPoint` is used. */ G_DEFINE_BOXED_TYPE (GskPathPoint, gsk_path_point, - gsk_path_point_ref, - gsk_path_point_unref) + gsk_path_point_copy, + gsk_path_point_free) GskPathPoint * -gsk_path_point_new (GskPath *path) +gsk_path_point_copy (GskPathPoint *point) { - GskPathPoint *self; + GskPathPoint *copy; - self = g_new0 (GskPathPoint, 1); + copy = g_new0 (GskPathPoint, 1); - self->ref_count = 1; + memcpy (copy, point, sizeof (GskRealPathPoint)); - self->path = gsk_path_ref (path); + return copy; +} - return self; +void +gsk_path_point_free (GskPathPoint *point) +{ + g_free (point); } GskPath * -gsk_path_point_get_path (GskPathPoint *self) +gsk_path_point_get_path (GskPathPoint *point) { + GskRealPathPoint *self = (GskRealPathPoint *) point; + return self->path; } const GskContour * -gsk_path_point_get_contour (GskPathPoint *self) +gsk_path_point_get_contour (GskPathPoint *point) { + GskRealPathPoint *self = (GskRealPathPoint *) point; + return self->contour; } -/** - * gsk_path_point_ref: - * @self: a `GskPathPoint` - * - * Increases the reference count of a `GskPathPoint` by one. - * - * Returns: the passed in `GskPathPoint` - * - * Since: 4.14 - */ -GskPathPoint * -gsk_path_point_ref (GskPathPoint *self) -{ - g_return_val_if_fail (self != NULL, NULL); - - self->ref_count++; - - return self; -} - -/** - * gsk_path_point_unref: - * @self: a `GskPathPoint` - * - * Decreases the reference count of a `GskPathPoint` by one. - * - * If the resulting reference count is zero, frees the object. - * - * Since: 4.14 - */ -void -gsk_path_point_unref (GskPathPoint *self) -{ - g_return_if_fail (self != NULL); - g_return_if_fail (self->ref_count > 0); - - self->ref_count--; - if (self->ref_count > 0) - return; - - gsk_path_unref (self->path); - g_free (self); -} - /** * gsk_path_point_get_position: - * @self: a `GskPathPoint` + * @point: a `GskPathPoint` * @position: (out caller-allocates): Return location for * the coordinates of the point * @@ -125,15 +94,17 @@ gsk_path_point_unref (GskPathPoint *self) * Since: 4.14 */ void -gsk_path_point_get_position (GskPathPoint *self, +gsk_path_point_get_position (GskPathPoint *point, graphene_point_t *position) { + GskRealPathPoint *self = (GskRealPathPoint *) point; + gsk_contour_get_position (self->contour, self, position); } /** * gsk_path_point_get_tangent: - * @self: a `GskPathPoint` + * @point: a `GskPathPoint` * @direction: the direction for which to return the tangent * @tangent: (out caller-allocates): Return location for * the tangent at the point @@ -149,16 +120,18 @@ gsk_path_point_get_position (GskPathPoint *self, * Since: 4.14 */ void -gsk_path_point_get_tangent (GskPathPoint *self, +gsk_path_point_get_tangent (GskPathPoint *point, GskPathDirection direction, graphene_vec2_t *tangent) { + GskRealPathPoint *self = (GskRealPathPoint *) point; + gsk_contour_get_tangent (self->contour, self, direction, tangent); } /** * gsk_path_point_get_curvature: - * @self: a `GskPathPoint` + * @point: a `GskPathPoint` * @center: (out caller-allocates): Return location for * the center of the osculating circle * @@ -174,15 +147,19 @@ gsk_path_point_get_tangent (GskPathPoint *self, * Since: 4.14 */ float -gsk_path_point_get_curvature (GskPathPoint *self, +gsk_path_point_get_curvature (GskPathPoint *point, graphene_point_t *center) { + GskRealPathPoint *self = (GskRealPathPoint *) point; + return gsk_contour_get_curvature (self->contour, self, center); } float -gsk_path_point_get_distance (GskPathPoint *self, +gsk_path_point_get_distance (GskPathPoint *point, gpointer measure_data) { + GskRealPathPoint *self = (GskRealPathPoint *) point; + return gsk_contour_get_distance (self->contour, self, measure_data); } diff --git a/gsk/gskpathpoint.h b/gsk/gskpathpoint.h index 2828631f02..72acbaee2d 100644 --- a/gsk/gskpathpoint.h +++ b/gsk/gskpathpoint.h @@ -30,27 +30,35 @@ G_BEGIN_DECLS #define GSK_TYPE_PATH_POINT (gsk_path_point_get_type ()) +typedef struct _GskPathPoint GskPathPoint; +struct _GskPathPoint { + /*< private >*/ + union { + float f[8]; + gpointer p[8]; + } data; +}; + GDK_AVAILABLE_IN_4_14 GType gsk_path_point_get_type (void) G_GNUC_CONST; GDK_AVAILABLE_IN_4_14 -GskPathPoint * gsk_path_point_ref (GskPathPoint *self); -GDK_AVAILABLE_IN_4_14 -void gsk_path_point_unref (GskPathPoint *self); +GskPathPoint * gsk_path_point_copy (GskPathPoint *point); GDK_AVAILABLE_IN_4_14 -void gsk_path_point_get_position (GskPathPoint *self, +void gsk_path_point_free (GskPathPoint *point); + +GDK_AVAILABLE_IN_4_14 +void gsk_path_point_get_position (GskPathPoint *point, graphene_point_t *position); GDK_AVAILABLE_IN_4_14 -void gsk_path_point_get_tangent (GskPathPoint *self, +void gsk_path_point_get_tangent (GskPathPoint *point, GskPathDirection direction, graphene_vec2_t *tangent); GDK_AVAILABLE_IN_4_14 -float gsk_path_point_get_curvature (GskPathPoint *self, +float gsk_path_point_get_curvature (GskPathPoint *point, graphene_point_t *center); -G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskPathPoint, gsk_path_point_unref) - G_END_DECLS diff --git a/gsk/gskpathpointprivate.h b/gsk/gskpathpointprivate.h index 260854f99b..6194a4a8cb 100644 --- a/gsk/gskpathpointprivate.h +++ b/gsk/gskpathpointprivate.h @@ -5,10 +5,8 @@ G_BEGIN_DECLS -struct _GskPathPoint +struct _GskRealPathPoint { - guint ref_count; - GskPath *path; const GskContour *contour; @@ -26,8 +24,6 @@ struct _GskPathPoint } data; }; -GskPathPoint * gsk_path_point_new (GskPath *path); - GskPath * gsk_path_point_get_path (GskPathPoint *self); const GskContour * gsk_path_point_get_contour (GskPathPoint *self); float gsk_path_point_get_distance (GskPathPoint *self, diff --git a/gsk/gskpathprivate.h b/gsk/gskpathprivate.h index 84c098fae2..8e37c0798d 100644 --- a/gsk/gskpathprivate.h +++ b/gsk/gskpathprivate.h @@ -22,11 +22,19 @@ #include "gskpath.h" -#include "gskcontourprivate.h" #include "gskpathopprivate.h" G_BEGIN_DECLS +typedef enum +{ + GSK_PATH_FLAT, + GSK_PATH_CLOSED +} GskPathFlags; + +typedef struct _GskContour GskContour; +typedef struct _GskRealPathPoint GskRealPathPoint; + /* Same as Skia, so looks like a good value. ¯\_(ツ)_/¯ */ #define GSK_PATH_TOLERANCE_DEFAULT (0.5) diff --git a/testsuite/gsk/curve.c b/testsuite/gsk/curve.c index 4babcaf637..81454323a3 100644 --- a/testsuite/gsk/curve.c +++ b/testsuite/gsk/curve.c @@ -269,14 +269,15 @@ test_curve_decompose_conic (void) /* Check that the curves we got are approximating the conic */ for (int k = 0; k < 11; k++) { - GskPathPoint *point; + GskPathPoint point; graphene_point_t p, q; gsk_curve_get_point (c2, k/10.0, &p); - point = gsk_path_get_closest_point (path, &p, INFINITY); - gsk_path_point_get_position (point, &q); - g_assert_true (graphene_point_near (&p, &q, 0.5)); - gsk_path_point_unref (point); + if (gsk_path_get_closest_point (path, &p, INFINITY, &point)) + { + gsk_path_point_get_position (&point, &q); + g_assert_true (graphene_point_near (&p, &q, 0.5)); + } } } diff --git a/testsuite/gsk/measure-special-cases.c b/testsuite/gsk/measure-special-cases.c index 3d55ec6dbd..7bcdc0238f 100644 --- a/testsuite/gsk/measure-special-cases.c +++ b/testsuite/gsk/measure-special-cases.c @@ -93,10 +93,11 @@ test_rect (void) GskPathBuilder *builder; GskPath *path; GskPathMeasure *measure; - GskPathPoint *point; + GskPathPoint point; graphene_point_t p; graphene_vec2_t tangent, expected_tangent; float length; + gboolean ret; builder = gsk_path_builder_new (); gsk_path_builder_add_rect (builder, &GRAPHENE_RECT_INIT (0, 0, 100, 50)); @@ -107,37 +108,37 @@ test_rect (void) g_assert_true (length == 300); #define TEST_POS_AT(distance, X, Y) \ - point = gsk_path_measure_get_point (measure, distance); \ - gsk_path_point_get_position (point, &p); \ + ret = gsk_path_measure_get_point (measure, distance, &point); \ + g_assert_true (ret); \ + gsk_path_point_get_position (&point, &p); \ g_assert_true (graphene_point_near (&p, &GRAPHENE_POINT_INIT (X, Y), 0.01)); \ - gsk_path_point_unref (point); \ - point = gsk_path_get_closest_point (path, &GRAPHENE_POINT_INIT (X, Y), INFINITY); \ + ret = gsk_path_get_closest_point (path, &GRAPHENE_POINT_INIT (X, Y), INFINITY, &point); \ + g_assert_true (ret); \ if (distance < length) \ - g_assert_true (fabs (gsk_path_measure_get_distance (measure, point) - distance) < 0.01); \ + g_assert_true (fabs (gsk_path_measure_get_distance (measure, &point) - distance) < 0.01); \ else \ - g_assert_true (fabs (gsk_path_measure_get_distance (measure, point)) < 0.01); \ - gsk_path_point_get_position (point, &p); \ + g_assert_true (fabs (gsk_path_measure_get_distance (measure, &point)) < 0.01); \ + gsk_path_point_get_position (&point, &p); \ g_assert_true (graphene_point_near (&p, &GRAPHENE_POINT_INIT (X, Y), 0.01)); \ - gsk_path_point_unref (point); #define TEST_TANGENT_AT(distance, x1, y1, x2, y2) \ - point = gsk_path_measure_get_point (measure, distance); \ - gsk_path_point_get_tangent (point, GSK_PATH_START, &tangent); \ + ret = gsk_path_measure_get_point (measure, distance, &point); \ + g_assert_true (ret); \ + gsk_path_point_get_tangent (&point, GSK_PATH_START, &tangent); \ g_assert_true (graphene_vec2_near (&tangent, graphene_vec2_init (&expected_tangent, x1, y1), 0.01)); \ - gsk_path_point_get_tangent (point, GSK_PATH_END, &tangent); \ + gsk_path_point_get_tangent (&point, GSK_PATH_END, &tangent); \ g_assert_true (graphene_vec2_near (&tangent, graphene_vec2_init (&expected_tangent, x2, y2), 0.01)); \ - gsk_path_point_unref (point); \ #define TEST_POS_AT2(distance, X, Y, expected_distance) \ - point = gsk_path_measure_get_point (measure, distance); \ - gsk_path_point_get_position (point, &p); \ + ret = gsk_path_measure_get_point (measure, distance, &point); \ + g_assert_true (ret); \ + gsk_path_point_get_position (&point, &p); \ g_assert_true (graphene_point_near (&p, &GRAPHENE_POINT_INIT (X, Y), 0.01)); \ - gsk_path_point_unref (point); \ - point = gsk_path_get_closest_point (path, &GRAPHENE_POINT_INIT (X, Y), INFINITY); \ - g_assert_true (fabs (gsk_path_measure_get_distance (measure, point) - expected_distance) < 0.01); \ - gsk_path_point_get_position (point, &p); \ + ret = gsk_path_get_closest_point (path, &GRAPHENE_POINT_INIT (X, Y), INFINITY, &point); \ + g_assert_true (ret); \ + g_assert_true (fabs (gsk_path_measure_get_distance (measure, &point) - expected_distance) < 0.01); \ + gsk_path_point_get_position (&point, &p); \ g_assert_true (graphene_point_near (&p, &GRAPHENE_POINT_INIT (X, Y), 0.01)); \ - gsk_path_point_unref (point); TEST_POS_AT (0, 0, 0) TEST_POS_AT (25, 25, 0) diff --git a/testsuite/gsk/measure.c b/testsuite/gsk/measure.c index 42cb5e349c..35f4eb7dbe 100644 --- a/testsuite/gsk/measure.c +++ b/testsuite/gsk/measure.c @@ -527,11 +527,12 @@ test_get_point (void) static const float tolerance = 1.0; GskPath *path; GskPathMeasure *measure; - GskPathPoint *point; + GskPathPoint point; guint n_discontinuities; float length, offset, last_offset; graphene_point_t p, last_point; guint i, j; + gboolean ret; for (i = 0; i < 10; i++) { @@ -540,14 +541,13 @@ test_get_point (void) length = gsk_path_measure_get_length (measure); n_discontinuities = 0; - point = gsk_path_measure_get_point (measure, 0); - if (point == NULL) + ret = gsk_path_measure_get_point (measure, 0, &point); + if (!ret) { g_assert_true (gsk_path_is_empty (path)); continue; } - gsk_path_point_get_position (point, &last_point); - gsk_path_point_unref (point); + gsk_path_point_get_position (&point, &last_point); /* FIXME: anything we can test with tangents here? */ last_offset = 0; @@ -555,9 +555,9 @@ test_get_point (void) for (j = 1; j <= 1024; j++) { offset = length * j / 1024; - point = gsk_path_measure_get_point (measure, offset); - gsk_path_point_get_position (point, &p); - gsk_path_point_unref (point); + ret = gsk_path_measure_get_point (measure, offset, &point); + g_assert_true (ret); + gsk_path_point_get_position (&point, &p); if (graphene_point_distance (&last_point, &p, NULL, NULL) > 2 * (offset - last_offset)) { @@ -581,8 +581,9 @@ test_closest_point (void) GskPath *path, *path1, *path2; GskPathMeasure *measure, *measure1, *measure2; GskPathBuilder *builder; - GskPathPoint *point; + GskPathPoint point; guint i, j; + gboolean ret; if (!g_test_slow ()) { @@ -614,32 +615,29 @@ test_closest_point (void) offset1 = offset2 = offset = 0; distance1 = distance2 = distance = 0; - point = gsk_path_get_closest_point (path1, &test, INFINITY); - g_assert_true (point != NULL); + ret = gsk_path_get_closest_point (path1, &test, INFINITY, &point); + g_assert_true (ret); - gsk_path_point_get_position (point, &p1); - gsk_path_point_get_tangent (point, GSK_PATH_END, &t1); - offset1 = gsk_path_measure_get_distance (measure1, point); + gsk_path_point_get_position (&point, &p1); + gsk_path_point_get_tangent (&point, GSK_PATH_END, &t1); + offset1 = gsk_path_measure_get_distance (measure1, &point); distance1 = graphene_point_distance (&p1, &test, NULL, NULL); - gsk_path_point_unref (point); - point = gsk_path_get_closest_point (path2, &test, INFINITY); - g_assert_true (point != NULL); + ret = gsk_path_get_closest_point (path2, &test, INFINITY, &point); + g_assert_true (ret); - gsk_path_point_get_position (point, &p2); - gsk_path_point_get_tangent (point, GSK_PATH_END, &t2); - offset2 = gsk_path_measure_get_distance (measure2, point); + gsk_path_point_get_position (&point, &p2); + gsk_path_point_get_tangent (&point, GSK_PATH_END, &t2); + offset2 = gsk_path_measure_get_distance (measure2, &point); distance2 = graphene_point_distance (&p2, &test, NULL, NULL); - gsk_path_point_unref (point); - point = gsk_path_get_closest_point (path, &test, INFINITY); - g_assert_true (point != NULL); + ret = gsk_path_get_closest_point (path, &test, INFINITY, &point); + g_assert_true (ret); - gsk_path_point_get_position (point, &p); - gsk_path_point_get_tangent (point, GSK_PATH_END, &t); - offset = gsk_path_measure_get_distance (measure, point); + gsk_path_point_get_position (&point, &p); + gsk_path_point_get_tangent (&point, GSK_PATH_END, &t); + offset = gsk_path_measure_get_distance (measure, &point); distance = graphene_point_distance (&p, &test, NULL, NULL); - gsk_path_point_unref (point); if (distance1 == distance) { @@ -674,10 +672,11 @@ test_closest_point_for_point (void) static const float tolerance = 0.5; GskPath *path; GskPathMeasure *measure; - GskPathPoint *point; + GskPathPoint point; float length, offset, distance; graphene_point_t p, closest_point; guint i, j; + gboolean ret; if (!g_test_slow ()) { @@ -701,15 +700,14 @@ test_closest_point_for_point (void) for (j = 0; j < 100; j++) { offset = g_test_rand_double_range (0, length); - point = gsk_path_measure_get_point (measure, offset); - gsk_path_point_get_position (point, &p); - gsk_path_point_unref (point); - point = gsk_path_get_closest_point (path, &p, 2 * tolerance); - g_assert_nonnull (point); - gsk_path_point_get_position (point, &closest_point); - //closest_offset = gsk_path_measure_get_distance (measure, point); + ret = gsk_path_measure_get_point (measure, offset, &point); + g_assert_true (ret); + gsk_path_point_get_position (&point, &p); + ret = gsk_path_get_closest_point (path, &p, 2 * tolerance, &point); + g_assert_true (ret); + gsk_path_point_get_position (&point, &closest_point); + //closest_offset = gsk_path_measure_get_distance (measure, &point); distance = graphene_point_distance (&p, &closest_point, NULL, NULL); - gsk_path_point_unref (point); /* should be given due to the TRUE return above, but who knows... */ g_assert_cmpfloat (distance, <=, 2 * tolerance);