diff --git a/gsk/gskcontour.c b/gsk/gskcontour.c index 54ce65c7dc..5539b4caa4 100644 --- a/gsk/gskcontour.c +++ b/gsk/gskcontour.c @@ -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, diff --git a/gsk/gskcontourprivate.h b/gsk/gskcontourprivate.h index 2f274782b1..62f31bffac 100644 --- a/gsk/gskcontourprivate.h +++ b/gsk/gskcontourprivate.h @@ -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); diff --git a/gsk/gskpath.c b/gsk/gskpath.c index f0a42d41e1..186f743c83 100644 --- a/gsk/gskpath.c +++ b/gsk/gskpath.c @@ -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; +} diff --git a/gsk/gskpath.h b/gsk/gskpath.h index 7bab7b0777..006f08f89c 100644 --- a/gsk/gskpath.h +++ b/gsk/gskpath.h @@ -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);