Add gsk_path_get_previous/next_point

These functions let you iterate over the 'significant'
points of a path.
This commit is contained in:
Matthias Clasen
2023-08-08 11:06:35 -04:00
parent a0d17418de
commit 244cdafe1b
4 changed files with 198 additions and 0 deletions

View File

@@ -70,6 +70,12 @@ struct _GskContourClass
GskRealPathPoint *result);
void (* get_end_point) (const GskContour *contour,
GskRealPathPoint *result);
gboolean (* get_previous_point) (const GskContour *contour,
GskRealPathPoint *point,
GskRealPathPoint *result);
gboolean (* get_next_point) (const GskContour *contour,
GskRealPathPoint *point,
GskRealPathPoint *result);
void (* get_position) (const GskContour *contour,
GskRealPathPoint *point,
graphene_point_t *position);
@@ -704,6 +710,50 @@ gsk_standard_contour_get_end_point (const GskContour *contour,
result->data.std.t = 1;
}
static gboolean
gsk_standard_contour_get_previous_point (const GskContour *contour,
GskRealPathPoint *point,
GskRealPathPoint *result)
{
if (point->data.std.t > 0)
{
result->data.std.idx = point->data.std.idx;
result->data.std.t = 0;
return TRUE;
}
else if (point->data.std.idx > 1)
{
result->data.std.idx = point->data.std.idx - 1;
result->data.std.t = 0;
return TRUE;
}
return FALSE;
}
static gboolean
gsk_standard_contour_get_next_point (const GskContour *contour,
GskRealPathPoint *point,
GskRealPathPoint *result)
{
GskStandardContour *self = (GskStandardContour *) contour;
if (point->data.std.t < 1)
{
result->data.std.idx = point->data.std.idx;
result->data.std.t = 1;
return TRUE;
}
else if (point->data.std.idx + 1 < self->n_ops - 1)
{
result->data.std.idx = point->data.std.idx + 1;
result->data.std.t = 1;
return TRUE;
}
return FALSE;
}
static void
gsk_standard_contour_get_point (const GskContour *contour,
gpointer measure_data,
@@ -871,6 +921,8 @@ static const GskContourClass GSK_STANDARD_CONTOUR_CLASS =
gsk_standard_contour_get_closest_point,
gsk_standard_contour_get_start_point,
gsk_standard_contour_get_end_point,
gsk_standard_contour_get_previous_point,
gsk_standard_contour_get_next_point,
gsk_standard_contour_get_position,
gsk_standard_contour_get_tangent,
gsk_standard_contour_get_curvature,
@@ -1073,6 +1125,22 @@ gsk_contour_get_end_point (const GskContour *self,
self->klass->get_end_point (self, result);
}
gboolean
gsk_contour_get_previous_point (const GskContour *self,
GskRealPathPoint *point,
GskRealPathPoint *result)
{
return self->klass->get_previous_point (self, point, result);
}
gboolean
gsk_contour_get_next_point (const GskContour *self,
GskRealPathPoint *point,
GskRealPathPoint *result)
{
return self->klass->get_next_point (self, point, result);
}
void
gsk_contour_get_point (const GskContour *self,
gpointer measure_data,

View File

@@ -98,6 +98,12 @@ void gsk_contour_get_start_point (const GskContou
GskRealPathPoint *result);
void gsk_contour_get_end_point (const GskContour *self,
GskRealPathPoint *result);
gboolean gsk_contour_get_previous_point (const GskContour *self,
GskRealPathPoint *point,
GskRealPathPoint *result);
gboolean gsk_contour_get_next_point (const GskContour *self,
GskRealPathPoint *point,
GskRealPathPoint *result);
float gsk_contour_get_distance (const GskContour *self,
GskRealPathPoint *point,
gpointer measure_data);

View File

@@ -1448,3 +1448,117 @@ gsk_path_builder_add_segment (GskPathBuilder *self,
contour = gsk_path_get_contour (path, e->contour);
gsk_contour_add_segment (contour, self, FALSE, NULL, e);
}
/**
* gsk_path_get_previous_point:
* @self: a `GskPath`
* @point: a point on @self
* @result: (out caller-allocates): Return location for the result
*
* Gets the previous 'significant' point on @self before @point.
*
* The 'significant' points of a path are typically the
* on-curve points that have been specified when the
* path was created.
*
* For example, in a path with 3 Bézier segments, the
* significant points are the start of the first segment,
* the start point of the second segment (which coincides
* with the end point of the first segment), the start
* point of the third segment, and the end point of the
* last segment.
*
* If @point is the start point of the path, there is no
* prior point, and this function returns `FALSE`.
*
* Returns: `TRUE` if @result has been set to a point
*/
gboolean
gsk_path_get_previous_point (GskPath *self,
const GskPathPoint *point,
GskPathPoint *result)
{
GskRealPathPoint *p = (GskRealPathPoint *) point;
GskRealPathPoint *res = (GskRealPathPoint *) result;
const GskContour *contour;
g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (self == p->path, FALSE);
contour = gsk_path_get_contour (self, p->contour);
if (gsk_contour_get_previous_point (contour, p, res))
{
res->path = self;
res->contour = p->contour;
return TRUE;
}
if (p->contour > 0)
{
contour = gsk_path_get_contour (self, p->contour - 1);
gsk_contour_get_end_point (contour, res);
res->path = self;
res->contour = p->contour - 1;
return TRUE;
}
return FALSE;
}
/**
* gsk_path_get_next_point:
* @self: a `GskPath`
* @point: a point on @self
* @result: (out caller-allocates): Return location for the result
*
* Gets the next 'significant' point on @self after @point.
*
* The 'significant' points of a path are typically the
* on-curve points that have been specified when the
* path was created.
*
* For example, in a path with 3 Bézier segments, the
* significant points are the start of the first segment,
* the start point of the second segment (which coincides
* with the end point of the first segment), the start
* point of the third segment, and the end point of the
* last segment.
*
* If @point is the end point of the path, there is no
* next point, and this function returns `FALSE`.
*
* Returns: `TRUE` if @result has been set to a point
*/
gboolean
gsk_path_get_next_point (GskPath *self,
const GskPathPoint *point,
GskPathPoint *result)
{
GskRealPathPoint *p = (GskRealPathPoint *) point;
GskRealPathPoint *res = (GskRealPathPoint *) result;
const GskContour *contour;
g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (self == p->path, FALSE);
contour = gsk_path_get_contour (self, p->contour);
if (gsk_contour_get_next_point (contour, p, res))
{
res->path = self;
res->contour = p->contour;
return TRUE;
}
if (p->contour < self->n_contours - 1)
{
contour = gsk_path_get_contour (self, p->contour + 1);
gsk_contour_get_start_point (contour, res);
res->path = self;
res->contour = p->contour + 1;
return TRUE;
}
return FALSE;
}

View File

@@ -116,6 +116,16 @@ gboolean gsk_path_get_closest_point (GskPath
float threshold,
GskPathPoint *result);
GDK_AVAILABLE_IN_4_14
gboolean gsk_path_get_previous_point (GskPath *self,
const GskPathPoint *point,
GskPathPoint *result);
GDK_AVAILABLE_IN_4_14
gboolean gsk_path_get_next_point (GskPath *self,
const GskPathPoint *point,
GskPathPoint *result);
GDK_AVAILABLE_IN_4_14
gboolean gsk_path_get_start_point (GskPath *self,
GskPathPoint *result);