diff options
-rw-r--r-- | demos/gtk-demo/path_text.c | 2 | ||||
-rw-r--r-- | docs/reference/gsk/gsk4-sections.txt | 1 | ||||
-rw-r--r-- | gsk/gskpath.c | 93 | ||||
-rw-r--r-- | gsk/gskpath.h | 18 | ||||
-rw-r--r-- | gsk/gskpathprivate.h | 1 | ||||
-rw-r--r-- | testsuite/gsk/path.c | 6 |
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]); |