Make points stack-allocated

This does the necessary reshuffling to make GskPathPoint
a stack-allocated struct.
This commit is contained in:
Matthias Clasen
2023-08-05 10:57:47 -04:00
parent 1de378655e
commit b533dfa0da
17 changed files with 269 additions and 278 deletions

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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,

View File

@@ -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;
}
/**

View File

@@ -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,

View File

@@ -24,6 +24,7 @@
#include "gskpathbuilder.h"
#include "gskpathprivate.h"
#include "gskcontourprivate.h"
/**
* GskPathBuilder:

View File

@@ -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;

View File

@@ -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,

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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,

View File

@@ -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)

View File

@@ -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));
}
}
}

View File

@@ -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)

View File

@@ -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);