summaryrefslogtreecommitdiff
path: root/gsk
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2016-12-17 07:44:10 +0100
committerBenjamin Otte <otte@redhat.com>2016-12-20 18:01:11 +0100
commit30438c6e8be4ca4a6142b4386f8596c6eb4068c8 (patch)
tree4b393400b5dfc46d3e13ffa6a6abbf41ee82e79f /gsk
parent3e4fd32b54a9df53749b339fff587bfc5aaafdc9 (diff)
downloadgtk+-30438c6e8be4ca4a6142b4386f8596c6eb4068c8.tar.gz
gsk: Add cross-fade node
And implement stack crossfades with it.
Diffstat (limited to 'gsk')
-rw-r--r--gsk/gskenums.h4
-rw-r--r--gsk/gskrendernode.h5
-rw-r--r--gsk/gskrendernodeimpl.c136
-rw-r--r--gsk/gskrendernodeprivate.h4
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__ */