path: Add gsk_path_foreach()
This commit is contained in:
@@ -240,6 +240,30 @@ typedef enum {
|
||||
GSK_LINE_JOIN_BEVEL
|
||||
} GskLineJoin;
|
||||
|
||||
/**
|
||||
* GskPathOperation:
|
||||
* @GSK_PATH_MOVE: A move-to operation, with 1 point describing the
|
||||
* target point.
|
||||
* @GSK_PATH_LINE: A line-to operation, with 2 points describing the
|
||||
* start and end point of a straight line.
|
||||
* @GSK_PATH_CLOSE: A close operation ending the current contour with
|
||||
* a line back to the starting point. Two points describe the start
|
||||
* and end of the line.
|
||||
* @GSK_PATH_CURVE: A curve-to operation describing a cubic bezier curve
|
||||
* with 4 points describing the start point, the two control points
|
||||
* and the end point of the curve.
|
||||
*
|
||||
* Path operations can be used to approximate a #GskPath.
|
||||
*
|
||||
* More values may be added in the future.
|
||||
**/
|
||||
typedef enum {
|
||||
GSK_PATH_MOVE,
|
||||
GSK_PATH_CLOSE,
|
||||
GSK_PATH_LINE,
|
||||
GSK_PATH_CURVE,
|
||||
} GskPathOperation;
|
||||
|
||||
/**
|
||||
* GskSerializationError:
|
||||
* @GSK_SERIALIZATION_UNSUPPORTED_FORMAT: The format can not be identified
|
||||
|
||||
102
gsk/gskpath.c
102
gsk/gskpath.c
@@ -62,6 +62,10 @@ struct _GskContourClass
|
||||
cairo_t *cr);
|
||||
gboolean (* get_bounds) (const GskContour *contour,
|
||||
graphene_rect_t *bounds);
|
||||
gboolean (* foreach) (const GskContour *contour,
|
||||
float tolerance,
|
||||
GskPathForeachFunc func,
|
||||
gpointer user_data);
|
||||
gpointer (* init_measure) (const GskContour *contour,
|
||||
float *out_length);
|
||||
void (* free_measure) (const GskContour *contour,
|
||||
@@ -181,6 +185,29 @@ gsk_rect_contour_get_bounds (const GskContour *contour,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsk_rect_contour_foreach (const GskContour *contour,
|
||||
float tolerance,
|
||||
GskPathForeachFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
const GskRectContour *self = (const GskRectContour *) contour;
|
||||
|
||||
graphene_point_t pts[] = {
|
||||
GRAPHENE_POINT_INIT (self->x, self->y),
|
||||
GRAPHENE_POINT_INIT (self->x + self->width, self->y),
|
||||
GRAPHENE_POINT_INIT (self->x + self->width, self->y + self->height),
|
||||
GRAPHENE_POINT_INIT (self->x, self->y + self->height),
|
||||
GRAPHENE_POINT_INIT (self->x, self->y)
|
||||
};
|
||||
|
||||
return func (GSK_PATH_MOVE, &pts[0], 1, user_data)
|
||||
&& func (GSK_PATH_LINE, &pts[0], 2, user_data)
|
||||
&& func (GSK_PATH_LINE, &pts[1], 2, user_data)
|
||||
&& func (GSK_PATH_LINE, &pts[2], 2, user_data)
|
||||
&& func (GSK_PATH_CLOSE, &pts[3], 2, user_data);
|
||||
}
|
||||
|
||||
static gpointer
|
||||
gsk_rect_contour_init_measure (const GskContour *contour,
|
||||
float *out_length)
|
||||
@@ -282,6 +309,7 @@ static const GskContourClass GSK_RECT_CONTOUR_CLASS =
|
||||
gsk_rect_contour_print,
|
||||
gsk_rect_contour_to_cairo,
|
||||
gsk_rect_contour_get_bounds,
|
||||
gsk_rect_contour_foreach,
|
||||
gsk_rect_contour_init_measure,
|
||||
gsk_rect_contour_free_measure,
|
||||
gsk_rect_contour_copy,
|
||||
@@ -306,14 +334,6 @@ gsk_rect_contour_init (GskContour *contour,
|
||||
|
||||
/* STANDARD CONTOUR */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GSK_PATH_MOVE,
|
||||
GSK_PATH_CLOSE,
|
||||
GSK_PATH_LINE,
|
||||
GSK_PATH_CURVE,
|
||||
} GskPathOperation;
|
||||
|
||||
typedef struct _GskStandardOperation GskStandardOperation;
|
||||
|
||||
struct _GskStandardOperation {
|
||||
@@ -351,6 +371,30 @@ gsk_standard_contour_get_size (const GskContour *contour)
|
||||
return gsk_standard_contour_compute_size (self->n_ops, self->n_points);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsk_standard_contour_foreach (const GskContour *contour,
|
||||
float tolerance,
|
||||
GskPathForeachFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
const GskStandardContour *self = (const GskStandardContour *) contour;
|
||||
gsize i;
|
||||
const gsize n_points[] = {
|
||||
[GSK_PATH_MOVE] = 1,
|
||||
[GSK_PATH_CLOSE] = 2,
|
||||
[GSK_PATH_LINE] = 2,
|
||||
[GSK_PATH_CURVE] = 4
|
||||
};
|
||||
|
||||
for (i = 0; i < self->n_ops; i ++)
|
||||
{
|
||||
if (!func (self->ops[i].op, &self->points[self->ops[i].point], n_points[self->ops[i].op], user_data))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GskPathFlags
|
||||
gsk_standard_contour_get_flags (const GskContour *contour)
|
||||
{
|
||||
@@ -655,6 +699,7 @@ static const GskContourClass GSK_STANDARD_CONTOUR_CLASS =
|
||||
gsk_standard_contour_print,
|
||||
gsk_standard_contour_to_cairo,
|
||||
gsk_standard_contour_get_bounds,
|
||||
gsk_standard_contour_foreach,
|
||||
gsk_standard_contour_init_measure,
|
||||
gsk_standard_contour_free_measure,
|
||||
gsk_standard_contour_copy,
|
||||
@@ -710,6 +755,15 @@ gsk_contour_dup (const GskContour *src)
|
||||
return copy;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsk_contour_foreach (const GskContour *contour,
|
||||
float tolerance,
|
||||
GskPathForeachFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
return contour->klass->foreach (contour, tolerance, func, user_data);
|
||||
}
|
||||
|
||||
gpointer
|
||||
gsk_contour_init_measure (GskPath *path,
|
||||
gsize i,
|
||||
@@ -1008,6 +1062,38 @@ gsk_path_get_bounds (GskPath *self,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_path_foreach:
|
||||
* @self: a #GskPath
|
||||
* @func: (scope call) (closure user_data): the function to call for operations
|
||||
* @user_data: (nullable): user data passed to @func
|
||||
*
|
||||
* Calls @func for every operation of the path. Note that this only approximates
|
||||
* @self, because paths can contain optimizations for various specialized contours.
|
||||
*
|
||||
* Returns: %FALSE if @func returned %FALSE, %TRUE otherwise.
|
||||
**/
|
||||
gboolean
|
||||
gsk_path_foreach (GskPath *self,
|
||||
GskPathForeachFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
gsize i;
|
||||
|
||||
g_return_val_if_fail (self != NULL, FALSE);
|
||||
g_return_val_if_fail (func, FALSE);
|
||||
|
||||
for (i = 0; i < self->n_contours; i++)
|
||||
{
|
||||
if (!gsk_contour_foreach (self->contours[i], GSK_PATH_TOLERANCE_DEFAULT, func, user_data))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* BUILDER */
|
||||
|
||||
/**
|
||||
* GskPathBuilder:
|
||||
*
|
||||
|
||||
@@ -29,6 +29,24 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* GskPathForeachFunc:
|
||||
* @op: The operation to perform
|
||||
* @pts: The points of the operation
|
||||
* @n_pts: The number of points
|
||||
* @user_data: The user data provided with the function
|
||||
*
|
||||
* Prototype of the callback to iterate throught the operations of
|
||||
* a path.
|
||||
*
|
||||
* Returns: %TRUE to continue evaluating the path, %FALSE to
|
||||
* immediately abort and not call the function again.
|
||||
*/
|
||||
typedef gboolean (* GskPathForeachFunc) (GskPathOperation op,
|
||||
const graphene_point_t *pts,
|
||||
gsize n_pts,
|
||||
gpointer user_data);
|
||||
|
||||
#define GSK_TYPE_PATH (gsk_path_get_type ())
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
@@ -56,6 +74,11 @@ GDK_AVAILABLE_IN_ALL
|
||||
gboolean gsk_path_get_bounds (GskPath *self,
|
||||
graphene_rect_t *bounds);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gsk_path_foreach (GskPath *self,
|
||||
GskPathForeachFunc func,
|
||||
gpointer user_data);
|
||||
|
||||
#define GSK_TYPE_PATH_BUILDER (gsk_path_builder_get_type ())
|
||||
|
||||
typedef struct _GskPathBuilder GskPathBuilder;
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* Same as Cairo, so looks like a good value. ¯\_(ツ)_/¯ */
|
||||
#define GSK_PATH_TOLERANCE_DEFAULT (0.1)
|
||||
|
||||
gsize gsk_path_get_n_contours (GskPath *path);
|
||||
|
||||
gpointer gsk_contour_init_measure (GskPath *path,
|
||||
|
||||
Reference in New Issue
Block a user