[gnome-shell] [StThemeNode] implement CSS "outline" property



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]