summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--demos/gtk-demo/path_text.c2
-rw-r--r--docs/reference/gsk/gsk4-sections.txt1
-rw-r--r--gsk/gskpath.c93
-rw-r--r--gsk/gskpath.h18
-rw-r--r--gsk/gskpathprivate.h1
-rw-r--r--testsuite/gsk/path.c6
6 files changed, 110 insertions, 11 deletions
diff --git a/demos/gtk-demo/path_text.c b/demos/gtk-demo/path_text.c
index ab4791a032..cb006eb34d 100644
--- a/demos/gtk-demo/path_text.c
+++ b/demos/gtk-demo/path_text.c
@@ -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);
}
diff --git a/docs/reference/gsk/gsk4-sections.txt b/docs/reference/gsk/gsk4-sections.txt
index bb8c213869..8cbb69766d 100644
--- a/docs/reference/gsk/gsk4-sections.txt
+++ b/docs/reference/gsk/gsk4-sections.txt
@@ -332,6 +332,7 @@ gsk_path_is_empty
gsk_path_get_bounds
<SUBSECTION>
GskPathOperation
+GskPathForeachFlags
GskPathForeachFunc
gsk_path_foreach
<SUBSECTION Private>
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))
diff --git a/gsk/gskpath.h b/gsk/gskpath.h
index bb8ae9875f..328da7dfbb 100644
--- a/gsk/gskpath.h
+++ b/gsk/gskpath.h
@@ -30,6 +30,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
* @pts: The points of the operation
@@ -80,6 +97,7 @@ gboolean gsk_path_get_bounds (GskPath
GDK_AVAILABLE_IN_ALL
gboolean gsk_path_foreach (GskPath *path,
+ GskPathForeachFlags flags,
GskPathForeachFunc func,
gpointer user_data);
diff --git a/gsk/gskpathprivate.h b/gsk/gskpathprivate.h
index 6ea2c2c6d3..310fa38b45 100644
--- a/gsk/gskpathprivate.h
+++ b/gsk/gskpathprivate.h
@@ -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);
diff --git a/testsuite/gsk/path.c b/testsuite/gsk/path.c
index 8cef3bc632..1390fd4364 100644
--- a/testsuite/gsk/path.c
+++ b/testsuite/gsk/path.c
@@ -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]);