[gtk+/wip/otte/rendernode: 84/100] gsk: Add cross-fade node
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/otte/rendernode: 84/100] gsk: Add cross-fade node
- Date: Sun, 18 Dec 2016 06:35:45 +0000 (UTC)
commit afef79d68e7a2488bc9f4e0ce4a86c987f1c1399
Author: Benjamin Otte <otte redhat com>
Date: Sat Dec 17 07:44:10 2016 +0100
gsk: Add cross-fade node
And implement stack crossfades with it.
docs/reference/gsk/gsk4-sections.txt | 1 +
gsk/gskenums.h | 4 +-
gsk/gskrendernode.h | 5 +
gsk/gskrendernodeimpl.c | 136 ++++++++++++++++++++++++++++++++
gsk/gskrendernodeprivate.h | 4 +
gtk/gtkstack.c | 52 +++++++------
gtk/inspector/gtktreemodelrendernode.c | 9 ++
7 files changed, 186 insertions(+), 25 deletions(-)
---
diff --git a/docs/reference/gsk/gsk4-sections.txt b/docs/reference/gsk/gsk4-sections.txt
index 59e1a39..f5cc151 100644
--- a/docs/reference/gsk/gsk4-sections.txt
+++ b/docs/reference/gsk/gsk4-sections.txt
@@ -51,6 +51,7 @@ gsk_rounded_clip_node_new
gsk_rounded_clip_node_get_child
GskBlendMode
gsk_blend_node_new
+gsk_cross_fade_node_new
<SUBSECTION Standard>
GSK_IS_RENDER_NODE
GSK_RENDER_NODE
diff --git a/gsk/gskenums.h b/gsk/gskenums.h
index 4e0e0bf..1d46c92 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 7562fb9..14fa797 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 5ab0d22..ee3cb46 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 e4b9ee4..e945ee7 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__ */
diff --git a/gtk/gtkstack.c b/gtk/gtkstack.c
index d0656e3..8ef6db9 100644
--- a/gtk/gtkstack.c
+++ b/gtk/gtkstack.c
@@ -1925,37 +1925,41 @@ gtk_stack_snapshot_crossfade (GtkWidget *widget,
GtkStack *stack = GTK_STACK (widget);
GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
gdouble progress = gtk_progress_tracker_get_progress (&priv->tracker, FALSE);
- cairo_t *cr;
+ GskRenderNode *end_node, *node;
+ char *name;
- cr = gtk_snapshot_append_cairo_node (snapshot,
- &GRAPHENE_RECT_INIT(
- 0, 0,
- gtk_widget_get_allocated_width (widget),
- gtk_widget_get_allocated_height (widget)
- ),
- "GtkStackCrossfade");
-
- gtk_container_propagate_draw (GTK_CONTAINER (stack),
+ gtk_snapshot_push (snapshot, TRUE, "GtkStackCrossFadeEnd");
+ gtk_container_snapshot_child (GTK_CONTAINER (stack),
priv->visible_child->widget,
- cr);
-
- /* Multiply alpha by progress */
- cairo_set_source_rgba (cr, 1, 1, 1, progress);
- cairo_set_operator (cr, CAIRO_OPERATOR_DEST_IN);
- cairo_paint (cr);
- cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+ snapshot);
+ end_node = gtk_snapshot_pop (snapshot);
if (priv->last_visible_node)
{
- cairo_push_group (cr);
- cairo_translate (cr, priv->last_visible_surface_allocation.x, priv->last_visible_surface_allocation.y);
- gsk_render_node_draw (priv->last_visible_node, cr);
- cairo_pop_group_to_source (cr);
- cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
- cairo_paint_with_alpha (cr, MAX (1.0 - progress, 0));
+ graphene_matrix_t identity;
+ GskRenderNode *start_node;
+
+ graphene_matrix_init_identity (&identity);
+
+ gtk_snapshot_push_transform (snapshot, &identity, "CrossFadeStart");
+ gtk_snapshot_append_node (snapshot, priv->last_visible_node);
+ start_node = gtk_snapshot_pop (snapshot);
+ node = gsk_cross_fade_node_new (start_node, end_node, progress);
+ gsk_render_node_unref (start_node);
+ }
+ else
+ {
+ node = gsk_opacity_node_new (end_node, 1.0 - progress);
}
- cairo_destroy (cr);
+ name = g_strdup_printf ("CrossFade<%g>", progress);
+ gsk_render_node_set_name (node, name);
+ g_free (name);
+
+ gtk_snapshot_append_node (snapshot, node);
+
+ gsk_render_node_unref (node);
+ gsk_render_node_unref (end_node);
}
static void
diff --git a/gtk/inspector/gtktreemodelrendernode.c b/gtk/inspector/gtktreemodelrendernode.c
index 6ac5b32..fff0a06 100644
--- a/gtk/inspector/gtktreemodelrendernode.c
+++ b/gtk/inspector/gtktreemodelrendernode.c
@@ -555,6 +555,15 @@ append_node (GtkTreeModelRenderNode *nodemodel,
}
break;
+ case GSK_CROSS_FADE_NODE:
+ {
+ int elt_index = priv->nodes->len - 1;
+
+ append_node (nodemodel, gsk_cross_fade_node_get_start_child (node), elt_index);
+ append_node (nodemodel, gsk_cross_fade_node_get_end_child (node), elt_index);
+ }
+ break;
+
case GSK_CONTAINER_NODE:
{
gint elt_index;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]