[gnome-shell/shell-toolkit: 20/32] StThemeNode: Add border-radius support
- From: Owen Taylor <otaylor src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-shell/shell-toolkit: 20/32] StThemeNode: Add border-radius support
- Date: Wed, 30 Sep 2009 00:02:46 +0000 (UTC)
commit c1c4adda02e23017372a4d696691408e0bdee2e3
Author: Owen W. Taylor <otaylor fishsoup net>
Date: Sun Sep 20 09:08:08 2009 -0400
StThemeNode: Add border-radius support
Add support for parsing and caching the border-radius property.
Different radii for the 4 corners are supported; elliptical corners
are not supported.
https://bugzilla.gnome.org/show_bug.cgi?id=595993
src/st/st-theme-node.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++-
src/st/st-theme-node.h | 30 ++++++++----
src/st/test-theme.c | 71 +++++++++++++++++++++++++++++
src/st/test-theme.css | 4 ++
4 files changed, 207 insertions(+), 13 deletions(-)
---
diff --git a/src/st/st-theme-node.c b/src/st/st-theme-node.c
index 6fe550a..176a198 100644
--- a/src/st/st-theme-node.c
+++ b/src/st/st-theme-node.c
@@ -34,6 +34,7 @@ struct _StThemeNode {
ClutterColor foreground_color;
ClutterColor border_color[4];
double border_width[4];
+ double border_radius[4];
guint padding[4];
char *background_image;
@@ -697,6 +698,96 @@ st_theme_node_get_length (StThemeNode *node,
}
static void
+do_border_radius_term (StThemeNode *node,
+ CRTerm *term,
+ gboolean topleft,
+ gboolean topright,
+ gboolean bottomright,
+ gboolean bottomleft)
+{
+ gdouble value;
+
+ if (get_length_from_term (node, term, FALSE, &value) != VALUE_FOUND)
+ return;
+
+ if (topleft)
+ node->border_radius[ST_CORNER_TOPLEFT] = value;
+ if (topright)
+ node->border_radius[ST_CORNER_TOPRIGHT] = value;
+ if (bottomright)
+ node->border_radius[ST_CORNER_BOTTOMRIGHT] = value;
+ if (bottomleft)
+ node->border_radius[ST_CORNER_BOTTOMLEFT] = value;
+}
+
+static void
+do_border_radius (StThemeNode *node,
+ CRDeclaration *decl)
+{
+ const char *property_name = decl->property->stryng->str + 13; /* Skip 'border-radius' */
+
+ if (strcmp (property_name, "") == 0)
+ {
+ /* Slight deviation ... if we don't understand some of the terms and understand others,
+ * then we set the ones we understand and ignore the others instead of ignoring the
+ * whole thing
+ */
+ if (decl->value == NULL) /* 0 values */
+ return;
+ else if (decl->value->next == NULL) /* 1 value */
+ {
+ do_border_radius_term (node, decl->value, TRUE, TRUE, TRUE, TRUE); /* all corners */
+ return;
+ }
+ else if (decl->value->next->next == NULL) /* 2 values */
+ {
+ do_border_radius_term (node, decl->value, TRUE, FALSE, TRUE, FALSE); /* topleft/bottomright */
+ do_border_radius_term (node, decl->value->next, FALSE, TRUE, FALSE, TRUE); /* topright/bottomleft */
+ }
+ else if (decl->value->next->next->next == NULL) /* 3 values */
+ {
+ do_border_radius_term (node, decl->value, TRUE, FALSE, FALSE, FALSE); /* topleft */
+ do_border_radius_term (node, decl->value->next, FALSE, TRUE, FALSE, TRUE); /* topright/bottomleft */
+ do_border_radius_term (node, decl->value->next->next, FALSE, FALSE, TRUE, FALSE); /* bottomright */
+ }
+ else if (decl->value->next->next->next->next == NULL) /* 4 values */
+ {
+ do_border_radius_term (node, decl->value, TRUE, FALSE, FALSE, FALSE); /* topleft */
+ do_border_radius_term (node, decl->value->next, FALSE, TRUE, FALSE, FALSE); /* topright */
+ do_border_radius_term (node, decl->value->next->next, FALSE, FALSE, TRUE, FALSE); /* bottomright */
+ do_border_radius_term (node, decl->value->next->next->next, FALSE, FALSE, FALSE, TRUE); /* bottomleft */
+ }
+ else
+ {
+ g_warning ("Too many values for border-radius property");
+ return;
+ }
+ }
+ else
+ {
+ if (decl->value == NULL || decl->value->next != NULL)
+ return;
+
+ if (strcmp (property_name, "-topleft") == 0)
+ {
+ do_border_radius_term (node, decl->value, TRUE, FALSE, FALSE, FALSE);
+ }
+ else if (strcmp (property_name, "-topright") == 0)
+ {
+ do_border_radius_term (node, decl->value, FALSE, TRUE, FALSE, FALSE);
+ }
+ else if (strcmp (property_name, "-bottomright") == 0)
+ {
+ do_border_radius_term (node, decl->value, FALSE, FALSE, TRUE, FALSE);
+ }
+ else if (strcmp (property_name, "-bottomleft") == 0)
+ {
+ do_border_radius_term (node, decl->value, FALSE, FALSE, FALSE, TRUE);
+ }
+ }
+}
+
+static void
do_border_property (StThemeNode *node,
CRDeclaration *decl)
{
@@ -708,6 +799,12 @@ do_border_property (StThemeNode *node,
gboolean width_set = FALSE;
int j;
+ if (g_str_has_prefix (property_name, "-radius"))
+ {
+ do_border_radius (node, decl);
+ return;
+ }
+
if (g_str_has_prefix (property_name, "-left"))
{
side = ST_SIDE_LEFT;
@@ -955,13 +1052,25 @@ st_theme_node_get_border_width (StThemeNode *node,
StSide side)
{
g_return_val_if_fail (ST_IS_THEME_NODE (node), 0.);
- g_return_val_if_fail (side >= ST_SIDE_LEFT && side <= ST_SIDE_BOTTOM, 0.);
+ g_return_val_if_fail (side >= ST_SIDE_TOP && side <= ST_SIDE_LEFT, 0.);
ensure_borders (node);
return node->border_width[side];
}
+double
+st_theme_node_get_border_radius (StThemeNode *node,
+ StCorner corner)
+{
+ g_return_val_if_fail (ST_IS_THEME_NODE (node), 0.);
+ g_return_val_if_fail (corner >= ST_CORNER_TOPLEFT && corner <= ST_CORNER_BOTTOMLEFT, 0.);
+
+ ensure_borders (node);
+
+ return node->border_radius[corner];
+}
+
static GetFromTermResult
get_background_color_from_term (StThemeNode *node,
CRTerm *term,
@@ -1150,7 +1259,7 @@ st_theme_node_get_border_color (StThemeNode *node,
ClutterColor *color)
{
g_return_if_fail (ST_IS_THEME_NODE (node));
- g_return_if_fail (side >= ST_SIDE_LEFT && side <= ST_SIDE_BOTTOM);
+ g_return_if_fail (side >= ST_SIDE_TOP && side <= ST_SIDE_LEFT);
ensure_borders (node);
@@ -1162,7 +1271,7 @@ st_theme_node_get_padding (StThemeNode *node,
StSide side)
{
g_return_val_if_fail (ST_IS_THEME_NODE (node), 0.);
- g_return_val_if_fail (side >= ST_SIDE_LEFT && side <= ST_SIDE_BOTTOM, 0.);
+ g_return_val_if_fail (side >= ST_SIDE_TOP && side <= ST_SIDE_LEFT, 0.);
ensure_borders (node);
diff --git a/src/st/st-theme-node.h b/src/st/st-theme-node.h
index 608c45a..d95e7cc 100644
--- a/src/st/st-theme-node.h
+++ b/src/st/st-theme-node.h
@@ -21,12 +21,19 @@ typedef struct _StThemeNodeClass StThemeNodeClass;
#define ST_THEME_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_THEME_NODE, StThemeNodeClass))
typedef enum {
- ST_SIDE_LEFT,
- ST_SIDE_RIGHT,
ST_SIDE_TOP,
- ST_SIDE_BOTTOM
+ ST_SIDE_RIGHT,
+ ST_SIDE_BOTTOM,
+ ST_SIDE_LEFT
} StSide;
+typedef enum {
+ ST_CORNER_TOPLEFT,
+ ST_CORNER_TOPRIGHT,
+ ST_CORNER_BOTTOMRIGHT,
+ ST_CORNER_BOTTOMLEFT
+} StCorner;
+
/* These are the CSS values; that doesn't mean we have to implement blink... */
typedef enum {
ST_TEXT_DECORATION_UNDERLINE = 1 << 0,
@@ -89,13 +96,16 @@ void st_theme_node_get_foreground_color (StThemeNode *node,
const char *st_theme_node_get_background_image (StThemeNode *node);
-double st_theme_node_get_border_width (StThemeNode *node,
- StSide side);
-void st_theme_node_get_border_color (StThemeNode *node,
- StSide side,
- ClutterColor *color);
-double st_theme_node_get_padding (StThemeNode *node,
- StSide side);
+double st_theme_node_get_border_width (StThemeNode *node,
+ StSide side);
+double st_theme_node_get_border_radius (StThemeNode *node,
+ StCorner corner);
+void st_theme_node_get_border_color (StThemeNode *node,
+ StSide side,
+ ClutterColor *color);
+
+double st_theme_node_get_padding (StThemeNode *node,
+ StSide side);
StTextDecoration st_theme_node_get_text_decoration (StThemeNode *node);
diff --git a/src/st/test-theme.c b/src/st/test-theme.c
index 30bc4bd..f39471a 100644
--- a/src/st/test-theme.c
+++ b/src/st/test-theme.c
@@ -112,6 +112,42 @@ assert_background_color (StThemeNode *node,
}
}
+static const char *
+side_to_string (StSide side)
+{
+ switch (side)
+ {
+ case ST_SIDE_TOP:
+ return "top";
+ case ST_SIDE_RIGHT:
+ return "right";
+ case ST_SIDE_BOTTOM:
+ return "bottom";
+ case ST_SIDE_LEFT:
+ return "left";
+ }
+
+ return "<unknown>";
+}
+
+static void
+assert_border_color (StThemeNode *node,
+ const char *node_description,
+ StSide side,
+ guint32 expected)
+{
+ ClutterColor color;
+ st_theme_node_get_border_color (node, side, &color);
+ guint32 value = clutter_color_to_pixel (&color);
+
+ if (expected != value)
+ {
+ g_print ("%s: %s.border-%s-color: expected: #%08x, got: #%08x\n",
+ test, node_description, side_to_string (side), expected, value);
+ fail = TRUE;
+ }
+}
+
static void
assert_background_image (StThemeNode *node,
const char *node_description,
@@ -223,6 +259,40 @@ test_padding (void)
}
static void
+test_border (void)
+{
+ test = "border";
+
+ /* group2 is defined as having a thin black border along the top three
+ * sides with rounded joins, then a square-joined green border at the
+ * botttom
+ */
+
+ assert_length ("group2", "border-top-width", 2.,
+ st_theme_node_get_border_width (group2, ST_SIDE_TOP));
+ assert_length ("group2", "border-right-width", 2.,
+ st_theme_node_get_border_width (group2, ST_SIDE_RIGHT));
+ assert_length ("group2", "border-bottom-width", 5.,
+ st_theme_node_get_border_width (group2, ST_SIDE_BOTTOM));
+ assert_length ("group2", "border-left-width", 2.,
+ st_theme_node_get_border_width (group2, ST_SIDE_LEFT));
+
+ assert_border_color (group2, "group2", ST_SIDE_TOP, 0x000000ff);
+ assert_border_color (group2, "group2", ST_SIDE_RIGHT, 0x000000ff);
+ assert_border_color (group2, "group2", ST_SIDE_BOTTOM, 0x0000ffff);
+ assert_border_color (group2, "group2", ST_SIDE_LEFT, 0x000000ff);
+
+ assert_length ("group2", "border-radius-topleft", 10.,
+ st_theme_node_get_border_radius (group2, ST_CORNER_TOPLEFT));
+ assert_length ("group2", "border-radius-topright", 10.,
+ st_theme_node_get_border_radius (group2, ST_CORNER_TOPRIGHT));
+ assert_length ("group2", "border-radius-bottomright", 0.,
+ st_theme_node_get_border_radius (group2, ST_CORNER_BOTTOMRIGHT));
+ assert_length ("group2", "border-radius-bottomleft", 0.,
+ st_theme_node_get_border_radius (group2, ST_CORNER_BOTTOMLEFT));
+}
+
+static void
test_background (void)
{
test = "background";
@@ -312,6 +382,7 @@ main (int argc, char **argv)
test_type_inheritance ();
test_adjacent_selector ();
test_padding ();
+ test_border ();
test_background ();
test_font ();
test_pseudo_class ();
diff --git a/src/st/test-theme.css b/src/st/test-theme.css
index be512d5..b2fad36 100644
--- a/src/st/test-theme.css
+++ b/src/st/test-theme.css
@@ -58,6 +58,10 @@ stage > #text2 {
#group2 {
background-image: url('other-background.png');
padding: 1px 2px 3px 4px;
+
+ border: 2px solid #000000;
+ border-bottom: 5px solid #0000ff;
+ border-radius: 10px 10px 0px 0px;
}
ClutterText:hover {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]