ShellThemeNode: 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.
This commit is contained in:
parent
8ffa161a7f
commit
49ba54820c
@ -34,6 +34,7 @@ struct _ShellThemeNode {
|
|||||||
ClutterColor foreground_color;
|
ClutterColor foreground_color;
|
||||||
ClutterColor border_color[4];
|
ClutterColor border_color[4];
|
||||||
double border_width[4];
|
double border_width[4];
|
||||||
|
double border_radius[4];
|
||||||
guint padding[4];
|
guint padding[4];
|
||||||
|
|
||||||
char *background_image;
|
char *background_image;
|
||||||
@ -696,6 +697,96 @@ shell_theme_node_get_length (ShellThemeNode *node,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_border_radius_term (ShellThemeNode *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[SHELL_CORNER_TOPLEFT] = value;
|
||||||
|
if (topright)
|
||||||
|
node->border_radius[SHELL_CORNER_TOPRIGHT] = value;
|
||||||
|
if (bottomright)
|
||||||
|
node->border_radius[SHELL_CORNER_BOTTOMRIGHT] = value;
|
||||||
|
if (bottomleft)
|
||||||
|
node->border_radius[SHELL_CORNER_BOTTOMLEFT] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_border_radius (ShellThemeNode *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
|
static void
|
||||||
do_border_property (ShellThemeNode *node,
|
do_border_property (ShellThemeNode *node,
|
||||||
CRDeclaration *decl)
|
CRDeclaration *decl)
|
||||||
@ -708,6 +799,12 @@ do_border_property (ShellThemeNode *node,
|
|||||||
gboolean width_set = FALSE;
|
gboolean width_set = FALSE;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
|
if (g_str_has_prefix (property_name, "-radius"))
|
||||||
|
{
|
||||||
|
do_border_radius (node, decl);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (g_str_has_prefix (property_name, "-left"))
|
if (g_str_has_prefix (property_name, "-left"))
|
||||||
{
|
{
|
||||||
side = SHELL_SIDE_LEFT;
|
side = SHELL_SIDE_LEFT;
|
||||||
@ -955,13 +1052,25 @@ shell_theme_node_get_border_width (ShellThemeNode *node,
|
|||||||
ShellSide side)
|
ShellSide side)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (SHELL_IS_THEME_NODE (node), 0.);
|
g_return_val_if_fail (SHELL_IS_THEME_NODE (node), 0.);
|
||||||
g_return_val_if_fail (side >= SHELL_SIDE_LEFT && side <= SHELL_SIDE_BOTTOM, 0.);
|
g_return_val_if_fail (side >= SHELL_SIDE_TOP && side <= SHELL_SIDE_LEFT, 0.);
|
||||||
|
|
||||||
ensure_borders (node);
|
ensure_borders (node);
|
||||||
|
|
||||||
return node->border_width[side];
|
return node->border_width[side];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
shell_theme_node_get_border_radius (ShellThemeNode *node,
|
||||||
|
ShellCorner corner)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (SHELL_IS_THEME_NODE (node), 0.);
|
||||||
|
g_return_val_if_fail (corner >= SHELL_CORNER_TOPLEFT && corner <= SHELL_CORNER_BOTTOMLEFT, 0.);
|
||||||
|
|
||||||
|
ensure_borders (node);
|
||||||
|
|
||||||
|
return node->border_radius[corner];
|
||||||
|
}
|
||||||
|
|
||||||
static GetFromTermResult
|
static GetFromTermResult
|
||||||
get_background_color_from_term (ShellThemeNode *node,
|
get_background_color_from_term (ShellThemeNode *node,
|
||||||
CRTerm *term,
|
CRTerm *term,
|
||||||
@ -1150,7 +1259,7 @@ shell_theme_node_get_border_color (ShellThemeNode *node,
|
|||||||
ClutterColor *color)
|
ClutterColor *color)
|
||||||
{
|
{
|
||||||
g_return_if_fail (SHELL_IS_THEME_NODE (node));
|
g_return_if_fail (SHELL_IS_THEME_NODE (node));
|
||||||
g_return_if_fail (side >= SHELL_SIDE_LEFT && side <= SHELL_SIDE_BOTTOM);
|
g_return_if_fail (side >= SHELL_SIDE_TOP && side <= SHELL_SIDE_LEFT);
|
||||||
|
|
||||||
ensure_borders (node);
|
ensure_borders (node);
|
||||||
|
|
||||||
@ -1162,7 +1271,7 @@ shell_theme_node_get_padding (ShellThemeNode *node,
|
|||||||
ShellSide side)
|
ShellSide side)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (SHELL_IS_THEME_NODE (node), 0.);
|
g_return_val_if_fail (SHELL_IS_THEME_NODE (node), 0.);
|
||||||
g_return_val_if_fail (side >= SHELL_SIDE_LEFT && side <= SHELL_SIDE_BOTTOM, 0.);
|
g_return_val_if_fail (side >= SHELL_SIDE_TOP && side <= SHELL_SIDE_LEFT, 0.);
|
||||||
|
|
||||||
ensure_borders (node);
|
ensure_borders (node);
|
||||||
|
|
||||||
|
@ -21,12 +21,19 @@ typedef struct _ShellThemeNodeClass ShellThemeNodeClass;
|
|||||||
#define SHELL_THEME_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_THEME_NODE, ShellThemeNodeClass))
|
#define SHELL_THEME_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_THEME_NODE, ShellThemeNodeClass))
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SHELL_SIDE_LEFT,
|
|
||||||
SHELL_SIDE_RIGHT,
|
|
||||||
SHELL_SIDE_TOP,
|
SHELL_SIDE_TOP,
|
||||||
SHELL_SIDE_BOTTOM
|
SHELL_SIDE_RIGHT,
|
||||||
|
SHELL_SIDE_BOTTOM,
|
||||||
|
SHELL_SIDE_LEFT
|
||||||
} ShellSide;
|
} ShellSide;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SHELL_CORNER_TOPLEFT,
|
||||||
|
SHELL_CORNER_TOPRIGHT,
|
||||||
|
SHELL_CORNER_BOTTOMRIGHT,
|
||||||
|
SHELL_CORNER_BOTTOMLEFT
|
||||||
|
} ShellCorner;
|
||||||
|
|
||||||
/* These are the CSS values; that doesn't mean we have to implement blink... */
|
/* These are the CSS values; that doesn't mean we have to implement blink... */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SHELL_TEXT_DECORATION_UNDERLINE = 1 << 0,
|
SHELL_TEXT_DECORATION_UNDERLINE = 1 << 0,
|
||||||
@ -89,11 +96,14 @@ void shell_theme_node_get_foreground_color (ShellThemeNode *node,
|
|||||||
|
|
||||||
const char *shell_theme_node_get_background_image (ShellThemeNode *node);
|
const char *shell_theme_node_get_background_image (ShellThemeNode *node);
|
||||||
|
|
||||||
double shell_theme_node_get_border_width (ShellThemeNode *node,
|
double shell_theme_node_get_border_width (ShellThemeNode *node,
|
||||||
ShellSide side);
|
ShellSide side);
|
||||||
void shell_theme_node_get_border_color (ShellThemeNode *node,
|
double shell_theme_node_get_border_radius (ShellThemeNode *node,
|
||||||
|
ShellCorner corner);
|
||||||
|
void shell_theme_node_get_border_color (ShellThemeNode *node,
|
||||||
ShellSide side,
|
ShellSide side,
|
||||||
ClutterColor *color);
|
ClutterColor *color);
|
||||||
|
|
||||||
double shell_theme_node_get_padding (ShellThemeNode *node,
|
double shell_theme_node_get_padding (ShellThemeNode *node,
|
||||||
ShellSide side);
|
ShellSide side);
|
||||||
|
|
||||||
|
@ -112,6 +112,42 @@ assert_background_color (ShellThemeNode *node,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
side_to_string (ShellSide side)
|
||||||
|
{
|
||||||
|
switch (side)
|
||||||
|
{
|
||||||
|
case SHELL_SIDE_TOP:
|
||||||
|
return "top";
|
||||||
|
case SHELL_SIDE_RIGHT:
|
||||||
|
return "right";
|
||||||
|
case SHELL_SIDE_BOTTOM:
|
||||||
|
return "bottom";
|
||||||
|
case SHELL_SIDE_LEFT:
|
||||||
|
return "left";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "<unknown>";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
assert_border_color (ShellThemeNode *node,
|
||||||
|
const char *node_description,
|
||||||
|
ShellSide side,
|
||||||
|
guint32 expected)
|
||||||
|
{
|
||||||
|
ClutterColor color;
|
||||||
|
shell_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
|
static void
|
||||||
assert_background_image (ShellThemeNode *node,
|
assert_background_image (ShellThemeNode *node,
|
||||||
const char *node_description,
|
const char *node_description,
|
||||||
@ -222,6 +258,40 @@ test_padding (void)
|
|||||||
shell_theme_node_get_padding (group2, SHELL_SIDE_LEFT));
|
shell_theme_node_get_padding (group2, SHELL_SIDE_LEFT));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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.,
|
||||||
|
shell_theme_node_get_border_width (group2, SHELL_SIDE_TOP));
|
||||||
|
assert_length ("group2", "border-right-width", 2.,
|
||||||
|
shell_theme_node_get_border_width (group2, SHELL_SIDE_RIGHT));
|
||||||
|
assert_length ("group2", "border-bottom-width", 5.,
|
||||||
|
shell_theme_node_get_border_width (group2, SHELL_SIDE_BOTTOM));
|
||||||
|
assert_length ("group2", "border-left-width", 2.,
|
||||||
|
shell_theme_node_get_border_width (group2, SHELL_SIDE_LEFT));
|
||||||
|
|
||||||
|
assert_border_color (group2, "group2", SHELL_SIDE_TOP, 0x000000ff);
|
||||||
|
assert_border_color (group2, "group2", SHELL_SIDE_RIGHT, 0x000000ff);
|
||||||
|
assert_border_color (group2, "group2", SHELL_SIDE_BOTTOM, 0x0000ffff);
|
||||||
|
assert_border_color (group2, "group2", SHELL_SIDE_LEFT, 0x000000ff);
|
||||||
|
|
||||||
|
assert_length ("group2", "border-radius-topleft", 10.,
|
||||||
|
shell_theme_node_get_border_radius (group2, SHELL_CORNER_TOPLEFT));
|
||||||
|
assert_length ("group2", "border-radius-topright", 10.,
|
||||||
|
shell_theme_node_get_border_radius (group2, SHELL_CORNER_TOPRIGHT));
|
||||||
|
assert_length ("group2", "border-radius-bottomright", 0.,
|
||||||
|
shell_theme_node_get_border_radius (group2, SHELL_CORNER_BOTTOMRIGHT));
|
||||||
|
assert_length ("group2", "border-radius-bottomleft", 0.,
|
||||||
|
shell_theme_node_get_border_radius (group2, SHELL_CORNER_BOTTOMLEFT));
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_background (void)
|
test_background (void)
|
||||||
{
|
{
|
||||||
@ -312,6 +382,7 @@ main (int argc, char **argv)
|
|||||||
test_type_inheritance ();
|
test_type_inheritance ();
|
||||||
test_adjacent_selector ();
|
test_adjacent_selector ();
|
||||||
test_padding ();
|
test_padding ();
|
||||||
|
test_border ();
|
||||||
test_background ();
|
test_background ();
|
||||||
test_font ();
|
test_font ();
|
||||||
test_pseudo_class ();
|
test_pseudo_class ();
|
||||||
|
@ -58,6 +58,10 @@ stage > #text2 {
|
|||||||
#group2 {
|
#group2 {
|
||||||
background-image: url('other-background.png');
|
background-image: url('other-background.png');
|
||||||
padding: 1px 2px 3px 4px;
|
padding: 1px 2px 3px 4px;
|
||||||
|
|
||||||
|
border: 2px solid #000000;
|
||||||
|
border-bottom: 5px solid #0000ff;
|
||||||
|
border-radius: 10px 10px 0px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClutterText:hover {
|
ClutterText:hover {
|
||||||
|
Loading…
Reference in New Issue
Block a user