diff --git a/docs/reference/gsk/gsk4-sections.txt b/docs/reference/gsk/gsk4-sections.txt index 486e31d9d0..57b8657634 100644 --- a/docs/reference/gsk/gsk4-sections.txt +++ b/docs/reference/gsk/gsk4-sections.txt @@ -45,6 +45,8 @@ gsk_transform_node_new gsk_transform_node_get_child gsk_opacity_node_new gsk_opacity_node_get_child +gsk_clip_node_new +gsk_clip_node_get_child GSK_IS_RENDER_NODE GSK_RENDER_NODE diff --git a/gsk/gskenums.h b/gsk/gskenums.h index caba77f6ab..7b37715ee6 100644 --- a/gsk/gskenums.h +++ b/gsk/gskenums.h @@ -32,6 +32,7 @@ * @GSK_TRANSFORM_NODE: A node that renders its child after applying a * matrix transform * @GSK_OPACITY_NODE: A node that changes the opacity of its child + * @GSK_CLIP_NODE: A node that clips its child to a rectangular area * * The type of a node determines what the node is rendering. * @@ -44,7 +45,8 @@ typedef enum { GSK_COLOR_NODE, GSK_TEXTURE_NODE, GSK_TRANSFORM_NODE, - GSK_OPACITY_NODE + GSK_OPACITY_NODE, + GSK_CLIP_NODE } GskRenderNodeType; /** diff --git a/gsk/gskrendernode.h b/gsk/gskrendernode.h index 3be25035b1..cdd52b7cb0 100644 --- a/gsk/gskrendernode.h +++ b/gsk/gskrendernode.h @@ -79,6 +79,12 @@ GskRenderNode * gsk_opacity_node_new (GskRenderNode GDK_AVAILABLE_IN_3_90 GskRenderNode * gsk_opacity_node_get_child (GskRenderNode *node); +GDK_AVAILABLE_IN_3_90 +GskRenderNode * gsk_clip_node_new (GskRenderNode *child, + const graphene_rect_t *clip); +GDK_AVAILABLE_IN_3_90 +GskRenderNode * gsk_clip_node_get_child (GskRenderNode *node); + GDK_AVAILABLE_IN_3_90 void gsk_render_node_set_blend_mode (GskRenderNode *node, GskBlendMode blend_mode); diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c index 764b702df8..9797f23c9d 100644 --- a/gsk/gskrendernodeimpl.c +++ b/gsk/gskrendernodeimpl.c @@ -819,3 +819,128 @@ gsk_opacity_node_get_opacity (GskRenderNode *node) return self->opacity; } +/*** GSK_CLIP_NODE ***/ + +typedef struct _GskClipNode GskClipNode; + +struct _GskClipNode +{ + GskRenderNode render_node; + + GskRenderNode *child; + graphene_rect_t clip; +}; + +static void +gsk_clip_node_finalize (GskRenderNode *node) +{ + GskClipNode *self = (GskClipNode *) node; + + gsk_render_node_unref (self->child); +} + +static void +gsk_clip_node_make_immutable (GskRenderNode *node) +{ + GskClipNode *self = (GskClipNode *) node; + + gsk_render_node_make_immutable (self->child); +} + +static void +gsk_clip_node_draw (GskRenderNode *node, + cairo_t *cr) +{ + GskClipNode *self = (GskClipNode *) node; + + cairo_save (cr); + + cairo_rectangle (cr, + self->clip.origin.x, self->clip.origin.y, + self->clip.size.width, self->clip.size.height); + cairo_clip (cr); + + gsk_render_node_draw (self->child, cr); + + cairo_restore (cr); +} + +static void +gsk_clip_node_get_bounds (GskRenderNode *node, + graphene_rect_t *bounds) +{ + GskClipNode *self = (GskClipNode *) node; + graphene_rect_t child_bounds; + + gsk_render_node_get_bounds (self->child, &child_bounds); + + graphene_rect_intersection (&self->clip, &child_bounds, bounds); +} + +static const GskRenderNodeClass GSK_CLIP_NODE_CLASS = { + GSK_CLIP_NODE, + sizeof (GskClipNode), + "GskClipNode", + gsk_clip_node_finalize, + gsk_clip_node_make_immutable, + gsk_clip_node_draw, + gsk_clip_node_get_bounds +}; + +/** + * gsk_clip_node_new: + * @child: The node to draw + * @clip: The clip to apply + * + * Creates a #GskRenderNode that will clip the @child to the area + * given by @clip. + * + * Returns: A new #GskRenderNode + * + * Since: 3.90 + */ +GskRenderNode * +gsk_clip_node_new (GskRenderNode *child, + const graphene_rect_t *clip) +{ + GskClipNode *self; + + g_return_val_if_fail (GSK_IS_RENDER_NODE (child), NULL); + g_return_val_if_fail (clip != NULL, NULL); + + self = (GskClipNode *) gsk_render_node_new (&GSK_CLIP_NODE_CLASS); + + self->child = gsk_render_node_ref (child); + graphene_rect_normalize_r (clip, &self->clip); + + return &self->render_node; +} + +/** + * gsk_clip_node_get_child: + * @node: a clip @GskRenderNode + * + * Gets the child node that is getting clipped by the given @node. + * + * Returns: (transfer none): The child that is getting clipped + **/ +GskRenderNode * +gsk_clip_node_get_child (GskRenderNode *node) +{ + GskClipNode *self = (GskClipNode *) node; + + g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_CLIP_NODE), NULL); + + return self->child; +} + +const graphene_rect_t * +gsk_clip_node_peek_clip (GskRenderNode *node) +{ + GskClipNode *self = (GskClipNode *) node; + + g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_CLIP_NODE), NULL); + + return &self->clip; +} + diff --git a/gsk/gskrendernodeprivate.h b/gsk/gskrendernodeprivate.h index 3ad5c43658..1bb06394cf 100644 --- a/gsk/gskrendernodeprivate.h +++ b/gsk/gskrendernodeprivate.h @@ -60,6 +60,8 @@ GskTexture *gsk_texture_node_get_texture (GskRenderNode *node); const GdkRGBA *gsk_color_node_peek_color (GskRenderNode *node); +const graphene_rect_t * gsk_clip_node_peek_clip (GskRenderNode *node); + void gsk_transform_node_get_transform (GskRenderNode *node, graphene_matrix_t *transform); GskBlendMode gsk_render_node_get_blend_mode (GskRenderNode *node); diff --git a/gtk/inspector/gtktreemodelrendernode.c b/gtk/inspector/gtktreemodelrendernode.c index b25ae64633..c44c4c7e0e 100644 --- a/gtk/inspector/gtktreemodelrendernode.c +++ b/gtk/inspector/gtktreemodelrendernode.c @@ -534,6 +534,10 @@ append_node (GtkTreeModelRenderNode *nodemodel, append_node (nodemodel, gsk_opacity_node_get_child (node), priv->nodes->len - 1); break; + case GSK_CLIP_NODE: + append_node (nodemodel, gsk_clip_node_get_child (node), priv->nodes->len - 1); + break; + case GSK_CONTAINER_NODE: { gint elt_index;