diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt index d628cbefb7..5ce0f550b5 100644 --- a/docs/reference/gtk/gtk4-sections.txt +++ b/docs/reference/gtk/gtk4-sections.txt @@ -4305,6 +4305,7 @@ gtk_snapshot_push_repeat gtk_snapshot_push_clip gtk_snapshot_push_rounded_clip gtk_snapshot_push_fill +gtk_snapshot_push_stroke gtk_snapshot_push_cross_fade gtk_snapshot_push_blend gtk_snapshot_push_blur diff --git a/gtk/gtksnapshot.c b/gtk/gtksnapshot.c index 476ae0019d..2d5cd6311f 100644 --- a/gtk/gtksnapshot.c +++ b/gtk/gtksnapshot.c @@ -31,6 +31,7 @@ #include "gsktransformprivate.h" #include "gsk/gskrendernodeprivate.h" +#include "gsk/gskstrokeprivate.h" #include "gtk/gskpango.h" @@ -112,6 +113,10 @@ struct _GtkSnapshotState { GskPath *path; GskFillRule fill_rule; } fill; + struct { + GskPath *path; + GskStroke stroke; + } stroke; struct { gsize n_shadows; GskShadow *shadows; @@ -1171,6 +1176,70 @@ gtk_snapshot_push_fill (GtkSnapshot *snapshot, state->data.fill.fill_rule = fill_rule; } +static GskRenderNode * +gtk_snapshot_collect_stroke (GtkSnapshot *snapshot, + GtkSnapshotState *state, + GskRenderNode **nodes, + guint n_nodes) +{ + GskRenderNode *node, *stroke_node; + + node = gtk_snapshot_collect_default (snapshot, state, nodes, n_nodes); + if (node == NULL) + return NULL; + + stroke_node = gsk_stroke_node_new (node, + state->data.stroke.path, + &state->data.stroke.stroke); + + if (stroke_node->bounds.size.width == 0 || + stroke_node->bounds.size.height == 0) + { + gsk_render_node_unref (node); + gsk_render_node_unref (stroke_node); + return NULL; + } + + gsk_render_node_unref (node); + + return stroke_node; +} + +static void +gtk_snapshot_clear_stroke (GtkSnapshotState *state) +{ + gsk_path_unref (state->data.stroke.path); + gsk_stroke_clear (&state->data.stroke.stroke); +} + +/** + * gtk_snapshot_push_stroke: + * @snapshot: a #GtkSnapshot + * @path: The path to stroke + * @stroke: The stroke attributes + * + * Strokes the given @path with the attributes given by @stroke and the + * image being recorded until the next call to gtk_snapshot_pop(). + */ +void +gtk_snapshot_push_stroke (GtkSnapshot *snapshot, + GskPath *path, + const GskStroke *stroke) +{ + GtkSnapshotState *state; + + /* FIXME: Is it worth calling ensure_affine() and transforming the path here? */ + gtk_snapshot_ensure_identity (snapshot); + + state = gtk_snapshot_push_state (snapshot, + gtk_snapshot_get_current_state (snapshot)->transform, + gtk_snapshot_collect_stroke, + gtk_snapshot_clear_stroke); + + state->data.stroke.path = gsk_path_ref (path); + gsk_stroke_init_copy (&state->data.stroke.stroke, stroke); +} + static GskRenderNode * gtk_snapshot_collect_shadow (GtkSnapshot *snapshot, GtkSnapshotState *state, diff --git a/gtk/gtksnapshot.h b/gtk/gtksnapshot.h index d0077ca9a1..7f509aae04 100644 --- a/gtk/gtksnapshot.h +++ b/gtk/gtksnapshot.h @@ -93,6 +93,10 @@ void gtk_snapshot_push_fill (GtkSnapshot GskPath *path, GskFillRule fill_rule); GDK_AVAILABLE_IN_ALL +void gtk_snapshot_push_stroke (GtkSnapshot *snapshot, + GskPath *path, + const GskStroke *stroke); +GDK_AVAILABLE_IN_ALL void gtk_snapshot_push_shadow (GtkSnapshot *snapshot, const GskShadow *shadow, gsize n_shadows);