Skip to content

Commit

Permalink
snapshot: Add gtk_snapshot_push_blend()
Browse files Browse the repository at this point in the history
and use it for backgrounds.
  • Loading branch information
Benjamin Otte committed Jan 13, 2017
1 parent 9616df9 commit bc3ba68
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 56 deletions.
1 change: 1 addition & 0 deletions docs/reference/gtk/gtk4-sections.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
75 changes: 19 additions & 56 deletions gtk/gtkrenderbackground.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -639,71 +641,32 @@ 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))
{
GtkCssValue *blend_modes;
GskBlendMode blend_mode;
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);

blend_modes = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BACKGROUND_BLEND_MODE);
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));

gtk_snapshot_push (snapshot, TRUE, "BackgroundBlendGroup");
if (blend_mode != GSK_BLEND_MODE_DEFAULT)
gtk_snapshot_push_blend (snapshot, blend_mode, "Background<%u>Blend<%u>", idx, blend_mode);
}

gtk_theming_background_snapshot_color (&bg, snapshot, bg_color, background_image);
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));

for (idx = number_of_layers - 1; idx >= 0; idx--)
if (blend_mode == GSK_BLEND_MODE_DEFAULT)
{
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_theming_background_snapshot_layer (&bg, idx, snapshot);
}

gtk_snapshot_pop_and_append (snapshot);
}
else
{
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--)
else
{
gtk_snapshot_pop_and_append (snapshot);
gtk_theming_background_snapshot_layer (&bg, idx, snapshot);
gtk_snapshot_pop_and_append (snapshot);
}
}

Expand Down
91 changes: 91 additions & 0 deletions gtk/gtksnapshot.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
5 changes: 5 additions & 0 deletions gtk/gtksnapshot.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 4 additions & 0 deletions gtk/gtksnapshotprivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit bc3ba68

Please sign in to comment.