summaryrefslogtreecommitdiff
path: root/gtk/gtkcssshadowvalue.c
diff options
context:
space:
mode:
authorCosimo Cecchi <cosimoc@gnome.org>2012-04-17 15:43:58 -0400
committerBenjamin Otte <otte@redhat.com>2012-09-20 02:45:41 +0200
commitb609686133f2728fc6e4f950738f0fa4a1a11d70 (patch)
tree1a4f07c74a1b0cba6cc893438cd97953711872e0 /gtk/gtkcssshadowvalue.c
parenta239f2e8b028b714cd269c10c70e19683390b68f (diff)
downloadgtk+-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.c63
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,