[gtk+/box-shadow: 3/5] shadow: add _gtk_box_shadow_render()
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/box-shadow: 3/5] shadow: add _gtk_box_shadow_render()
- Date: Mon, 6 Jun 2011 18:15:54 +0000 (UTC)
commit 82970033378c47baf6051249a782b6577310e70f
Author: Cosimo Cecchi <cosimoc gnome org>
Date: Wed Jun 1 20:58:53 2011 -0400
shadow: add _gtk_box_shadow_render()
This supports only inset box-shadow elements for now.
gtk/gtkshadow.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++
gtk/gtkshadowprivate.h | 17 +++++-
2 files changed, 149 insertions(+), 3 deletions(-)
---
diff --git a/gtk/gtkshadow.c b/gtk/gtkshadow.c
index ce84e4b..d0b294f 100644
--- a/gtk/gtkshadow.c
+++ b/gtk/gtkshadow.c
@@ -23,6 +23,8 @@
#include "gtkshadowprivate.h"
#include "gtkstylecontext.h"
+#include "gtkthemingengineprivate.h"
+#include "gtkthemingengine.h"
#include "gtkpango.h"
typedef struct _GtkShadowElement GtkShadowElement;
@@ -39,6 +41,42 @@ struct _GtkShadowElement {
GtkSymbolicColor *symbolic_color;
};
+/* From: http://dev.w3.org/csswg/css3-background/#box-shadow
+ *
+ * If a spread distance is defined, the shadow is [...] contracted inward by
+ * an operation [...]. Alternatively the UA may approximate the transformed
+ * shadow perimeter shape by outsetting (insetting, for inner shadows) the
+ * shadow's straight edges by the spread distance and increasing (decreasing,
+ * for inner shadows) and flooring at zero the corner radii by the same amount.
+ */
+static void
+shadow_element_adjust_radius_for_spread (GtkShadowElement *element,
+ const GtkCssBorderRadius *radius,
+ GtkCssBorderRadius *adjusted_radius)
+{
+ GtkCssBorderRadius spread_radius;
+
+ spread_radius.top_left.horizontal =
+ MAX (0, radius->top_left.horizontal - element->spread);
+ spread_radius.top_left.vertical =
+ MAX (0, radius->top_left.vertical - element->spread);
+ spread_radius.top_right.horizontal =
+ MAX (0, radius->top_right.horizontal - element->spread);
+ spread_radius.top_right.vertical =
+ MAX (0, radius->top_right.vertical - element->spread);
+ spread_radius.bottom_right.horizontal =
+ MAX (0, radius->bottom_right.horizontal - element->spread);
+ spread_radius.bottom_right.vertical =
+ MAX (0, radius->bottom_right.vertical - element->spread);
+ spread_radius.bottom_left.horizontal =
+ MAX (0, radius->bottom_left.horizontal - element->spread);
+ spread_radius.bottom_left.vertical =
+ MAX (0, radius->bottom_left.vertical - element->spread);
+
+ if (adjusted_radius != NULL)
+ *adjusted_radius = spread_radius;
+}
+
static void
shadow_element_print (GtkShadowElement *element,
GString *str)
@@ -275,3 +313,100 @@ _gtk_text_shadow_paint_layout (GtkShadow *shadow,
}
}
+void
+_gtk_box_shadow_render (GtkShadow *shadow,
+ cairo_t *cr,
+ gdouble x,
+ gdouble y,
+ gdouble width,
+ gdouble height,
+ GtkBorder *border,
+ GtkCssBorderRadius *border_radius)
+{
+ GtkShadowElement *element;
+ GtkCssBorderRadius spread_radius;
+ gdouble fill_x, fill_y, fill_w, fill_h;
+ GList *l;
+
+ cairo_save (cr);
+
+ cairo_translate (cr, x, y);
+ cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
+
+ _cairo_round_rectangle_sides (cr, border_radius,
+ border->left,
+ border->top,
+ width - border->left - border->right,
+ height - border->top - border->bottom,
+ SIDE_ALL);
+ cairo_clip (cr);
+
+ /* render shadows starting from the last one,
+ * and the others on top.
+ */
+ for (l = g_list_last (shadow->elements); l != NULL; l = l->prev)
+ {
+ element = l->data;
+
+ if (!element->inset)
+ continue;
+
+ cairo_save (cr);
+
+ shadow_element_adjust_radius_for_spread (element,
+ border_radius, &spread_radius);
+
+ if (element->hoffset > 0)
+ {
+ fill_x = border->left + element->hoffset + element->spread;
+ fill_w = width - fill_x - border->right;
+ }
+ else if (element->hoffset < 0)
+ {
+ fill_x = border->left;
+ fill_w = width - border->left - border->right + element->hoffset - element->spread;
+ }
+ else
+ {
+ /* element->hoffset == 0 */
+ fill_x = border->left + element->spread;
+ fill_w = width - border->left - border->right - 2 * element->spread;
+ }
+
+ if (element->voffset > 0)
+ {
+ fill_y = border->top + element->voffset + element->spread;
+ fill_h = height - fill_y - border->bottom;
+ }
+ else if (element->hoffset < 0)
+ {
+ fill_y = border->top;
+ fill_h = height - border->top - border->bottom + element->voffset - element->spread;
+ }
+ else
+ {
+ /* element->voffset == 0 */
+ fill_y = border->top + element->spread;
+ fill_h = height - border->top - border->bottom - 2 * element->spread;
+ }
+
+ _cairo_round_rectangle_sides (cr, border_radius,
+ border->left,
+ border->top,
+ width - border->left - border->right,
+ height - border->top - border->bottom,
+ SIDE_ALL);
+
+ _cairo_round_rectangle_sides (cr, &spread_radius,
+ fill_x, fill_y,
+ fill_w, fill_h,
+ SIDE_ALL);
+
+ gdk_cairo_set_source_rgba (cr, &element->color);
+ cairo_fill (cr);
+
+ cairo_restore (cr);
+ }
+
+ cairo_restore (cr);
+}
diff --git a/gtk/gtkshadowprivate.h b/gtk/gtkshadowprivate.h
index 1594dc6..9f2af13 100644
--- a/gtk/gtkshadowprivate.h
+++ b/gtk/gtkshadowprivate.h
@@ -23,9 +23,11 @@
#define __GTK_SHADOW_H__
#include <glib-object.h>
-#include <gtk/gtkstyleproperties.h>
-#include <gtk/gtksymboliccolor.h>
-#include <gtk/gtkicontheme.h>
+
+#include "gtkstyleproperties.h"
+#include "gtksymboliccolor.h"
+#include "gtkicontheme.h"
+#include "gtkcsstypesprivate.h"
G_BEGIN_DECLS
@@ -58,6 +60,15 @@ void _gtk_text_shadow_paint_layout (GtkShadow *shadow,
cairo_t *cr,
PangoLayout *layout);
+void _gtk_box_shadow_render (GtkShadow *shadow,
+ cairo_t *cr,
+ gdouble x,
+ gdouble y,
+ gdouble width,
+ gdouble height,
+ GtkBorder *border,
+ GtkCssBorderRadius *border_radius);
+
G_END_DECLS
#endif /* __GTK_SHADOW_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]