forked from AuroraMiddleware/gtk
gsk: Add cross-fade node
And implement stack crossfades with it.
This commit is contained in:
parent
3e4fd32b54
commit
30438c6e8b
@ -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
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -117,6 +117,11 @@ GskRenderNode * gsk_blend_node_new (GskRenderNode
|
||||
GskRenderNode *top,
|
||||
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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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__ */
|
||||
|
@ -1913,37 +1913,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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user