summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrea Cimitan <andrea.cimitan@canonical.com>2012-04-18 15:40:52 +0100
committerAndrea Cimitan <andrea.cimitan@canonical.com>2012-04-18 16:02:32 +0100
commitb40f90f47b19bafb27d4ca46e52dc884276827fe (patch)
treee38752b63813cea7b947c03d84190c8edbbdbc9e
parent654553cc706d6e21e7e2b631ac9521e530c58fb1 (diff)
downloadgtk+-wip/blur.tar.gz
Optimize blur rendering by always choosing the smaller surface to blur, since rendering speed is inversely proportional to the dimension of the surface to blurwip/blur
-rw-r--r--gtk/gtkcssshadowsvalue.c5
-rw-r--r--gtk/gtkcssshadowsvalueprivate.h4
-rw-r--r--gtk/gtkcssshadowvalue.c117
-rw-r--r--gtk/gtkcssshadowvalueprivate.h4
-rw-r--r--gtk/gtkthemingengine.c13
5 files changed, 96 insertions, 47 deletions
diff --git a/gtk/gtkcssshadowsvalue.c b/gtk/gtkcssshadowsvalue.c
index d4f7655b52..50ebe960d2 100644
--- a/gtk/gtkcssshadowsvalue.c
+++ b/gtk/gtkcssshadowsvalue.c
@@ -228,7 +228,8 @@ _gtk_css_shadows_value_paint_layout (const GtkCssValue *shadows,
void
_gtk_css_shadows_value_paint_icon (const GtkCssValue *shadows,
- cairo_t *cr)
+ cairo_t *cr,
+ cairo_rectangle_t *rect)
{
guint i;
@@ -236,7 +237,7 @@ _gtk_css_shadows_value_paint_icon (const GtkCssValue *shadows,
for (i = 0; i < shadows->len; i++)
{
- _gtk_css_shadow_value_paint_icon (shadows->values[i], cr);
+ _gtk_css_shadow_value_paint_icon (shadows->values[i], cr, rect);
}
}
diff --git a/gtk/gtkcssshadowsvalueprivate.h b/gtk/gtkcssshadowsvalueprivate.h
index 0918278b4e..34b7db982a 100644
--- a/gtk/gtkcssshadowsvalueprivate.h
+++ b/gtk/gtkcssshadowsvalueprivate.h
@@ -41,12 +41,14 @@ void _gtk_css_shadows_value_paint_layout (const GtkCssValue
PangoLayout *layout);
void _gtk_css_shadows_value_paint_icon (const GtkCssValue *shadows,
- cairo_t *cr);
+ cairo_t *cr,
+ cairo_rectangle_t *rect);
void _gtk_css_shadows_value_paint_spinner (const GtkCssValue *shadows,
cairo_t *cr,
gdouble radius,
gdouble progress);
+
void _gtk_css_shadows_value_paint_box (const GtkCssValue *shadows,
cairo_t *cr,
const GtkRoundedBox *padding_box);
diff --git a/gtk/gtkcssshadowvalue.c b/gtk/gtkcssshadowvalue.c
index 7296caf303..573ae3820c 100644
--- a/gtk/gtkcssshadowvalue.c
+++ b/gtk/gtkcssshadowvalue.c
@@ -18,6 +18,7 @@
*/
#include "config.h"
+#include "math.h"
#include "gtkcssshadowvalueprivate.h"
@@ -291,43 +292,41 @@ _gtk_css_shadow_value_compute (GtkCssValue *shadow,
}
static void
-_gtk_css_shadow_value_blur_surface_create (const GtkCssValue *shadow,
- cairo_t *original_cr,
- cairo_t **out_cr,
- cairo_surface_t **out_surface)
+gtk_css_shadow_value_blur_surface_create (const GtkCssValue *shadow,
+ cairo_t *original_cr,
+ cairo_t **out_cr,
+ cairo_surface_t **out_surface,
+ cairo_rectangle_int_t *rect_surface)
{
- cairo_rectangle_int_t clip_rect;
- gdouble radius;
+ gint radius;
- gdk_cairo_get_clip_rectangle (original_cr, &clip_rect);
- radius = _gtk_css_number_value_get (shadow->radius, 0);
+ radius = ceil (_gtk_css_number_value_get (shadow->radius, 0));
/* Create a larger surface to center the blur. */
*out_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
- clip_rect.width + 2 * radius,
- clip_rect.height + 2 * radius);
+ rect_surface->width + 2 * radius,
+ rect_surface->height + 2 * radius);
*out_cr = cairo_create (*out_surface);
cairo_translate (*out_cr, radius, radius);
}
static void
-_gtk_css_shadow_value_blur_surface_paint (const GtkCssValue *shadow,
- cairo_t *cr,
- cairo_surface_t *surface)
+gtk_css_shadow_value_blur_surface_paint (const GtkCssValue *shadow,
+ cairo_t *cr,
+ cairo_surface_t *surface,
+ cairo_rectangle_int_t *rect_surface)
{
- gdouble x, y;
- gdouble radius;
+ gint radius;
- radius = _gtk_css_number_value_get (shadow->radius, 0);
+ radius = ceil (_gtk_css_number_value_get (shadow->radius, 0));
/* Blur the surface. */
_gtk_cairo_blur_surface (surface, radius);
/* Paint the blurred surface to cr. */
- cairo_get_current_point (cr, &x, &y);
cairo_set_source_surface (cr, surface,
- x - radius,
- y - radius);
+ rect_surface->x - radius,
+ rect_surface->y - radius);
cairo_paint (cr);
}
@@ -349,17 +348,35 @@ _gtk_css_shadow_value_paint_layout (const GtkCssValue *shadow,
if (_gtk_css_number_value_get (shadow->radius, 0) > 0)
{
+ PangoRectangle ink_rect;
cairo_t *blur_cr;
cairo_surface_t *surface;
-
- _gtk_css_shadow_value_blur_surface_create (shadow, cr,
- &blur_cr, &surface);
+ cairo_rectangle_int_t rect_surface;
+ gdouble x, y;
+ gint extra_pad;
+
+ /* Calculate blur surface coordinates. */
+ extra_pad = 1; /* Padding seems to help on blur edges, please verify. */
+ pango_layout_get_pixel_extents (layout, &ink_rect, NULL);
+ cairo_get_current_point (cr, &x, &y);
+ rect_surface.x = x + ink_rect.x - extra_pad; /* Loss of precision? */
+ rect_surface.y = y + ink_rect.y - extra_pad; /* Loss of precision? */
+ rect_surface.width = ink_rect.width + 2 * extra_pad;
+ rect_surface.height = ink_rect.height + 2 * extra_pad;
+
+ gtk_css_shadow_value_blur_surface_create (shadow, cr,
+ &blur_cr, &surface,
+ &rect_surface);
/* Create the path on the surface to blur. */
+ cairo_translate (blur_cr,
+ - ink_rect.x + extra_pad,
+ - ink_rect.y + extra_pad);
+
gdk_cairo_set_source_rgba (blur_cr, _gtk_css_rgba_value_get_rgba (shadow->color));
_gtk_pango_fill_layout (blur_cr, layout);
- _gtk_css_shadow_value_blur_surface_paint (shadow, cr, surface);
+ gtk_css_shadow_value_blur_surface_paint (shadow, cr, surface, &rect_surface);
cairo_destroy (blur_cr);
cairo_surface_destroy (surface);
@@ -378,7 +395,8 @@ _gtk_css_shadow_value_paint_layout (const GtkCssValue *shadow,
void
_gtk_css_shadow_value_paint_icon (const GtkCssValue *shadow,
- cairo_t *cr)
+ cairo_t *cr,
+ cairo_rectangle_t *rect)
{
cairo_pattern_t *pattern;
@@ -391,19 +409,23 @@ _gtk_css_shadow_value_paint_icon (const GtkCssValue *shadow,
{
cairo_t *blur_cr;
cairo_surface_t *surface;
+ cairo_rectangle_int_t rect_surface;
- _gtk_css_shadow_value_blur_surface_create (shadow, cr,
- &blur_cr, &surface);
+ /* Calculate blur surface coordinates. */
+ rect_surface.x = rect->x + _gtk_css_number_value_get (shadow->hoffset, 0);
+ rect_surface.y = rect->y + _gtk_css_number_value_get (shadow->voffset, 0);
+ rect_surface.width = rect->width;
+ rect_surface.height = rect->height;
+
+ gtk_css_shadow_value_blur_surface_create (shadow, cr,
+ &blur_cr, &surface,
+ &rect_surface);
/* Create the path on the surface to blur. */
gdk_cairo_set_source_rgba (blur_cr, _gtk_css_rgba_value_get_rgba (shadow->color));
-
- cairo_translate (blur_cr,
- _gtk_css_number_value_get (shadow->hoffset, 0),
- _gtk_css_number_value_get (shadow->voffset, 0));
cairo_mask (blur_cr, pattern);
- _gtk_css_shadow_value_blur_surface_paint (shadow, cr, surface);
+ gtk_css_shadow_value_blur_surface_paint (shadow, cr, surface, &rect_surface);
cairo_destroy (blur_cr);
cairo_surface_destroy (surface);
@@ -436,19 +458,24 @@ _gtk_css_shadow_value_paint_spinner (const GtkCssValue *shadow,
{
cairo_t *blur_cr;
cairo_surface_t *surface;
+ cairo_rectangle_int_t rect_surface;
- _gtk_css_shadow_value_blur_surface_create (shadow, cr,
- &blur_cr, &surface);
+ /* Calculate blur surface coordinates. */
+ rect_surface.x = _gtk_css_number_value_get (shadow->hoffset, 0);
+ rect_surface.y = _gtk_css_number_value_get (shadow->voffset, 0);
+ rect_surface.width = 2 * radius;
+ rect_surface.height = 2 * radius;
+
+ gtk_css_shadow_value_blur_surface_create (shadow, cr,
+ &blur_cr, &surface,
+ &rect_surface);
/* Create the path on the surface to blur. */
- cairo_translate (blur_cr,
- _gtk_css_number_value_get (shadow->hoffset, 0),
- _gtk_css_number_value_get (shadow->voffset, 0));
_gtk_theming_engine_paint_spinner (blur_cr,
radius, progress,
_gtk_css_rgba_value_get_rgba (shadow->color));
- _gtk_css_shadow_value_blur_surface_paint (shadow, cr, surface);
+ gtk_css_shadow_value_blur_surface_paint (shadow, cr, surface, &rect_surface);
cairo_destroy (blur_cr);
cairo_surface_destroy (surface);
@@ -493,9 +520,19 @@ _gtk_css_shadow_value_paint_box (const GtkCssValue *shadow,
{
cairo_t *blur_cr;
cairo_surface_t *surface;
+ cairo_rectangle_int_t rect_surface;
+ gdouble x, y;
+
+ /* Calculate blur surface coordinates. */
+ cairo_get_current_point (cr, &x, &y);
+ rect_surface.x = x; /* Loss of precision? */
+ rect_surface.x = y; /* Loss of precision? */
+ rect_surface.width = MAX (padding_box->box.width, box.box.width);
+ rect_surface.height = MAX (padding_box->box.height, box.box.height);
- _gtk_css_shadow_value_blur_surface_create (shadow, cr,
- &blur_cr, &surface);
+ gtk_css_shadow_value_blur_surface_create (shadow, cr,
+ &blur_cr, &surface,
+ &rect_surface);
/* Create the path on the surface to blur. */
_gtk_rounded_box_path (padding_box, blur_cr);
@@ -509,7 +546,7 @@ _gtk_css_shadow_value_paint_box (const GtkCssValue *shadow,
gdk_cairo_set_source_rgba (blur_cr, _gtk_css_rgba_value_get_rgba (shadow->color));
cairo_fill (blur_cr);
- _gtk_css_shadow_value_blur_surface_paint (shadow, cr, surface);
+ gtk_css_shadow_value_blur_surface_paint (shadow, cr, surface, &rect_surface);
cairo_destroy (blur_cr);
cairo_surface_destroy (surface);
diff --git a/gtk/gtkcssshadowvalueprivate.h b/gtk/gtkcssshadowvalueprivate.h
index 3683e11091..695d863f44 100644
--- a/gtk/gtkcssshadowvalueprivate.h
+++ b/gtk/gtkcssshadowvalueprivate.h
@@ -42,12 +42,14 @@ void _gtk_css_shadow_value_paint_layout (const GtkCssValue
PangoLayout *layout);
void _gtk_css_shadow_value_paint_icon (const GtkCssValue *shadow,
- cairo_t *cr);
+ cairo_t *cr,
+ cairo_rectangle_t *rect);
void _gtk_css_shadow_value_paint_spinner (const GtkCssValue *shadow,
cairo_t *cr,
gdouble radius,
gdouble progress);
+
void _gtk_css_shadow_value_paint_box (const GtkCssValue *shadow,
cairo_t *cr,
const GtkRoundedBox *padding_box);
diff --git a/gtk/gtkthemingengine.c b/gtk/gtkthemingengine.c
index a085dc421e..9de5254f8d 100644
--- a/gtk/gtkthemingengine.c
+++ b/gtk/gtkthemingengine.c
@@ -178,7 +178,7 @@ static GdkPixbuf * gtk_theming_engine_render_icon_pixbuf (GtkThemingEngine *e
GtkIconSize size);
static void gtk_theming_engine_render_icon (GtkThemingEngine *engine,
cairo_t *cr,
- GdkPixbuf *pixbuf,
+ GdkPixbuf *pixbuf,
gdouble x,
gdouble y);
@@ -2928,15 +2928,22 @@ gtk_theming_engine_render_icon_pixbuf (GtkThemingEngine *engine,
static void
gtk_theming_engine_render_icon (GtkThemingEngine *engine,
cairo_t *cr,
- GdkPixbuf *pixbuf,
+ GdkPixbuf *pixbuf,
gdouble x,
gdouble y)
{
+ cairo_rectangle_t rect;
+
cairo_save (cr);
gdk_cairo_set_source_pixbuf (cr, pixbuf, x, y);
- _gtk_css_shadows_value_paint_icon (_gtk_theming_engine_peek_property (engine, GTK_CSS_PROPERTY_ICON_SHADOW), cr);
+ rect.x = x;
+ rect.y = y;
+ rect.width = gdk_pixbuf_get_width (pixbuf);
+ rect.height = gdk_pixbuf_get_height (pixbuf);
+
+ _gtk_css_shadows_value_paint_icon (_gtk_theming_engine_peek_property (engine, GTK_CSS_PROPERTY_ICON_SHADOW), cr, &rect);
cairo_paint (cr);