diff options
author | Cosimo Cecchi <cosimoc@gnome.org> | 2012-04-17 15:43:58 -0400 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2012-09-20 02:45:41 +0200 |
commit | b609686133f2728fc6e4f950738f0fa4a1a11d70 (patch) | |
tree | 1a4f07c74a1b0cba6cc893438cd97953711872e0 /gtk/gtkcssshadowvalue.c | |
parent | a239f2e8b028b714cd269c10c70e19683390b68f (diff) | |
download | gtk+-b609686133f2728fc6e4f950738f0fa4a1a11d70.tar.gz |
shadow: add code to render blurred shadows
Split out the blurred shadow rendering in three steps:
- creation of a surface of the appropriate size - we use the clip
rectangle as a good measurement for the size, since we won't render
out of it anyway
- painting the unblurred shape on the surface - this is responsibility
of the single shadow implementations
- blur the surface and compose the result back on the original cairo_t
This means we can share code between the implementations for the first
and third steps; it also makes the code independent of the rendered
size, so we can avoid passing down a cairo_rectangle_t with e.g. the
icon coordinates.
Diffstat (limited to 'gtk/gtkcssshadowvalue.c')
-rw-r--r-- | gtk/gtkcssshadowvalue.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/gtk/gtkcssshadowvalue.c b/gtk/gtkcssshadowvalue.c index ed311a17ef..bbc91bb1dd 100644 --- a/gtk/gtkcssshadowvalue.c +++ b/gtk/gtkcssshadowvalue.c @@ -21,6 +21,7 @@ #include "gtkcssshadowvalueprivate.h" +#include "gtkcairoblurprivate.h" #include "gtkcssnumbervalueprivate.h" #include "gtkcssrgbavalueprivate.h" #include "gtkstylecontextprivate.h" @@ -302,6 +303,68 @@ fail: return NULL; } +static const cairo_user_data_key_t shadow_key; + +static cairo_t * +gtk_css_shadow_value_start_drawing (const GtkCssValue *shadow, + cairo_t *cr) +{ + cairo_rectangle_int_t clip_rect; + cairo_surface_t *surface; + cairo_t *blur_cr; + gdouble radius; + + radius = _gtk_css_number_value_get (shadow->radius, 0); + if (radius == 0.0) + return cr; + + gdk_cairo_get_clip_rectangle (cr, &clip_rect); + + /* Create a larger surface to center the blur. */ + surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, + clip_rect.width + 2 * radius, + clip_rect.height + 2 * radius); + cairo_surface_set_device_offset (surface, radius - clip_rect.x, radius - clip_rect.y); + blur_cr = cairo_create (surface); + cairo_set_user_data (blur_cr, &shadow_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 cairo_t * +gtk_css_shadow_value_finish_drawing (const GtkCssValue *shadow, + cairo_t *cr) +{ + gdouble radius; + cairo_t *original_cr; + cairo_surface_t *surface; + + radius = _gtk_css_number_value_get (shadow->radius, 0); + if (radius == 0.0) + return cr; + + surface = cairo_get_target (cr); + original_cr = cairo_get_user_data (cr, &shadow_key); + + /* Blur the surface. */ + _gtk_cairo_blur_surface (surface, radius); + + cairo_set_source_surface (original_cr, surface, 0, 0); + cairo_paint (original_cr); + + cairo_destroy (cr); + + return original_cr; +} + void _gtk_css_shadow_value_paint_layout (const GtkCssValue *shadow, cairo_t *cr, |