summaryrefslogtreecommitdiff
path: root/gtk/gtkcssshadowvalue.c
diff options
context:
space:
mode:
Diffstat (limited to 'gtk/gtkcssshadowvalue.c')
-rw-r--r--gtk/gtkcssshadowvalue.c117
1 files changed, 77 insertions, 40 deletions
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);