[gtk+] css shadows: Split up rendering of shadows
- From: Alexander Larsson <alexl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] css shadows: Split up rendering of shadows
- Date: Mon, 6 May 2013 14:29:34 +0000 (UTC)
commit 66d3b5a9cdb8f9799dc5080495f33fb56101da1b
Author: Alexander Larsson <alexl redhat com>
Date: Mon May 6 13:06:13 2013 +0200
css shadows: Split up rendering of shadows
We split up the rendering of blurred shadows into 9 parts, the
corners, the sides and the rest. This lets us only blur the "blurry"
part, and it lets us completely skip blurry parts that are fully
clipped.
gtk/gtkcssshadowvalue.c | 155 +++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 151 insertions(+), 4 deletions(-)
---
diff --git a/gtk/gtkcssshadowvalue.c b/gtk/gtkcssshadowvalue.c
index 7b6efdc..8699f6f 100644
--- a/gtk/gtkcssshadowvalue.c
+++ b/gtk/gtkcssshadowvalue.c
@@ -488,14 +488,18 @@ static void
draw_shadow (const GtkCssValue *shadow,
cairo_t *cr,
GtkRoundedBox *box,
- GtkRoundedBox *clip_box)
+ GtkRoundedBox *clip_box,
+ gboolean blur)
{
cairo_t *shadow_cr;
if (has_empty_clip (cr))
return;
- shadow_cr = gtk_css_shadow_value_start_drawing (shadow, cr);
+ if (blur)
+ shadow_cr = gtk_css_shadow_value_start_drawing (shadow, cr);
+ else
+ shadow_cr = cr;
cairo_set_fill_rule (shadow_cr, CAIRO_FILL_RULE_EVEN_ODD);
_gtk_rounded_box_path (box, shadow_cr);
@@ -505,7 +509,8 @@ draw_shadow (const GtkCssValue *shadow,
gdk_cairo_set_source_rgba (shadow_cr, _gtk_css_rgba_value_get_rgba (shadow->color));
cairo_fill (shadow_cr);
- gtk_css_shadow_value_finish_drawing (shadow, shadow_cr);
+ if (blur)
+ gtk_css_shadow_value_finish_drawing (shadow, shadow_cr);
}
void
@@ -539,6 +544,7 @@ _gtk_css_shadow_value_paint_box (const GtkCssValue *shadow,
clip_box = *padding_box;
_gtk_rounded_box_grow (&clip_box, outside, outside, outside, outside);
_gtk_rounded_box_clip_path (&clip_box, cr);
+
cairo_clip (cr);
}
@@ -559,7 +565,148 @@ _gtk_css_shadow_value_paint_box (const GtkCssValue *shadow,
clip_box = *padding_box;
_gtk_rounded_box_shrink (&clip_box, -radius, -radius, -radius, -radius);
- draw_shadow (shadow, cr, &box, &clip_box);
+ if (radius == 0)
+ draw_shadow (shadow, cr, &box, &clip_box, FALSE);
+ else
+ {
+ int i, x1, x2, y1, y2;
+ cairo_region_t *remaining;
+ cairo_rectangle_int_t r;
+
+ /* For the blurred case we divide the rendering into 9 parts,
+ * 4 of the corners, 4 for the horizonat/vertical lines and
+ * one for the interior. We make the non-interior parts
+ * large enought to fit the full radius of the blur, so that
+ * the interior part can be drawn solidly.
+ */
+
+ if (shadow->inset)
+ {
+ /* In the inset case we want to paint the whole clip-box.
+ * We could remove the part of "box" where the blur doesn't
+ * reach, but computing that is a bit tricky since the
+ * rounded corners are on the "inside" of it. */
+ r.x = floor (clip_box.box.x);
+ r.y = floor (clip_box.box.y);
+ r.width = ceil (clip_box.box.x + clip_box.box.width) - r.x;
+ r.height = ceil (clip_box.box.y + clip_box.box.height) - r.y;
+ remaining = cairo_region_create_rectangle (&r);
+ }
+ else
+ {
+ /* In the outset case we want to paint the entire box, plus as far
+ * as the radius reaches from it */
+ r.x = floor (box.box.x - radius);
+ r.y = floor (box.box.y - radius);
+ r.width = ceil (box.box.x + box.box.width + radius) - r.x;
+ r.height = ceil (box.box.y + box.box.height + radius) - r.y;
+
+ remaining = cairo_region_create_rectangle (&r);
+ }
+
+ /* First do the corners of box */
+ for (i = 0; i < 4; i++)
+ {
+ if (i == GTK_CSS_TOP_LEFT || i == GTK_CSS_BOTTOM_LEFT)
+ {
+ x1 = floor (box.box.x - radius);
+ x2 = ceil (box.box.x + box.corner[i].horizontal + radius);
+ }
+ else
+ {
+ x1 = floor (box.box.x + box.box.width - box.corner[i].horizontal - radius);
+ x2 = ceil (box.box.x + box.box.width + radius);
+ }
+
+ if (i == GTK_CSS_TOP_LEFT || i == GTK_CSS_TOP_RIGHT)
+ {
+ y1 = floor (box.box.y - radius);
+ y2 = ceil (box.box.y + box.corner[i].vertical + radius);
+ }
+ else
+ {
+ y1 = floor (box.box.y + box.box.height - box.corner[i].vertical - radius);
+ y2 = ceil (box.box.y + box.box.height + radius);
+ }
+
+
+ cairo_save (cr);
+ cairo_rectangle (cr, x1, y1, x2 - x1, y2 - y1);
+ cairo_clip (cr);
+ /* Also clip with remaining to ensure we never draw any area twice */
+ gdk_cairo_region (cr, remaining);
+ cairo_clip (cr);
+ draw_shadow (shadow, cr, &box, &clip_box, TRUE);
+ cairo_restore (cr);
+
+ /* We drew the region, remove it from remaining */
+ r.x = x1;
+ r.y = y1;
+ r.width = x2 - x1;
+ r.height = y2 - y1;
+ cairo_region_subtract_rectangle (remaining, &r);
+ }
+
+ /* Then the sides */
+ for (i = 0; i < 4; i++)
+ {
+ if (i == GTK_CSS_TOP || i == GTK_CSS_BOTTOM)
+ {
+ x1 = floor (box.box.x - radius);
+ x2 = ceil (box.box.x + box.box.width + radius);
+ }
+ else if (i == GTK_CSS_LEFT)
+ {
+ x1 = floor (box.box.x -radius);
+ x2 = ceil (box.box.x + radius);
+ }
+ else
+ {
+ x1 = floor (box.box.x + box.box.width -radius);
+ x2 = ceil (box.box.x + box.box.width + radius);
+ }
+
+ if (i == GTK_CSS_LEFT || i == GTK_CSS_RIGHT)
+ {
+ y1 = floor (box.box.y - radius);
+ y2 = ceil (box.box.y + box.box.height + radius);
+ }
+ else if (i == GTK_CSS_TOP)
+ {
+ y1 = floor (box.box.y -radius);
+ y2 = ceil (box.box.y + radius);
+ }
+ else
+ {
+ y1 = floor (box.box.y + box.box.height -radius);
+ y2 = ceil (box.box.y + box.box.height + radius);
+ }
+
+ cairo_save (cr);
+ cairo_rectangle (cr, x1, y1, x2 - x1, y2 - y1);
+ cairo_clip (cr);
+ /* Also clip with remaining to ensure we never draw any area twice */
+ gdk_cairo_region (cr, remaining);
+ cairo_clip (cr);
+ draw_shadow (shadow, cr, &box, &clip_box, TRUE);
+ cairo_restore (cr);
+
+ /* We drew the region, remove it from remaining */
+ r.x = x1;
+ r.y = y1;
+ r.width = x2 - x1;
+ r.height = y2 - y1;
+ cairo_region_subtract_rectangle (remaining, &r);
+ }
+
+ /* Then the rest, which needs no blurring */
+
+ cairo_save (cr);
+ gdk_cairo_region (cr, remaining);
+ cairo_clip (cr);
+ draw_shadow (shadow, cr, &box, &clip_box, FALSE);
+ cairo_restore (cr);
+ }
cairo_restore (cr);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]