forked from AuroraMiddleware/gtk
shadow: add code to render blurred shadows
Split out the blurred shadow rendering in three steps: - creation of a surface of the appropriate size - we use the clip rectangle as a good measurement for the size, since we won't render out of it anyway - painting the unblurred shape on the surface - this is responsibility of the single shadow implementations - blur the surface and compose the result back on the original cairo_t This means we can share code between the implementations for the first and third steps; it also makes the code independent of the rendered size, so we can avoid passing down a cairo_rectangle_t with e.g. the icon coordinates.
This commit is contained in:
parent
a239f2e8b0
commit
b609686133
@ -21,6 +21,7 @@
|
||||
|
||||
#include "gtkcssshadowvalueprivate.h"
|
||||
|
||||
#include "gtkcairoblurprivate.h"
|
||||
#include "gtkcssnumbervalueprivate.h"
|
||||
#include "gtkcssrgbavalueprivate.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
@ -302,6 +303,68 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const cairo_user_data_key_t shadow_key;
|
||||
|
||||
static cairo_t *
|
||||
gtk_css_shadow_value_start_drawing (const GtkCssValue *shadow,
|
||||
cairo_t *cr)
|
||||
{
|
||||
cairo_rectangle_int_t clip_rect;
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *blur_cr;
|
||||
gdouble radius;
|
||||
|
||||
radius = _gtk_css_number_value_get (shadow->radius, 0);
|
||||
if (radius == 0.0)
|
||||
return cr;
|
||||
|
||||
gdk_cairo_get_clip_rectangle (cr, &clip_rect);
|
||||
|
||||
/* 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);
|
||||
blur_cr = cairo_create (surface);
|
||||
cairo_set_user_data (blur_cr, &shadow_key, cairo_reference (cr), (cairo_destroy_func_t) cairo_destroy);
|
||||
|
||||
if (cairo_has_current_point (cr))
|
||||
{
|
||||
double x, y;
|
||||
|
||||
cairo_get_current_point (cr, &x, &y);
|
||||
cairo_move_to (blur_cr, x, y);
|
||||
}
|
||||
|
||||
return blur_cr;
|
||||
}
|
||||
|
||||
static cairo_t *
|
||||
gtk_css_shadow_value_finish_drawing (const GtkCssValue *shadow,
|
||||
cairo_t *cr)
|
||||
{
|
||||
gdouble radius;
|
||||
cairo_t *original_cr;
|
||||
cairo_surface_t *surface;
|
||||
|
||||
radius = _gtk_css_number_value_get (shadow->radius, 0);
|
||||
if (radius == 0.0)
|
||||
return cr;
|
||||
|
||||
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_paint (original_cr);
|
||||
|
||||
cairo_destroy (cr);
|
||||
|
||||
return original_cr;
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_css_shadow_value_paint_layout (const GtkCssValue *shadow,
|
||||
cairo_t *cr,
|
||||
|
Loading…
Reference in New Issue
Block a user