mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-25 05:01:09 +00:00
gsk: Add GskShadowNode
... and make the icon rendering code use it. This requires moving even more shadow renering code into GSK, but so be it. At least the "shadows not implemented" warning is now gone!
This commit is contained in:
parent
071c9a8221
commit
2480e0d575
@ -50,6 +50,8 @@ gsk_clip_node_new
|
||||
gsk_clip_node_get_child
|
||||
gsk_rounded_clip_node_new
|
||||
gsk_rounded_clip_node_get_child
|
||||
GskShadow
|
||||
gsk_shadow_node_new
|
||||
GskBlendMode
|
||||
gsk_blend_node_new
|
||||
gsk_cross_fade_node_new
|
||||
|
@ -280,3 +280,121 @@ gsk_cairo_blur_compute_pixels (double radius)
|
||||
return floor (radius * GAUSSIAN_SCALE_FACTOR * 1.5 + 0.5);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
needs_blur (float radius)
|
||||
{
|
||||
/* The code doesn't actually do any blurring for radius 1, as it
|
||||
* ends up with box filter size 1 */
|
||||
if (radius <= 1.0)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const cairo_user_data_key_t original_cr_key;
|
||||
|
||||
cairo_t *
|
||||
gsk_cairo_blur_start_drawing (cairo_t *cr,
|
||||
float radius,
|
||||
GskBlurFlags blur_flags)
|
||||
{
|
||||
cairo_rectangle_int_t clip_rect;
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *blur_cr;
|
||||
gdouble clip_radius;
|
||||
gdouble x_scale, y_scale;
|
||||
gboolean blur_x = (blur_flags & GSK_BLUR_X) != 0;
|
||||
gboolean blur_y = (blur_flags & GSK_BLUR_Y) != 0;
|
||||
|
||||
if (!needs_blur (radius))
|
||||
return cr;
|
||||
|
||||
gdk_cairo_get_clip_rectangle (cr, &clip_rect);
|
||||
|
||||
clip_radius = gsk_cairo_blur_compute_pixels (radius);
|
||||
|
||||
x_scale = y_scale = 1;
|
||||
cairo_surface_get_device_scale (cairo_get_target (cr), &x_scale, &y_scale);
|
||||
|
||||
if (blur_flags & GSK_BLUR_REPEAT)
|
||||
{
|
||||
if (!blur_x)
|
||||
clip_rect.width = 1;
|
||||
if (!blur_y)
|
||||
clip_rect.height = 1;
|
||||
}
|
||||
|
||||
/* Create a larger surface to center the blur. */
|
||||
surface = cairo_surface_create_similar_image (cairo_get_target (cr),
|
||||
CAIRO_FORMAT_A8,
|
||||
x_scale * (clip_rect.width + (blur_x ? 2 * clip_radius : 0)),
|
||||
y_scale * (clip_rect.height + (blur_y ? 2 * clip_radius : 0)));
|
||||
cairo_surface_set_device_scale (surface, x_scale, y_scale);
|
||||
cairo_surface_set_device_offset (surface,
|
||||
x_scale * ((blur_x ? clip_radius : 0) - clip_rect.x),
|
||||
y_scale * ((blur_y ? clip_radius * y_scale : 0) - clip_rect.y));
|
||||
|
||||
blur_cr = cairo_create (surface);
|
||||
cairo_set_user_data (blur_cr, &original_cr_key, cairo_reference (cr), (cairo_destroy_func_t) cairo_destroy);
|
||||
|
||||
if (cairo_has_current_point (cr))
|
||||
{
|
||||
double x, y;
|
||||
|
||||
cairo_get_current_point (cr, &x, &y);
|
||||
cairo_move_to (blur_cr, x, y);
|
||||
}
|
||||
|
||||
return blur_cr;
|
||||
}
|
||||
|
||||
static void
|
||||
mask_surface_repeat (cairo_t *cr,
|
||||
cairo_surface_t *surface)
|
||||
{
|
||||
cairo_pattern_t *pattern;
|
||||
|
||||
pattern = cairo_pattern_create_for_surface (surface);
|
||||
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
|
||||
|
||||
cairo_mask (cr, pattern);
|
||||
|
||||
cairo_pattern_destroy (pattern);
|
||||
}
|
||||
|
||||
cairo_t *
|
||||
gsk_cairo_blur_finish_drawing (cairo_t *cr,
|
||||
float radius,
|
||||
const GdkRGBA *color,
|
||||
GskBlurFlags blur_flags)
|
||||
{
|
||||
cairo_t *original_cr;
|
||||
cairo_surface_t *surface;
|
||||
gdouble x_scale;
|
||||
|
||||
if (!needs_blur (radius))
|
||||
return cr;
|
||||
|
||||
original_cr = cairo_get_user_data (cr, &original_cr_key);
|
||||
|
||||
/* Blur the surface. */
|
||||
surface = cairo_get_target (cr);
|
||||
|
||||
x_scale = 1;
|
||||
cairo_surface_get_device_scale (cairo_get_target (cr), &x_scale, NULL);
|
||||
|
||||
gsk_cairo_blur_surface (surface, x_scale * radius, blur_flags);
|
||||
|
||||
gdk_cairo_set_source_rgba (original_cr, color);
|
||||
if (blur_flags & GSK_BLUR_REPEAT)
|
||||
mask_surface_repeat (original_cr, surface);
|
||||
else
|
||||
cairo_mask_surface (original_cr, surface, 0, 0);
|
||||
|
||||
cairo_destroy (cr);
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
return original_cr;
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
#ifndef _GSK_CAIRO_BLUR_H
|
||||
#define _GSK_CAIRO_BLUR_H
|
||||
|
||||
#include <glib.h>
|
||||
#include <gdk/gdk.h>
|
||||
#include <cairo.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@ -41,6 +41,14 @@ void gsk_cairo_blur_surface (cairo_surface_t *surface,
|
||||
GskBlurFlags flags);
|
||||
int gsk_cairo_blur_compute_pixels (double radius);
|
||||
|
||||
cairo_t * gsk_cairo_blur_start_drawing (cairo_t *cr,
|
||||
float radius,
|
||||
GskBlurFlags blur_flags);
|
||||
cairo_t * gsk_cairo_blur_finish_drawing (cairo_t *cr,
|
||||
float radius,
|
||||
const GdkRGBA *color,
|
||||
GskBlurFlags blur_flags);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _GSK_CAIRO_BLUR_H */
|
||||
|
@ -38,6 +38,7 @@
|
||||
* @GSK_OPACITY_NODE: A node that changes the opacity of its child
|
||||
* @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_SHADOW_NODE: A node that draws a shadow below its child
|
||||
* @GSK_BLEND_NODE: A node the blends two children together
|
||||
* @GSK_CROSS_FADE_NODE: A node the cross-fades between two children
|
||||
*
|
||||
@ -58,6 +59,7 @@ typedef enum {
|
||||
GSK_OPACITY_NODE,
|
||||
GSK_CLIP_NODE,
|
||||
GSK_ROUNDED_CLIP_NODE,
|
||||
GSK_SHADOW_NODE,
|
||||
GSK_BLEND_NODE,
|
||||
GSK_CROSS_FADE_NODE
|
||||
} GskRenderNodeType;
|
||||
|
@ -34,6 +34,7 @@ G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GskRenderNode GskRenderNode;
|
||||
typedef struct _GskColorStop GskColorStop;
|
||||
typedef struct _GskShadow GskShadow;
|
||||
|
||||
struct _GskColorStop
|
||||
{
|
||||
@ -41,6 +42,15 @@ struct _GskColorStop
|
||||
GdkRGBA color;
|
||||
};
|
||||
|
||||
struct _GskShadow
|
||||
{
|
||||
GdkRGBA color;
|
||||
float dx;
|
||||
float dy;
|
||||
float spread;
|
||||
float radius;
|
||||
};
|
||||
|
||||
GDK_AVAILABLE_IN_3_90
|
||||
GType gsk_render_node_get_type (void) G_GNUC_CONST;
|
||||
|
||||
@ -117,6 +127,11 @@ GskRenderNode * gsk_rounded_clip_node_new (GskRenderNode
|
||||
GDK_AVAILABLE_IN_3_90
|
||||
GskRenderNode * gsk_rounded_clip_node_get_child (GskRenderNode *node);
|
||||
|
||||
GDK_AVAILABLE_IN_3_90
|
||||
GskRenderNode * gsk_shadow_node_new (GskRenderNode *child,
|
||||
const GskShadow *shadows,
|
||||
gsize n_shadows);
|
||||
|
||||
GDK_AVAILABLE_IN_3_90
|
||||
GskRenderNode * gsk_blend_node_new (GskRenderNode *bottom,
|
||||
GskRenderNode *top,
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "gskrendernodeprivate.h"
|
||||
|
||||
#include "gskcairoblurprivate.h"
|
||||
#include "gskdebugprivate.h"
|
||||
#include "gskrendererprivate.h"
|
||||
#include "gskroundedrectprivate.h"
|
||||
@ -1410,6 +1411,175 @@ gsk_rounded_clip_node_peek_clip (GskRenderNode *node)
|
||||
return &self->clip;
|
||||
}
|
||||
|
||||
/*** GSK_SHADOW_NODE ***/
|
||||
|
||||
typedef struct _GskShadowNode GskShadowNode;
|
||||
|
||||
struct _GskShadowNode
|
||||
{
|
||||
GskRenderNode render_node;
|
||||
|
||||
GskRenderNode *child;
|
||||
|
||||
GskShadow *shadows;
|
||||
gsize n_shadows;
|
||||
};
|
||||
|
||||
static void
|
||||
gsk_shadow_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
GskShadowNode *self = (GskShadowNode *) node;
|
||||
|
||||
gsk_render_node_unref (self->child);
|
||||
|
||||
g_free (self->shadows);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_shadow_node_make_immutable (GskRenderNode *node)
|
||||
{
|
||||
GskShadowNode *self = (GskShadowNode *) node;
|
||||
|
||||
gsk_render_node_make_immutable (self->child);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_shadow_node_draw (GskRenderNode *node,
|
||||
cairo_t *cr)
|
||||
{
|
||||
GskShadowNode *self = (GskShadowNode *) node;
|
||||
cairo_pattern_t *pattern;
|
||||
gsize i;
|
||||
|
||||
cairo_push_group (cr);
|
||||
gsk_render_node_draw (self->child, cr);
|
||||
pattern = cairo_pop_group (cr);
|
||||
|
||||
for (i = 0; i < self->n_shadows; i++)
|
||||
{
|
||||
GskShadow *shadow = &self->shadows[i];
|
||||
|
||||
/* We don't need to draw invisible shadows */
|
||||
if (gdk_rgba_is_clear (&shadow->color))
|
||||
continue;
|
||||
|
||||
cairo_save (cr);
|
||||
gdk_cairo_set_source_rgba (cr, &shadow->color);
|
||||
cr = gsk_cairo_blur_start_drawing (cr, shadow->radius, GSK_BLUR_X | GSK_BLUR_Y);
|
||||
|
||||
cairo_translate (cr, shadow->dx, shadow->dy);
|
||||
cairo_mask (cr, pattern);
|
||||
|
||||
cr = gsk_cairo_blur_finish_drawing (cr, shadow->radius, &shadow->color, GSK_BLUR_X | GSK_BLUR_Y);
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
cairo_set_source (cr, pattern);
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_pattern_destroy (pattern);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_shadow_node_get_bounds (GskRenderNode *node,
|
||||
graphene_rect_t *bounds)
|
||||
{
|
||||
GskShadowNode *self = (GskShadowNode *) node;
|
||||
float top = 0, right = 0, bottom = 0, left = 0;
|
||||
gsize i;
|
||||
|
||||
gsk_render_node_get_bounds (self->child, bounds);
|
||||
|
||||
for (i = 0; i < self->n_shadows; i++)
|
||||
{
|
||||
float clip_radius = gsk_cairo_blur_compute_pixels (self->shadows[i].radius);
|
||||
top = MAX (top, clip_radius - self->shadows[i].dy);
|
||||
right = MAX (right, clip_radius + self->shadows[i].dx);
|
||||
bottom = MAX (bottom, clip_radius + self->shadows[i].dy);
|
||||
left = MAX (left, clip_radius - self->shadows[i].dx);
|
||||
}
|
||||
|
||||
bounds->origin.x -= left;
|
||||
bounds->origin.y -= top;
|
||||
bounds->size.width += left + right;
|
||||
bounds->size.height += top + bottom;
|
||||
}
|
||||
|
||||
static const GskRenderNodeClass GSK_SHADOW_NODE_CLASS = {
|
||||
GSK_SHADOW_NODE,
|
||||
sizeof (GskShadowNode),
|
||||
"GskShadowNode",
|
||||
gsk_shadow_node_finalize,
|
||||
gsk_shadow_node_make_immutable,
|
||||
gsk_shadow_node_draw,
|
||||
gsk_shadow_node_get_bounds
|
||||
};
|
||||
|
||||
/**
|
||||
* gsk_shadow_node_new:
|
||||
* @child: The node to draw
|
||||
* @shadows: (array length=n_shadows): The shadows to apply
|
||||
* @n_shadows: number of entries in the @shadows array
|
||||
*
|
||||
* Creates a #GskRenderNode that will draw a @child with the given
|
||||
* @shadows below it.
|
||||
*
|
||||
* Returns: A new #GskRenderNode
|
||||
*
|
||||
* Since: 3.90
|
||||
*/
|
||||
GskRenderNode *
|
||||
gsk_shadow_node_new (GskRenderNode *child,
|
||||
const GskShadow *shadows,
|
||||
gsize n_shadows)
|
||||
{
|
||||
GskShadowNode *self;
|
||||
|
||||
g_return_val_if_fail (GSK_IS_RENDER_NODE (child), NULL);
|
||||
g_return_val_if_fail (shadows != NULL, NULL);
|
||||
g_return_val_if_fail (n_shadows > 0, NULL);
|
||||
|
||||
self = (GskShadowNode *) gsk_render_node_new (&GSK_SHADOW_NODE_CLASS);
|
||||
|
||||
self->child = gsk_render_node_ref (child);
|
||||
self->shadows = g_memdup (shadows, n_shadows * sizeof (GskShadow));
|
||||
self->n_shadows = n_shadows;
|
||||
|
||||
return &self->render_node;
|
||||
}
|
||||
|
||||
GskRenderNode *
|
||||
gsk_shadow_node_get_child (GskRenderNode *node)
|
||||
{
|
||||
GskShadowNode *self = (GskShadowNode *) node;
|
||||
|
||||
g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_SHADOW_NODE), NULL);
|
||||
|
||||
return self->child;
|
||||
}
|
||||
|
||||
const GskShadow *
|
||||
gsk_shadow_node_peek_shadow (GskRenderNode *node,
|
||||
gsize i)
|
||||
{
|
||||
GskShadowNode *self = (GskShadowNode *) node;
|
||||
|
||||
g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_SHADOW_NODE), NULL);
|
||||
g_return_val_if_fail (i < self->n_shadows, NULL);
|
||||
|
||||
return &self->shadows[i];
|
||||
}
|
||||
|
||||
gsize
|
||||
gsk_shadow_node_get_n_shadows (GskRenderNode *node)
|
||||
{
|
||||
GskShadowNode *self = (GskShadowNode *) node;
|
||||
|
||||
g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_SHADOW_NODE), 0);
|
||||
|
||||
return self->n_shadows;
|
||||
}
|
||||
|
||||
/*** GSK_BLEND_NODE ***/
|
||||
|
||||
typedef struct _GskBlendNode GskBlendNode;
|
||||
|
@ -62,6 +62,10 @@ const graphene_rect_t * gsk_clip_node_peek_clip (GskRenderNode *node);
|
||||
|
||||
const GskRoundedRect * gsk_rounded_clip_node_peek_clip (GskRenderNode *node);
|
||||
|
||||
GskRenderNode * gsk_shadow_node_get_child (GskRenderNode *node);
|
||||
const GskShadow * gsk_shadow_node_peek_shadow (GskRenderNode *node, gsize i);
|
||||
gsize gsk_shadow_node_get_n_shadows (GskRenderNode *node);
|
||||
|
||||
void gsk_transform_node_get_transform (GskRenderNode *node, graphene_matrix_t *transform);
|
||||
|
||||
GskRenderNode * gsk_blend_node_get_bottom_child (GskRenderNode *node);
|
||||
|
@ -268,6 +268,25 @@ _gtk_css_shadows_value_is_none (const GtkCssValue *shadows)
|
||||
return shadows->len == 0;
|
||||
}
|
||||
|
||||
GskShadow *
|
||||
gtk_css_shadows_value_get_shadows (const GtkCssValue *shadows,
|
||||
gsize *n_shadows)
|
||||
{
|
||||
GskShadow *result;
|
||||
guint i;
|
||||
|
||||
result = g_new (GskShadow, shadows->len);
|
||||
|
||||
for (i = 0; i < shadows->len; i++)
|
||||
{
|
||||
gtk_css_shadow_value_get_shadow (shadows->values[i], &result[i]);
|
||||
}
|
||||
|
||||
*n_shadows = shadows->len;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_css_shadows_value_paint_layout (const GtkCssValue *shadows,
|
||||
cairo_t *cr,
|
||||
|
@ -36,6 +36,9 @@ GtkCssValue * _gtk_css_shadows_value_parse (GtkCssParser
|
||||
|
||||
gboolean _gtk_css_shadows_value_is_none (const GtkCssValue *shadows);
|
||||
|
||||
GskShadow * gtk_css_shadows_value_get_shadows (const GtkCssValue *shadows,
|
||||
gsize *n_shadows);
|
||||
|
||||
void _gtk_css_shadows_value_paint_layout (const GtkCssValue *shadows,
|
||||
cairo_t *cr,
|
||||
PangoLayout *layout);
|
||||
|
@ -625,6 +625,17 @@ gtk_css_shadow_value_get_extents (const GtkCssValue *shadow,
|
||||
border->left = MAX (0, ceil (clip_radius + spread - hoffset));
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_shadow_value_get_shadow (const GtkCssValue *value,
|
||||
GskShadow *shadow)
|
||||
{
|
||||
shadow->color = *_gtk_css_rgba_value_get_rgba (value->color);
|
||||
shadow->dx = _gtk_css_number_value_get (value->hoffset, 0);
|
||||
shadow->dy = _gtk_css_number_value_get (value->voffset, 0);
|
||||
shadow->spread = _gtk_css_number_value_get (value->spread, 0);
|
||||
shadow->radius = _gtk_css_number_value_get (value->radius, 0);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
has_empty_clip (cairo_t *cr)
|
||||
{
|
||||
|
@ -39,6 +39,8 @@ gboolean _gtk_css_shadow_value_get_inset (const GtkCssValue
|
||||
|
||||
void gtk_css_shadow_value_get_extents (const GtkCssValue *shadow,
|
||||
GtkBorder *border);
|
||||
void gtk_css_shadow_value_get_shadow (const GtkCssValue *value,
|
||||
GskShadow *shadow);
|
||||
|
||||
void _gtk_css_shadow_value_paint_layout (const GtkCssValue *shadow,
|
||||
cairo_t *cr,
|
||||
|
@ -95,10 +95,11 @@ gtk_css_style_snapshot_icon (GtkCssStyle *style,
|
||||
double height,
|
||||
GtkCssImageBuiltinType builtin_type)
|
||||
{
|
||||
const GtkCssValue *shadows, *transform;
|
||||
static gboolean shadow_warning;
|
||||
const GtkCssValue *shadows_value, *transform;
|
||||
graphene_matrix_t transform_matrix;
|
||||
GtkCssImage *image;
|
||||
GskShadow *shadows;
|
||||
gsize n_shadows;
|
||||
|
||||
g_return_if_fail (GTK_IS_CSS_STYLE (style));
|
||||
g_return_if_fail (snapshot != NULL);
|
||||
@ -107,17 +108,15 @@ gtk_css_style_snapshot_icon (GtkCssStyle *style,
|
||||
if (image == NULL)
|
||||
return;
|
||||
|
||||
shadows = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_SHADOW);
|
||||
shadows_value = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_SHADOW);
|
||||
transform = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_TRANSFORM);
|
||||
|
||||
if (!gtk_css_transform_value_get_matrix (transform, &transform_matrix))
|
||||
return;
|
||||
|
||||
if (!_gtk_css_shadows_value_is_none (shadows) && !shadow_warning)
|
||||
{
|
||||
g_warning ("Painting shadows not implemented for textures yet.");
|
||||
shadow_warning = TRUE;
|
||||
}
|
||||
shadows = gtk_css_shadows_value_get_shadows (shadows_value, &n_shadows);
|
||||
if (shadows)
|
||||
gtk_snapshot_push_shadow (snapshot, shadows, n_shadows, "IconShadow<%zu>", n_shadows);
|
||||
|
||||
if (graphene_matrix_is_identity (&transform_matrix))
|
||||
{
|
||||
@ -139,6 +138,12 @@ gtk_css_style_snapshot_icon (GtkCssStyle *style,
|
||||
|
||||
gtk_snapshot_pop_and_append (snapshot);
|
||||
}
|
||||
|
||||
if (shadows)
|
||||
{
|
||||
gtk_snapshot_pop_and_append (snapshot);
|
||||
g_free (shadows);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -261,18 +266,19 @@ gtk_css_style_snapshot_icon_texture (GtkCssStyle *style,
|
||||
GskTexture *texture,
|
||||
double texture_scale)
|
||||
{
|
||||
const GtkCssValue *shadows, *transform;
|
||||
const GtkCssValue *shadows_value, *transform;
|
||||
graphene_matrix_t transform_matrix;
|
||||
graphene_rect_t bounds;
|
||||
double width, height;
|
||||
static gboolean shadow_warning;
|
||||
GskShadow *shadows;
|
||||
gsize n_shadows;
|
||||
|
||||
g_return_if_fail (GTK_IS_CSS_STYLE (style));
|
||||
g_return_if_fail (snapshot != NULL);
|
||||
g_return_if_fail (GSK_IS_TEXTURE (texture));
|
||||
g_return_if_fail (texture_scale > 0);
|
||||
|
||||
shadows = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_SHADOW);
|
||||
shadows_value = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_SHADOW);
|
||||
transform = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_TRANSFORM);
|
||||
width = gsk_texture_get_width (texture) / texture_scale;
|
||||
height = gsk_texture_get_height (texture) / texture_scale;
|
||||
@ -280,11 +286,9 @@ gtk_css_style_snapshot_icon_texture (GtkCssStyle *style,
|
||||
if (!gtk_css_transform_value_get_matrix (transform, &transform_matrix))
|
||||
return;
|
||||
|
||||
if (!_gtk_css_shadows_value_is_none (shadows) && !shadow_warning)
|
||||
{
|
||||
g_warning ("Painting shadows not implemented for textures yet.");
|
||||
shadow_warning = TRUE;
|
||||
}
|
||||
shadows = gtk_css_shadows_value_get_shadows (shadows_value, &n_shadows);
|
||||
if (shadows)
|
||||
gtk_snapshot_push_shadow (snapshot, shadows, n_shadows, "IconShadow<%zu>", n_shadows);
|
||||
|
||||
if (graphene_matrix_is_identity (&transform_matrix))
|
||||
{
|
||||
@ -311,4 +315,10 @@ gtk_css_style_snapshot_icon_texture (GtkCssStyle *style,
|
||||
|
||||
gtk_snapshot_pop_and_append (snapshot);
|
||||
}
|
||||
|
||||
if (shadows)
|
||||
{
|
||||
gtk_snapshot_pop_and_append (snapshot);
|
||||
g_free (shadows);
|
||||
}
|
||||
}
|
||||
|
@ -472,6 +472,67 @@ gtk_snapshot_push_rounded_clip (GtkSnapshot *snapshot,
|
||||
cairo_region_destroy (clip);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
gsize n_shadows;
|
||||
GskShadow shadows[0];
|
||||
} Shadow;
|
||||
|
||||
static GskRenderNode *
|
||||
gtk_snapshot_collect_shadow (GskRenderNode **nodes,
|
||||
guint n_nodes,
|
||||
const char *name,
|
||||
gpointer data)
|
||||
{
|
||||
Shadow *shadow = data;
|
||||
GskRenderNode *node, *shadow_node;
|
||||
|
||||
node = gtk_snapshot_collect_default (nodes, n_nodes, name, NULL);
|
||||
if (node == NULL)
|
||||
return NULL;
|
||||
|
||||
shadow_node = gsk_shadow_node_new (node, shadow->shadows, shadow->n_shadows);
|
||||
gsk_render_node_set_name (shadow_node, name);
|
||||
|
||||
gsk_render_node_unref (node);
|
||||
g_free (shadow);
|
||||
|
||||
return shadow_node;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_snapshot_push_shadow (GtkSnapshot *snapshot,
|
||||
const GskShadow *shadow,
|
||||
gsize n_shadows,
|
||||
const char *name,
|
||||
...)
|
||||
{
|
||||
Shadow *real_shadow;
|
||||
char *str;
|
||||
|
||||
real_shadow = g_malloc (sizeof (GskShadow) * n_shadows + sizeof (GskShadow));
|
||||
real_shadow->n_shadows = n_shadows;
|
||||
memcpy (real_shadow->shadows, shadow, sizeof (GskShadow) * n_shadows);
|
||||
|
||||
if (name)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start (args, name);
|
||||
str = g_strdup_vprintf (name, args);
|
||||
va_end (args);
|
||||
}
|
||||
else
|
||||
str = NULL;
|
||||
|
||||
snapshot->state = gtk_snapshot_state_new (snapshot->state,
|
||||
str,
|
||||
snapshot->state->clip_region,
|
||||
snapshot->state->translate_x,
|
||||
snapshot->state->translate_y,
|
||||
gtk_snapshot_collect_shadow,
|
||||
real_shadow);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_snapshot_pop:
|
||||
* @snapshot: a #GtkSnapshot
|
||||
|
@ -62,6 +62,12 @@ void gtk_snapshot_push_rounded_clip (GtkSnapshot
|
||||
const char *name,
|
||||
...) G_GNUC_PRINTF (3, 4);
|
||||
GDK_AVAILABLE_IN_3_90
|
||||
void gtk_snapshot_push_shadow (GtkSnapshot *snapshot,
|
||||
const GskShadow *shadow,
|
||||
gsize n_shadows,
|
||||
const char *name,
|
||||
...) G_GNUC_PRINTF (4, 5);
|
||||
GDK_AVAILABLE_IN_3_90
|
||||
GskRenderNode * gtk_snapshot_pop (GtkSnapshot *snapshot) G_GNUC_WARN_UNUSED_RESULT;
|
||||
GDK_AVAILABLE_IN_3_90
|
||||
void gtk_snapshot_pop_and_append (GtkSnapshot *snapshot);
|
||||
|
@ -547,6 +547,10 @@ append_node (GtkTreeModelRenderNode *nodemodel,
|
||||
append_node (nodemodel, gsk_rounded_clip_node_get_child (node), priv->nodes->len - 1);
|
||||
break;
|
||||
|
||||
case GSK_SHADOW_NODE:
|
||||
append_node (nodemodel, gsk_shadow_node_get_child (node), priv->nodes->len - 1);
|
||||
break;
|
||||
|
||||
case GSK_BLEND_NODE:
|
||||
{
|
||||
int elt_index = priv->nodes->len - 1;
|
||||
|
@ -159,6 +159,8 @@ node_type_name (GskRenderNodeType type)
|
||||
return "Clip";
|
||||
case GSK_ROUNDED_CLIP_NODE:
|
||||
return "Rounded Clip";
|
||||
case GSK_SHADOW_NODE:
|
||||
return "Shadow";
|
||||
case GSK_BLEND_NODE:
|
||||
return "Blend";
|
||||
case GSK_CROSS_FADE_NODE:
|
||||
|
Loading…
Reference in New Issue
Block a user