path: Add flags to gsk_path_foreach()
This way we can default to the siplest possible foreach() output - like cairo_copy_path_flat() decomposing everything into lines - and add flags to get more and more fancy. This will be useful to have conics automatically decomposed for Cairo drawing or if we want to add more line types in the future.
This commit is contained in:
@@ -160,7 +160,7 @@ gtk_path_transform (GskPathMeasure *measure,
|
||||
else
|
||||
transform.scale = 1.0f;
|
||||
|
||||
gsk_path_foreach (path, gtk_path_transform_op, &transform);
|
||||
gsk_path_foreach (path, GSK_PATH_FOREACH_ALLOW_CURVES, gtk_path_transform_op, &transform);
|
||||
|
||||
return gsk_path_builder_free_to_path (transform.builder);
|
||||
}
|
||||
|
||||
@@ -2016,6 +2016,7 @@ gsk_path_to_cairo (GskPath *self,
|
||||
g_return_if_fail (cr != NULL);
|
||||
|
||||
gsk_path_foreach_with_tolerance (self,
|
||||
GSK_PATH_FOREACH_ALLOW_CURVES,
|
||||
cairo_get_tolerance (cr),
|
||||
gsk_path_to_cairo_add_op,
|
||||
cr);
|
||||
@@ -2109,6 +2110,8 @@ gsk_path_get_bounds (GskPath *self,
|
||||
/**
|
||||
* gsk_path_foreach:
|
||||
* @self: a #GskPath
|
||||
* @flags: flags to pass to the foreach function. See #GskPathForeachFlags for
|
||||
* details about flags.
|
||||
* @func: (scope call) (closure user_data): the function to call for operations
|
||||
* @user_data: (nullable): user data passed to @func
|
||||
*
|
||||
@@ -2118,24 +2121,98 @@ gsk_path_get_bounds (GskPath *self,
|
||||
* Returns: %FALSE if @func returned %FALSE, %TRUE otherwise.
|
||||
**/
|
||||
gboolean
|
||||
gsk_path_foreach (GskPath *self,
|
||||
GskPathForeachFunc func,
|
||||
gpointer user_data)
|
||||
gsk_path_foreach (GskPath *self,
|
||||
GskPathForeachFlags flags,
|
||||
GskPathForeachFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_return_val_if_fail (self != NULL, FALSE);
|
||||
g_return_val_if_fail (func, FALSE);
|
||||
|
||||
return gsk_path_foreach_with_tolerance (self, GSK_PATH_TOLERANCE_DEFAULT, func, user_data);
|
||||
return gsk_path_foreach_with_tolerance (self,
|
||||
flags,
|
||||
GSK_PATH_TOLERANCE_DEFAULT,
|
||||
func,
|
||||
user_data);
|
||||
}
|
||||
|
||||
typedef struct _GskPathForeachTrampoline GskPathForeachTrampoline;
|
||||
struct _GskPathForeachTrampoline
|
||||
{
|
||||
GskPathForeachFlags flags;
|
||||
double tolerance;
|
||||
GskPathForeachFunc func;
|
||||
gpointer user_data;
|
||||
gboolean retval;
|
||||
};
|
||||
|
||||
static void
|
||||
gsk_path_foreach_trampoline_add_point (const graphene_point_t *from,
|
||||
const graphene_point_t *to,
|
||||
float from_progress,
|
||||
float to_progress,
|
||||
gpointer data)
|
||||
{
|
||||
GskPathForeachTrampoline *trampoline = data;
|
||||
|
||||
if (!trampoline->retval)
|
||||
return;
|
||||
|
||||
trampoline->retval = trampoline->func (GSK_PATH_LINE,
|
||||
(graphene_point_t[2]) { *from, *to },
|
||||
2,
|
||||
trampoline->user_data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsk_path_foreach_trampoline (GskPathOperation op,
|
||||
const graphene_point_t *pts,
|
||||
gsize n_pts,
|
||||
gpointer data)
|
||||
{
|
||||
GskPathForeachTrampoline *trampoline = data;
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case GSK_PATH_MOVE:
|
||||
case GSK_PATH_CLOSE:
|
||||
case GSK_PATH_LINE:
|
||||
return trampoline->func (op, pts, n_pts, trampoline->user_data);
|
||||
|
||||
case GSK_PATH_CURVE:
|
||||
if (trampoline->flags & GSK_PATH_FOREACH_ALLOW_CURVES)
|
||||
return trampoline->func (op, pts, n_pts, trampoline->user_data);
|
||||
|
||||
gsk_spline_decompose_cubic (pts,
|
||||
trampoline->tolerance,
|
||||
gsk_path_foreach_trampoline_add_point,
|
||||
trampoline);
|
||||
return trampoline->retval;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gsk_path_foreach_with_tolerance (GskPath *self,
|
||||
double tolerance,
|
||||
GskPathForeachFunc func,
|
||||
gpointer user_data)
|
||||
gsk_path_foreach_with_tolerance (GskPath *self,
|
||||
GskPathForeachFlags flags,
|
||||
double tolerance,
|
||||
GskPathForeachFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
GskPathForeachTrampoline trampoline;
|
||||
gsize i;
|
||||
|
||||
/* If we need to massage the data, set up a trampoline here */
|
||||
if (flags != GSK_PATH_FOREACH_ALLOW_CURVES)
|
||||
{
|
||||
trampoline = (GskPathForeachTrampoline) { flags, tolerance, func, user_data, TRUE };
|
||||
func = gsk_path_foreach_trampoline;
|
||||
user_data = &trampoline;
|
||||
}
|
||||
|
||||
for (i = 0; i < self->n_contours; i++)
|
||||
{
|
||||
if (!gsk_contour_foreach (self->contours[i], tolerance, func, user_data))
|
||||
|
||||
@@ -29,6 +29,23 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* GskPathForeachFlags:
|
||||
* @GSK_PATH_FOREACH_ALLOW_CURVES: Allow emission of %GSK_PATH_CURVE
|
||||
* operations.
|
||||
*
|
||||
* Flags that can be passed to gsk_path_foreach() to enable additional
|
||||
* features.
|
||||
*
|
||||
* By default, gsk_path_foreach() will only emit a path with all operations
|
||||
* flattened to straight lines to allow for maximum compatibility. The only
|
||||
* operations emitted will be %GSK_PATH_MOVE, %GSK_PATH_LINE and %GSK_PATH_CLOSE.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
GSK_PATH_FOREACH_ALLOW_CURVES = (1 << 0)
|
||||
} GskPathForeachFlags;
|
||||
|
||||
/**
|
||||
* GskPathForeachFunc:
|
||||
* @op: The operation to perform
|
||||
@@ -80,6 +97,7 @@ gboolean gsk_path_get_bounds (GskPath
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gsk_path_foreach (GskPath *self,
|
||||
GskPathForeachFlags flags,
|
||||
GskPathForeachFunc func,
|
||||
gpointer user_data);
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ gsize gsk_path_get_n_contours (GskPath
|
||||
const GskContour * gsk_path_get_contour (GskPath *path,
|
||||
gsize i);
|
||||
gboolean gsk_path_foreach_with_tolerance (GskPath *self,
|
||||
GskPathForeachFlags flags,
|
||||
double tolerance,
|
||||
GskPathForeachFunc func,
|
||||
gpointer user_data);
|
||||
|
||||
@@ -412,7 +412,8 @@ collect_path (GskPath *path)
|
||||
{
|
||||
GArray *array = g_array_new (FALSE, FALSE, sizeof (PathOperation));
|
||||
|
||||
gsk_path_foreach (path, collect_path_operation_cb, array);
|
||||
/* Use -1 here because we want all the flags, even future additions */
|
||||
gsk_path_foreach (path, -1, collect_path_operation_cb, array);
|
||||
|
||||
return array;
|
||||
}
|
||||
@@ -1019,7 +1020,8 @@ test_in_fill_rotated (void)
|
||||
path = create_random_path (G_MAXUINT);
|
||||
builders[0] = gsk_path_builder_new ();
|
||||
builders[1] = gsk_path_builder_new ();
|
||||
gsk_path_foreach (path, rotate_path_cb, builders);
|
||||
/* Use -1 here because we want all the flags, even future additions */
|
||||
gsk_path_foreach (path, -1, rotate_path_cb, builders);
|
||||
gsk_path_unref (path);
|
||||
|
||||
path = gsk_path_builder_free_to_path (builders[0]);
|
||||
|
||||
Reference in New Issue
Block a user