[gtk+] blur: Use recording surface for capturing things to blur
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] blur: Use recording surface for capturing things to blur
- Date: Thu, 20 Sep 2012 00:47:42 +0000 (UTC)
commit f2cb8f12705ab3a36767df3430f8868ed7b29536
Author: Benjamin Otte <otte redhat com>
Date: Thu Sep 20 02:39:35 2012 +0200
blur: Use recording surface for capturing things to blur
This gets around clipping issues quite nicely and provides us with a
(mostly theoretical) performance boost.
gtk/gtkcssshadowvalue.c | 45 +++++++++++++++++++++++++++++++++------------
1 files changed, 33 insertions(+), 12 deletions(-)
---
diff --git a/gtk/gtkcssshadowvalue.c b/gtk/gtkcssshadowvalue.c
index 56ebe3a..7d4acbc 100644
--- a/gtk/gtkcssshadowvalue.c
+++ b/gtk/gtkcssshadowvalue.c
@@ -21,6 +21,8 @@
#include "gtkcssshadowvalueprivate.h"
+#include <math.h>
+
#include "gtkcairoblurprivate.h"
#include "gtkcssnumbervalueprivate.h"
#include "gtkcssrgbavalueprivate.h"
@@ -309,7 +311,7 @@ static cairo_t *
gtk_css_shadow_value_start_drawing (const GtkCssValue *shadow,
cairo_t *cr)
{
- cairo_rectangle_int_t clip_rect;
+ cairo_rectangle_t clip;
cairo_surface_t *surface;
cairo_t *blur_cr;
gdouble radius;
@@ -318,13 +320,16 @@ gtk_css_shadow_value_start_drawing (const GtkCssValue *shadow,
if (radius == 0.0)
return cr;
- gdk_cairo_get_clip_rectangle (cr, &clip_rect);
+ radius = ceil (radius);
+ cairo_clip_extents (cr, &clip.x, &clip.y, &clip.width, &clip.height);
+ clip.x -= radius;
+ clip.y -= radius;
+ clip.width += 2 * radius;
+ clip.height += 2 * radius;
/* 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);
+ surface = cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, &clip);
+ cairo_surface_set_device_offset (surface, - clip.x, - clip.y);
blur_cr = cairo_create (surface);
cairo_set_user_data (blur_cr, &shadow_key, cairo_reference (cr), (cairo_destroy_func_t) cairo_destroy);
@@ -344,23 +349,39 @@ gtk_css_shadow_value_finish_drawing (const GtkCssValue *shadow,
cairo_t *cr)
{
gdouble radius;
- cairo_t *original_cr;
- cairo_surface_t *surface;
+ cairo_t *original_cr, *image_cr;
+ cairo_surface_t *recording_surface, *image_surface;
+ cairo_rectangle_t ink;
radius = _gtk_css_number_value_get (shadow->radius, 0);
if (radius == 0.0)
return cr;
- surface = cairo_get_target (cr);
+ recording_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_recording_surface_ink_extents (recording_surface, &ink.x, &ink.y, &ink.width, &ink.height);
+ ink.width = ceil (ink.width + ink.x - floor (ink.x)) + 2 * ceil (radius);
+ ink.height = ceil (ink.height + ink.y - floor (ink.y)) + 2 * ceil (radius);
+ ink.x = floor (ink.x) + ceil (radius);
+ ink.y = floor (ink.y) + ceil (radius);
+
+ image_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, ink.width, ink.height);
+ cairo_surface_set_device_offset (image_surface, - ink.x, - ink.y);
+
+ image_cr = cairo_create (image_surface);
+ cairo_set_source_surface (image_cr, recording_surface, 0, 0);
+ cairo_paint (image_cr);
+ cairo_destroy (image_cr);
+
+ _gtk_cairo_blur_surface (image_surface, radius);
+
+ cairo_set_source_surface (original_cr, image_surface, 0, 0);
cairo_paint (original_cr);
cairo_destroy (cr);
+ cairo_surface_destroy (image_surface);
return original_cr;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]