forked from AuroraMiddleware/gtk
snapshot: Add gtk_snapshot_push_blend()
and use it for backgrounds.
This commit is contained in:
parent
9616df9292
commit
bc3ba68641
@ -4459,6 +4459,7 @@ gtk_snapshot_push_repeat
|
||||
gtk_snapshot_push_clip
|
||||
gtk_snapshot_push_rounded_clip
|
||||
gtk_snapshot_push_cross_fade
|
||||
gtk_snapshot_push_blend
|
||||
gtk_snapshot_pop
|
||||
gtk_snapshot_pop_and_append
|
||||
gtk_snapshot_set_transform
|
||||
|
@ -619,6 +619,8 @@ gtk_css_style_snapshot_background (GtkCssStyle *style,
|
||||
gint idx;
|
||||
GtkCssValue *background_image;
|
||||
GtkCssValue *box_shadow;
|
||||
GtkCssValue *blend_modes;
|
||||
GskBlendMode blend_mode;
|
||||
const GdkRGBA *bg_color;
|
||||
gint number_of_layers;
|
||||
|
||||
@ -639,72 +641,33 @@ gtk_css_style_snapshot_background (GtkCssStyle *style,
|
||||
snapshot,
|
||||
&bg.boxes[GTK_CSS_AREA_BORDER_BOX]);
|
||||
|
||||
/*
|
||||
* When we have a blend mode set for the background, we must blend on a transparent
|
||||
* background. GSK can't do that yet.
|
||||
*/
|
||||
if (_gtk_theming_background_needs_push_group (style))
|
||||
blend_modes = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BACKGROUND_BLEND_MODE);
|
||||
number_of_layers = _gtk_css_array_value_get_n_values (background_image);
|
||||
|
||||
for (idx = number_of_layers - 1; idx >= 0; idx--)
|
||||
{
|
||||
GtkCssValue *blend_modes;
|
||||
GskBlendMode blend_mode;
|
||||
blend_mode = _gtk_css_blend_mode_value_get (_gtk_css_array_value_get_nth (blend_modes, idx));
|
||||
|
||||
blend_modes = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BACKGROUND_BLEND_MODE);
|
||||
|
||||
gtk_snapshot_push (snapshot, TRUE, "BackgroundBlendGroup");
|
||||
|
||||
gtk_theming_background_snapshot_color (&bg, snapshot, bg_color, background_image);
|
||||
|
||||
number_of_layers = _gtk_css_array_value_get_n_values (background_image);
|
||||
|
||||
for (idx = number_of_layers - 1; idx >= 0; idx--)
|
||||
{
|
||||
blend_mode = _gtk_css_blend_mode_value_get (_gtk_css_array_value_get_nth (blend_modes, idx));
|
||||
|
||||
if (blend_mode == GSK_BLEND_MODE_DEFAULT)
|
||||
{
|
||||
gtk_theming_background_snapshot_layer (&bg, idx, snapshot);
|
||||
}
|
||||
else
|
||||
{
|
||||
GskRenderNode *bottom, *top, *blend;
|
||||
|
||||
bottom = gtk_snapshot_pop (snapshot);
|
||||
|
||||
gtk_snapshot_push (snapshot, TRUE, "BackgroundBlendGroup<Mode%u>", blend_mode);
|
||||
gtk_theming_background_snapshot_layer (&bg, idx, snapshot);
|
||||
top = gtk_snapshot_pop (snapshot);
|
||||
|
||||
/* XXX: Is this necessary? Do we need a NULL node? */
|
||||
if (top == NULL)
|
||||
top = gsk_container_node_new (NULL, 0);
|
||||
if (bottom == NULL)
|
||||
bottom = gsk_container_node_new (NULL, 0);
|
||||
|
||||
blend = gsk_blend_node_new (bottom, top, blend_mode);
|
||||
if (snapshot->record_names)
|
||||
gsk_render_node_set_name (blend, "BackgroundBlend");
|
||||
|
||||
gtk_snapshot_push (snapshot, TRUE, "BackgroundBlendGroup");
|
||||
gtk_snapshot_append_node (snapshot, blend);
|
||||
|
||||
gsk_render_node_unref (blend);
|
||||
gsk_render_node_unref (top);
|
||||
gsk_render_node_unref (bottom);
|
||||
}
|
||||
}
|
||||
|
||||
gtk_snapshot_pop_and_append (snapshot);
|
||||
if (blend_mode != GSK_BLEND_MODE_DEFAULT)
|
||||
gtk_snapshot_push_blend (snapshot, blend_mode, "Background<%u>Blend<%u>", idx, blend_mode);
|
||||
}
|
||||
else
|
||||
|
||||
gtk_theming_background_snapshot_color (&bg, snapshot, bg_color, background_image);
|
||||
|
||||
for (idx = number_of_layers - 1; idx >= 0; idx--)
|
||||
{
|
||||
gtk_theming_background_snapshot_color (&bg, snapshot, bg_color, background_image);
|
||||
blend_mode = _gtk_css_blend_mode_value_get (_gtk_css_array_value_get_nth (blend_modes, idx));
|
||||
|
||||
number_of_layers = _gtk_css_array_value_get_n_values (background_image);
|
||||
|
||||
for (idx = number_of_layers - 1; idx >= 0; idx--)
|
||||
if (blend_mode == GSK_BLEND_MODE_DEFAULT)
|
||||
{
|
||||
gtk_theming_background_snapshot_layer (&bg, idx, snapshot);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_snapshot_pop_and_append (snapshot);
|
||||
gtk_theming_background_snapshot_layer (&bg, idx, snapshot);
|
||||
gtk_snapshot_pop_and_append (snapshot);
|
||||
}
|
||||
}
|
||||
|
||||
gtk_css_shadows_value_snapshot_inset (box_shadow,
|
||||
|
@ -675,6 +675,97 @@ gtk_snapshot_push_shadow (GtkSnapshot *snapshot,
|
||||
snapshot->state = state;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
gtk_snapshot_collect_blend_top (GtkSnapshotState *state,
|
||||
GskRenderNode **nodes,
|
||||
guint n_nodes,
|
||||
const char *name)
|
||||
{
|
||||
GskRenderNode *bottom_node, *top_node, *blend_node;
|
||||
|
||||
top_node = gtk_snapshot_collect_default (state, nodes, n_nodes, name);
|
||||
bottom_node = state->data.blend.bottom_node;
|
||||
|
||||
/* XXX: Is this necessary? Do we need a NULL node? */
|
||||
if (top_node == NULL)
|
||||
top_node = gsk_container_node_new (NULL, 0);
|
||||
if (bottom_node == NULL)
|
||||
bottom_node = gsk_container_node_new (NULL, 0);
|
||||
|
||||
blend_node = gsk_blend_node_new (bottom_node, top_node, state->data.blend.blend_mode);
|
||||
gsk_render_node_set_name (blend_node, name);
|
||||
|
||||
gsk_render_node_unref (top_node);
|
||||
gsk_render_node_unref (bottom_node);
|
||||
|
||||
return blend_node;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
gtk_snapshot_collect_blend_bottom (GtkSnapshotState *state,
|
||||
GskRenderNode **nodes,
|
||||
guint n_nodes,
|
||||
const char *name)
|
||||
{
|
||||
state->parent->data.blend.bottom_node = gtk_snapshot_collect_default (state, nodes, n_nodes, name);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_snapshot_push_blend:
|
||||
* @snapshot: a #GtkSnapshot
|
||||
* @blend_mode: blend mode to use
|
||||
* @name: printf format string for name of the pushed node
|
||||
* @...: printf-style arguments for the @name string
|
||||
*
|
||||
* Blends together 2 images with the given blend mode.
|
||||
*
|
||||
* Until the first call to gtk_snapshot_pop(), the bottom image for the
|
||||
* blend operation will be recorded. After that call, the top image to
|
||||
* be blended will be recorded until the second call to gtk_snapshot_pop().
|
||||
*
|
||||
* Calling this function requires 2 subsequent calls to gtk_snapshot_pop().
|
||||
**/
|
||||
void
|
||||
gtk_snapshot_push_blend (GtkSnapshot *snapshot,
|
||||
GskBlendMode blend_mode,
|
||||
const char *name,
|
||||
...)
|
||||
{
|
||||
GtkSnapshotState *state;
|
||||
char *str;
|
||||
|
||||
if (name && snapshot->record_names)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start (args, name);
|
||||
str = g_strdup_vprintf (name, args);
|
||||
va_end (args);
|
||||
}
|
||||
else
|
||||
str = NULL;
|
||||
|
||||
state = gtk_snapshot_state_new (snapshot->state,
|
||||
str,
|
||||
snapshot->state->clip_region,
|
||||
snapshot->state->translate_x,
|
||||
snapshot->state->translate_y,
|
||||
gtk_snapshot_collect_blend_top);
|
||||
state->data.blend.blend_mode = blend_mode;
|
||||
state->data.blend.bottom_node = NULL;
|
||||
|
||||
state = gtk_snapshot_state_new (state,
|
||||
str,
|
||||
state->clip_region,
|
||||
state->translate_x,
|
||||
state->translate_y,
|
||||
gtk_snapshot_collect_blend_bottom);
|
||||
|
||||
snapshot->state = state;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
gtk_snapshot_collect_cross_fade_end (GtkSnapshotState *state,
|
||||
GskRenderNode **nodes,
|
||||
|
@ -80,6 +80,11 @@ void gtk_snapshot_push_shadow (GtkSnapshot
|
||||
const char *name,
|
||||
...) G_GNUC_PRINTF (4, 5);
|
||||
GDK_AVAILABLE_IN_3_90
|
||||
void gtk_snapshot_push_blend (GtkSnapshot *snapshot,
|
||||
GskBlendMode blend_mode,
|
||||
const char *name,
|
||||
...) G_GNUC_PRINTF (3, 4);
|
||||
GDK_AVAILABLE_IN_3_90
|
||||
void gtk_snapshot_push_cross_fade (GtkSnapshot *snapshot,
|
||||
double progress,
|
||||
const char *name,
|
||||
|
@ -67,6 +67,10 @@ struct _GtkSnapshotState {
|
||||
GskShadow *shadows;
|
||||
GskShadow a_shadow; /* Used if n_shadows == 1 */
|
||||
} shadow;
|
||||
struct {
|
||||
GskBlendMode blend_mode;
|
||||
GskRenderNode *bottom_node;
|
||||
} blend;
|
||||
struct {
|
||||
double progress;
|
||||
GskRenderNode *start_node;
|
||||
|
Loading…
Reference in New Issue
Block a user