diff options
author | Benjamin Otte <otte@redhat.com> | 2016-12-17 07:44:10 +0100 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2016-12-20 18:01:11 +0100 |
commit | 30438c6e8be4ca4a6142b4386f8596c6eb4068c8 (patch) | |
tree | 4b393400b5dfc46d3e13ffa6a6abbf41ee82e79f /gsk | |
parent | 3e4fd32b54a9df53749b339fff587bfc5aaafdc9 (diff) | |
download | gtk+-30438c6e8be4ca4a6142b4386f8596c6eb4068c8.tar.gz |
gsk: Add cross-fade node
And implement stack crossfades with it.
Diffstat (limited to 'gsk')
-rw-r--r-- | gsk/gskenums.h | 4 | ||||
-rw-r--r-- | gsk/gskrendernode.h | 5 | ||||
-rw-r--r-- | gsk/gskrendernodeimpl.c | 136 | ||||
-rw-r--r-- | gsk/gskrendernodeprivate.h | 4 |
4 files changed, 148 insertions, 1 deletions
diff --git a/gsk/gskenums.h b/gsk/gskenums.h index 4e0e0bf35d..1d46c9230e 100644 --- a/gsk/gskenums.h +++ b/gsk/gskenums.h @@ -38,6 +38,7 @@ * @GSK_CLIP_NODE: A node that clips its child to a rectangular area * @GSK_ROUNDED_CLIP_NODE: A node that clips its child to a rounded rectangle * @GSK_BLEND_NODE: A node the blends two children together + * @GSK_CROSS_FADE_NODE: A node the cross-fades between two children * * The type of a node determines what the node is rendering. * @@ -55,7 +56,8 @@ typedef enum { GSK_OPACITY_NODE, GSK_CLIP_NODE, GSK_ROUNDED_CLIP_NODE, - GSK_BLEND_NODE + GSK_BLEND_NODE, + GSK_CROSS_FADE_NODE } GskRenderNodeType; /** diff --git a/gsk/gskrendernode.h b/gsk/gskrendernode.h index 7562fb92ef..14fa797db9 100644 --- a/gsk/gskrendernode.h +++ b/gsk/gskrendernode.h @@ -118,6 +118,11 @@ GskRenderNode * gsk_blend_node_new (GskRenderNode GskBlendMode blend_mode); GDK_AVAILABLE_IN_3_90 +GskRenderNode * gsk_cross_fade_node_new (GskRenderNode *start, + GskRenderNode *end, + double progress); + +GDK_AVAILABLE_IN_3_90 void gsk_render_node_set_scaling_filter (GskRenderNode *node, GskScalingFilter min_filter, GskScalingFilter mag_filter); diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c index 5ab0d22beb..ee3cb46015 100644 --- a/gsk/gskrendernodeimpl.c +++ b/gsk/gskrendernodeimpl.c @@ -1402,3 +1402,139 @@ gsk_blend_node_get_blend_mode (GskRenderNode *node) return self->blend_mode; } +/*** GSK_CROSS_FADE_NODE ***/ + +typedef struct _GskCrossFadeNode GskCrossFadeNode; + +struct _GskCrossFadeNode +{ + GskRenderNode render_node; + + GskRenderNode *start; + GskRenderNode *end; + double progress; +}; + +static void +gsk_cross_fade_node_finalize (GskRenderNode *node) +{ + GskCrossFadeNode *self = (GskCrossFadeNode *) node; + + gsk_render_node_unref (self->start); + gsk_render_node_unref (self->end); +} + +static void +gsk_cross_fade_node_make_immutable (GskRenderNode *node) +{ + GskCrossFadeNode *self = (GskCrossFadeNode *) node; + + gsk_render_node_make_immutable (self->start); + gsk_render_node_make_immutable (self->end); +} + +static void +gsk_cross_fade_node_draw (GskRenderNode *node, + cairo_t *cr) +{ + GskCrossFadeNode *self = (GskCrossFadeNode *) node; + + cairo_push_group (cr); + gsk_render_node_draw (self->start, cr); + + cairo_push_group (cr); + gsk_render_node_draw (self->end, cr); + + cairo_pop_group_to_source (cr); + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_paint_with_alpha (cr, self->progress); + + cairo_pop_group_to_source (cr); /* resets operator */ + cairo_paint (cr); +} + +static void +gsk_cross_fade_node_get_bounds (GskRenderNode *node, + graphene_rect_t *bounds) +{ + GskCrossFadeNode *self = (GskCrossFadeNode *) node; + graphene_rect_t start_bounds, end_bounds; + + gsk_render_node_get_bounds (self->start, &start_bounds); + gsk_render_node_get_bounds (self->end, &end_bounds); + + graphene_rect_union (&start_bounds, &end_bounds, bounds); +} + +static const GskRenderNodeClass GSK_CROSS_FADE_NODE_CLASS = { + GSK_CROSS_FADE_NODE, + sizeof (GskCrossFadeNode), + "GskCrossFadeNode", + gsk_cross_fade_node_finalize, + gsk_cross_fade_node_make_immutable, + gsk_cross_fade_node_draw, + gsk_cross_fade_node_get_bounds +}; + +/** + * gsk_cross_fade_node_new: + * @start: The start node to be drawn + * @end: The node to be cross_fadeed onto the @start node + * @progress: How far the fade has progressed from start to end. The value will + * be clamped to the range [0 ... 1] + * + * Creates a #GskRenderNode that will do a cross-fade between @start and @end. + * + * Returns: A new #GskRenderNode + * + * Since: 3.90 + */ +GskRenderNode * +gsk_cross_fade_node_new (GskRenderNode *start, + GskRenderNode *end, + double progress) +{ + GskCrossFadeNode *self; + + g_return_val_if_fail (GSK_IS_RENDER_NODE (start), NULL); + g_return_val_if_fail (GSK_IS_RENDER_NODE (end), NULL); + + self = (GskCrossFadeNode *) gsk_render_node_new (&GSK_CROSS_FADE_NODE_CLASS); + + self->start = gsk_render_node_ref (start); + self->end = gsk_render_node_ref (end); + self->progress = CLAMP (progress, 0.0, 1.0); + + return &self->render_node; +} + +GskRenderNode * +gsk_cross_fade_node_get_start_child (GskRenderNode *node) +{ + GskCrossFadeNode *self = (GskCrossFadeNode *) node; + + g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_CROSS_FADE_NODE), NULL); + + return self->start; +} + +GskRenderNode * +gsk_cross_fade_node_get_end_child (GskRenderNode *node) +{ + GskCrossFadeNode *self = (GskCrossFadeNode *) node; + + g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_CROSS_FADE_NODE), NULL); + + return self->end; +} + +double +gsk_cross_fade_node_get_progress (GskRenderNode *node) +{ + GskCrossFadeNode *self = (GskCrossFadeNode *) node; + + g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_CROSS_FADE_NODE), 0.0); + + return self->progress; +} + diff --git a/gsk/gskrendernodeprivate.h b/gsk/gskrendernodeprivate.h index e4b9ee4209..e945ee7b2c 100644 --- a/gsk/gskrendernodeprivate.h +++ b/gsk/gskrendernodeprivate.h @@ -64,6 +64,10 @@ GskRenderNode * gsk_blend_node_get_bottom_child (GskRenderNode *node); GskRenderNode * gsk_blend_node_get_top_child (GskRenderNode *node); GskBlendMode gsk_blend_node_get_blend_node (GskRenderNode *node); +GskRenderNode * gsk_cross_fade_node_get_start_child (GskRenderNode *node); +GskRenderNode * gsk_cross_fade_node_get_end_child (GskRenderNode *node); +double gsk_cross_fade_node_get_progress (GskRenderNode *node); + G_END_DECLS #endif /* __GSK_RENDER_NODE_PRIVATE_H__ */ |