summaryrefslogtreecommitdiff
path: root/gsk/gskpath.c
diff options
context:
space:
mode:
Diffstat (limited to 'gsk/gskpath.c')
-rw-r--r--gsk/gskpath.c93
1 files changed, 85 insertions, 8 deletions
diff --git a/gsk/gskpath.c b/gsk/gskpath.c
index 5dc8a09343..e9a724db28 100644
--- a/gsk/gskpath.c
+++ b/gsk/gskpath.c
@@ -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))