Optimize blur rendering by always choosing the smaller surface to blur, since rendering speed is inversely proportional to the dimension of the surface to blur

This commit is contained in:
Andrea Cimitan
2012-04-18 15:40:52 +01:00
parent 654553cc70
commit b40f90f47b
5 changed files with 95 additions and 46 deletions

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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;
cairo_rectangle_int_t rect_surface;
gdouble x, y;
gint extra_pad;
_gtk_css_shadow_value_blur_surface_create (shadow, cr,
&blur_cr, &surface);
/* 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;
_gtk_css_shadow_value_blur_surface_create (shadow, cr,
&blur_cr, &surface);
/* 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,
&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);

View File

@@ -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);

View File

@@ -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);