[gtk+/wip/blur] Optimize blur rendering by always choosing the smaller surface to blur, since rendering speed is inv



commit 51b6ce28871d1c7120d9e39f18079f805ede36db
Author: Andrea Cimitan <andrea cimitan canonical com>
Date:   Wed Apr 18 15:40:52 2012 +0100

    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

 gtk/gtkcssshadowsvalue.c        |    5 +-
 gtk/gtkcssshadowsvalueprivate.h |    4 +-
 gtk/gtkcssshadowvalue.c         |  118 ++++++++++++++++++++++++++-------------
 gtk/gtkcssshadowvalueprivate.h  |    4 +-
 gtk/gtkthemingengine.c          |   13 +++-
 5 files changed, 98 insertions(+), 46 deletions(-)
---
diff --git a/gtk/gtkcssshadowsvalue.c b/gtk/gtkcssshadowsvalue.c
index d4f7655..50ebe96 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 0918278..34b7db9 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 7296caf..ef75617 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,27 @@ _gtk_css_shadow_value_paint_spinner (const GtkCssValue *shadow,
     {
       cairo_t *blur_cr;
       cairo_surface_t *surface;
+      cairo_rectangle_int_t rect_surface;
+
+      /* Calculate blur surface coordinates. */
+      rect_surface.x = _gtk_css_number_value_get (shadow->hoffset, 0) - radius;
+      rect_surface.y = _gtk_css_number_value_get (shadow->voffset, 0) - radius;
+      rect_surface.width = 2 * radius;
+      rect_surface.height = 2 * radius;
 
-      _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. */
       cairo_translate (blur_cr,
-                       _gtk_css_number_value_get (shadow->hoffset, 0),
-                       _gtk_css_number_value_get (shadow->voffset, 0));
+                       radius,
+                       radius);
       _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 +523,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 +549,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 3683e11..695d863 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 a085dc4..9de5254 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);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]