[gnome-shell] [StThemeNode] implement CSS "outline" property
- From: Dan Winship <danw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] [StThemeNode] implement CSS "outline" property
- Date: Thu, 17 Jun 2010 18:07:34 +0000 (UTC)
commit cae61e62fdc469b97f3df373b6d3bda78c61a86f
Author: Dan Winship <danw gnome org>
Date: Wed May 26 16:50:24 2010 -0400
[StThemeNode] implement CSS "outline" property
Could potentially be used for focus indication
https://bugzilla.gnome.org/show_bug.cgi?id=621669
src/st/st-theme-node-drawing.c | 50 +++++++++++++
src/st/st-theme-node-private.h | 2 +
src/st/st-theme-node.c | 155 +++++++++++++++++++++++++++++++++++-----
src/st/st-theme-node.h | 4 +
4 files changed, 194 insertions(+), 17 deletions(-)
---
diff --git a/src/st/st-theme-node-drawing.c b/src/st/st-theme-node-drawing.c
index f55174f..46d9de7 100644
--- a/src/st/st-theme-node-drawing.c
+++ b/src/st/st-theme-node-drawing.c
@@ -1054,6 +1054,54 @@ st_theme_node_paint_sliced_border_image (StThemeNode *node,
cogl_handle_unref (material);
}
+static void
+st_theme_node_paint_outline (StThemeNode *node,
+ const ClutterActorBox *box,
+ guint8 paint_opacity)
+
+{
+ float width, height;
+ int outline_width;
+ ClutterColor outline_color, effective_outline;
+
+ width = box->x2 - box->x1;
+ height = box->y2 - box->y1;
+
+ outline_width = st_theme_node_get_outline_width (node);
+ if (outline_width == 0)
+ return;
+
+ st_theme_node_get_outline_color (node, &outline_color);
+ over (&outline_color, &node->background_color, &effective_outline);
+
+ cogl_set_source_color4ub (effective_outline.red,
+ effective_outline.green,
+ effective_outline.blue,
+ paint_opacity * effective_outline.alpha / 255);
+
+ /* The outline is drawn just outside the border, which means just
+ * outside the allocation box. This means that in some situations
+ * involving clip_to_allocation or the screen edges, you won't be
+ * able to see the outline. In practice, it works well enough.
+ */
+
+ /* NORTH */
+ cogl_rectangle (-outline_width, -outline_width,
+ width + outline_width, 0);
+
+ /* EAST */
+ cogl_rectangle (width, 0,
+ width + outline_width, height);
+
+ /* SOUTH */
+ cogl_rectangle (-outline_width, height,
+ width + outline_width, height + outline_width);
+
+ /* WEST */
+ cogl_rectangle (-outline_width, 0,
+ 0, height);
+}
+
void
st_theme_node_paint (StThemeNode *node,
const ClutterActorBox *box,
@@ -1121,6 +1169,8 @@ st_theme_node_paint (StThemeNode *node,
else
st_theme_node_paint_borders (node, box, paint_opacity);
+ st_theme_node_paint_outline (node, box, paint_opacity);
+
if (node->background_texture != COGL_INVALID_HANDLE)
{
ClutterActorBox background_box;
diff --git a/src/st/st-theme-node-private.h b/src/st/st-theme-node-private.h
index 1f9d1c3..4641df3 100644
--- a/src/st/st-theme-node-private.h
+++ b/src/st/st-theme-node-private.h
@@ -24,9 +24,11 @@ struct _StThemeNode {
ClutterColor foreground_color;
ClutterColor border_color[4];
+ ClutterColor outline_color;
int border_width[4];
int border_radius[4];
+ int outline_width;
guint padding[4];
int width;
diff --git a/src/st/st-theme-node.c b/src/st/st-theme-node.c
index d097da5..639c566 100644
--- a/src/st/st-theme-node.c
+++ b/src/st/st-theme-node.c
@@ -943,7 +943,7 @@ do_border_property (StThemeNode *node,
if (strcmp (property_name, "") == 0)
{
- /* Set value for width/color/node in any order */
+ /* Set value for width/color/style in any order */
CRTerm *term;
for (term = decl->value; term; term = term->next)
@@ -965,7 +965,6 @@ do_border_property (StThemeNode *node,
}
else if (strcmp (ident, "dotted") == 0 ||
strcmp (ident, "dashed") == 0 ||
- strcmp (ident, "solid") == 0 ||
strcmp (ident, "double") == 0 ||
strcmp (ident, "groove") == 0 ||
strcmp (ident, "ridge") == 0 ||
@@ -1037,6 +1036,97 @@ do_border_property (StThemeNode *node,
}
static void
+do_outline_property (StThemeNode *node,
+ CRDeclaration *decl)
+{
+ const char *property_name = decl->property->stryng->str + 7; /* Skip 'outline' */
+ ClutterColor color;
+ gboolean color_set = FALSE;
+ int width;
+ gboolean width_set = FALSE;
+
+ if (strcmp (property_name, "") == 0)
+ {
+ /* Set value for width/color/style in any order */
+ CRTerm *term;
+
+ for (term = decl->value; term; term = term->next)
+ {
+ GetFromTermResult result;
+
+ if (term->type == TERM_IDENT)
+ {
+ const char *ident = term->content.str->stryng->str;
+ if (strcmp (ident, "none") == 0 || strcmp (ident, "hidden") == 0)
+ {
+ width = 0.;
+ continue;
+ }
+ else if (strcmp (ident, "solid") == 0)
+ {
+ /* The only thing we support */
+ continue;
+ }
+ else if (strcmp (ident, "dotted") == 0 ||
+ strcmp (ident, "dashed") == 0 ||
+ strcmp (ident, "double") == 0 ||
+ strcmp (ident, "groove") == 0 ||
+ strcmp (ident, "ridge") == 0 ||
+ strcmp (ident, "inset") == 0 ||
+ strcmp (ident, "outset") == 0)
+ {
+ /* Treat the same as solid */
+ continue;
+ }
+
+ /* Presumably a color, fall through */
+ }
+
+ if (term->type == TERM_NUMBER)
+ {
+ result = get_length_from_term_int (node, term, FALSE, &width);
+ if (result != VALUE_NOT_FOUND)
+ {
+ width_set = result == VALUE_FOUND;
+ continue;
+ }
+ }
+
+ result = get_color_from_term (node, term, &color);
+ if (result != VALUE_NOT_FOUND)
+ {
+ color_set = result == VALUE_FOUND;
+ continue;
+ }
+ }
+
+ }
+ else if (strcmp (property_name, "-color") == 0)
+ {
+ if (decl->value == NULL || decl->value->next != NULL)
+ return;
+
+ if (get_color_from_term (node, decl->value, &color) == VALUE_FOUND)
+ /* Ignore inherit */
+ color_set = TRUE;
+ }
+ else if (strcmp (property_name, "-width") == 0)
+ {
+ if (decl->value == NULL || decl->value->next != NULL)
+ return;
+
+ if (get_length_from_term_int (node, decl->value, FALSE, &width) == VALUE_FOUND)
+ /* Ignore inherit */
+ width_set = TRUE;
+ }
+
+ if (color_set)
+ node->outline_color = color;
+ if (width_set)
+ node->outline_width = width;
+}
+
+static void
do_padding_property_term (StThemeNode *node,
CRTerm *term,
gboolean left,
@@ -1144,6 +1234,9 @@ _st_theme_node_ensure_geometry (StThemeNode *node)
node->border_color[j] = TRANSPARENT_COLOR;
}
+ node->outline_width = 0;
+ node->outline_color = TRANSPARENT_COLOR;
+
node->width = -1;
node->height = -1;
node->min_width = -1;
@@ -1158,6 +1251,8 @@ _st_theme_node_ensure_geometry (StThemeNode *node)
if (g_str_has_prefix (property_name, "border"))
do_border_property (node, decl);
+ else if (g_str_has_prefix (property_name, "outline"))
+ do_outline_property (node, decl);
else if (g_str_has_prefix (property_name, "padding"))
do_padding_property (node, decl);
else if (strcmp (property_name, "width") == 0)
@@ -1224,6 +1319,27 @@ st_theme_node_get_border_radius (StThemeNode *node,
}
int
+st_theme_node_get_outline_width (StThemeNode *node)
+{
+ g_return_val_if_fail (ST_IS_THEME_NODE (node), 0);
+
+ _st_theme_node_ensure_geometry (node);
+
+ return node->outline_width;
+}
+
+void
+st_theme_node_get_outline_color (StThemeNode *node,
+ ClutterColor *color)
+{
+ g_return_if_fail (ST_IS_THEME_NODE (node));
+
+ _st_theme_node_ensure_geometry (node);
+
+ *color = node->outline_color;
+}
+
+int
st_theme_node_get_width (StThemeNode *node)
{
g_return_val_if_fail (ST_IS_THEME_NODE (node), -1);
@@ -2539,13 +2655,13 @@ st_theme_node_get_content_box (StThemeNode *node,
/**
* st_theme_node_get_paint_box:
* @node: a #StThemeNode
- * @allocation: the box allocated to a #ClutterAlctor
+ * @allocation: the box allocated to a #ClutterActor
* @paint_box: computed box occupied when painting the actor
*
- * Gets the box used to paint the actor, including the area occupied by
- * properties which paint outside the actor's assigned allocation
- * (currently only st-shadow). When painting @node to an offscreen buffer,
- * this function can be used to determine the necessary size of the buffer.
+ * Gets the box used to paint the actor, including the area occupied
+ * by properties which paint outside the actor's assigned allocation.
+ * When painting @node to an offscreen buffer, this function can be
+ * used to determine the necessary size of the buffer.
*/
void
st_theme_node_get_paint_box (StThemeNode *node,
@@ -2553,25 +2669,30 @@ st_theme_node_get_paint_box (StThemeNode *node,
ClutterActorBox *paint_box)
{
StShadow *shadow;
+ ClutterActorBox shadow_box;
+ int outline_width;
g_return_if_fail (ST_IS_THEME_NODE (node));
g_return_if_fail (actor_box != NULL);
g_return_if_fail (paint_box != NULL);
shadow = st_theme_node_get_shadow (node);
- if (shadow)
+ outline_width = st_theme_node_get_outline_width (node);
+ if (!shadow && !outline_width)
{
- ClutterActorBox shadow_box;
-
- st_shadow_get_box (shadow, actor_box, &shadow_box);
-
- paint_box->x1 = MIN (actor_box->x1, shadow_box.x1);
- paint_box->x2 = MAX (actor_box->x2, shadow_box.x2);
- paint_box->y1 = MIN (actor_box->y1, shadow_box.y1);
- paint_box->y2 = MAX (actor_box->y2, shadow_box.y2);
+ *paint_box = *actor_box;
+ return;
}
+
+ if (shadow)
+ st_shadow_get_box (shadow, actor_box, &shadow_box);
else
- *paint_box = *actor_box;
+ shadow_box = *actor_box;
+
+ paint_box->x1 = MIN (actor_box->x1 - outline_width, shadow_box.x1);
+ paint_box->x2 = MAX (actor_box->x2 + outline_width, shadow_box.x2);
+ paint_box->y1 = MIN (actor_box->y1 - outline_width, shadow_box.y1);
+ paint_box->y2 = MAX (actor_box->y2 + outline_width, shadow_box.y2);
}
diff --git a/src/st/st-theme-node.h b/src/st/st-theme-node.h
index 2dfa2b2..dadff59 100644
--- a/src/st/st-theme-node.h
+++ b/src/st/st-theme-node.h
@@ -128,6 +128,10 @@ void st_theme_node_get_border_color (StThemeNode *node,
StSide side,
ClutterColor *color);
+int st_theme_node_get_outline_width (StThemeNode *node);
+void st_theme_node_get_outline_color (StThemeNode *node,
+ ClutterColor *color);
+
double st_theme_node_get_padding (StThemeNode *node,
StSide side);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]