[gnome-shell] Implement non-uniform borders (when not using corner_radius)
- From: Colin Walters <walters src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-shell] Implement non-uniform borders (when not using corner_radius)
- Date: Wed, 4 Nov 2009 21:48:13 +0000 (UTC)
commit 4f456b968959669ce299ffcb6deee47cd0dda00d
Author: Colin Walters <walters verbum org>
Date: Wed Oct 28 12:53:26 2009 -0400
Implement non-uniform borders (when not using corner_radius)
StTheme CSS supports different border widths for different sides. Implement
it for StWidget by drawing the border internally. However, we don't support
a nonzero corner-radius with nonuniform borders.
https://bugzilla.gnome.org/show_bug.cgi?id=599442
src/st/st-widget.c | 178 ++++++++++++++++++++++++++++++++++++++++------------
1 files changed, 138 insertions(+), 40 deletions(-)
---
diff --git a/src/st/st-widget.c b/src/st/st-widget.c
index c2488ec..d606497 100644
--- a/src/st/st-widget.c
+++ b/src/st/st-widget.c
@@ -63,6 +63,7 @@ struct _StWidgetPrivate
gboolean has_tooltip : 1;
gboolean is_style_dirty : 1;
gboolean draw_bg_color : 1;
+ gboolean draw_border_internal : 1;
StTooltip *tooltip;
};
@@ -356,25 +357,25 @@ static void
st_widget_real_draw_background (StWidget *self)
{
StWidgetPrivate *priv = self->priv;
+ ClutterActor *actor = CLUTTER_ACTOR (self);
+ ClutterActorBox allocation = { 0, };
+ gfloat w, h;
+ guint8 opacity;
+
+ clutter_actor_get_allocation_box (actor, &allocation);
+ w = allocation.x2 - allocation.x1;
+ h = allocation.y2 - allocation.y1;
+
+ opacity = clutter_actor_get_paint_opacity (actor);
/* Default implementation just draws the background
* colour and the image on top
*/
if (priv->draw_bg_color)
{
- ClutterActor *actor = CLUTTER_ACTOR (self);
- ClutterActorBox allocation = { 0, };
ClutterColor bg_color = priv->bg_color;
- gfloat w, h;
- bg_color.alpha = clutter_actor_get_paint_opacity (actor)
- * bg_color.alpha
- / 255;
-
- clutter_actor_get_allocation_box (actor, &allocation);
-
- w = allocation.x2 - allocation.x1;
- h = allocation.y2 - allocation.y1;
+ bg_color.alpha = opacity * bg_color.alpha / 255;
cogl_set_source_color4ub (bg_color.red,
bg_color.green,
@@ -383,6 +384,76 @@ st_widget_real_draw_background (StWidget *self)
cogl_rectangle (0, 0, w, h);
}
+ if (priv->draw_border_internal)
+ {
+ StThemeNode *node = st_widget_get_theme_node (self);
+ int side;
+ double border_top, border_right, border_bottom, border_left;
+
+ border_top = st_theme_node_get_border_width (node, ST_SIDE_TOP);
+ border_right = st_theme_node_get_border_width (node, ST_SIDE_RIGHT);
+ border_bottom = st_theme_node_get_border_width (node, ST_SIDE_BOTTOM);
+ border_left = st_theme_node_get_border_width (node, ST_SIDE_LEFT);
+
+ for (side = 0; side < 4; side++)
+ {
+ ClutterColor color;
+
+ switch (side)
+ {
+ case ST_SIDE_TOP:
+ if (border_top <= 0)
+ continue;
+ break;
+ case ST_SIDE_RIGHT:
+ if (border_right <= 0)
+ continue;
+ break;
+ case ST_SIDE_BOTTOM:
+ if (border_bottom <= 0)
+ continue;
+ break;
+ case ST_SIDE_LEFT:
+ if (border_left <= 0)
+ continue;
+ break;
+ }
+
+ st_theme_node_get_border_color (node, side, &color);
+
+ color.alpha = (color.alpha * opacity) / 0xff;
+
+ cogl_set_source_color4ub (color.red,
+ color.green,
+ color.blue,
+ color.alpha);
+
+ /* Note top and bottom extend to the ends, left/right
+ * are constrained by them. See comment above about CSS
+ * conformance.
+ */
+ switch (side)
+ {
+ case ST_SIDE_TOP:
+ cogl_rectangle (0, 0,
+ w, border_top);
+ break;
+ case ST_SIDE_RIGHT:
+ cogl_rectangle (w - border_right, border_top,
+ w, h - border_bottom);
+ break;
+ case ST_SIDE_BOTTOM:
+ cogl_rectangle (0, h - border_bottom,
+ w, h);
+ break;
+ case ST_SIDE_LEFT:
+ cogl_rectangle (0, border_top,
+ border_left, h - border_bottom);
+ break;
+ }
+ }
+ }
+
if (priv->border_image)
clutter_actor_paint (priv->border_image);
}
@@ -491,6 +562,7 @@ st_widget_real_style_changed (StWidget *self)
ClutterColor border_color = { 0, };
StSide side;
StCorner corner;
+ gboolean uniform_border_width;
/* application has request this widget is not stylable */
if (!priv->is_stylable)
@@ -520,33 +592,6 @@ st_widget_real_style_changed (StWidget *self)
texture_cache = st_texture_cache_get_default ();
- /* StThemeNode supports different widths and colors for different sides
- * of the border, and different radii for the different corners. We take
- * the different border widths into account when positioning, but our current
- * drawing code (using BigRectangle) can only handle a single width, color,
- * and radius, so we arbitrarily pick the first non-zero width and radius,
- * and use that.
- */
- for (side = ST_SIDE_TOP; side <= ST_SIDE_LEFT; side++)
- {
- double width = st_theme_node_get_border_width (theme_node, side);
- if (width > 0.5)
- {
- border_width = (int)(0.5 + width);
- st_theme_node_get_border_color (theme_node, side, &border_color);
- break;
- }
- }
-
- for (corner = ST_CORNER_TOPLEFT; corner <= ST_CORNER_BOTTOMLEFT; corner++)
- {
- double radius = st_theme_node_get_border_radius (theme_node, corner);
- if (radius > 0.5)
- {
- border_radius = (int)(0.5 + radius);
- break;
- }
- }
/* Rough notes about the relationship of borders and backgrounds in CSS3;
* see http://www.w3.org/TR/css3-background/ for more accurate details.
@@ -565,6 +610,8 @@ st_widget_real_style_changed (StWidget *self)
* zero width or a border image is being used.
*
* Deviations from the above as implemented here:
+ * - Nonuniform border widths combined with a non-zero border radius result
+ * in the border radius being ignored
* - The combination of border image and a non-zero border radius is
* not supported; the background color will be drawn with square
* corners.
@@ -576,6 +623,44 @@ st_widget_real_style_changed (StWidget *self)
* and a single background image above it.
*/
+ /* Check whether all border widths are the same. Also, acquire the
+ * first nonzero border width as well as the border color.
+ */
+ uniform_border_width = TRUE;
+ border_width = st_theme_node_get_border_width (theme_node, ST_SIDE_TOP);
+ if (border_width > 0.5)
+ border_width = (int)(0.5 + border_width);
+ for (side = 0; side < 4; side++)
+ {
+ double width = st_theme_node_get_border_width (theme_node, side);
+ if (width > 0.5)
+ width = (int)(0.5 + width);
+ if (width > 0)
+ {
+ border_width = width;
+ st_theme_node_get_border_color (theme_node, side, &border_color);
+ }
+ if ((int)width != border_width)
+ {
+ uniform_border_width = FALSE;
+ break;
+ }
+ }
+
+ /* Pick the first nonzero border radius, but only if we have a uniform border. */
+ if (uniform_border_width)
+ {
+ for (corner = 0; corner < 4; corner++)
+ {
+ double radius = st_theme_node_get_border_radius (theme_node, corner);
+ if (radius > 0.5)
+ {
+ border_radius = (int)(0.5 + radius);
+ break;
+ }
+ }
+ }
+
border_image = st_theme_node_get_border_image (theme_node);
if (border_image)
{
@@ -607,9 +692,9 @@ st_widget_real_style_changed (StWidget *self)
has_changed = TRUE;
relayout_needed = TRUE;
}
- else if ((border_width > 0 && border_color.alpha != 0) ||
- (border_radius > 0 && priv->bg_color.alpha != 0))
+ else if (border_radius > 0)
{
+ priv->draw_border_internal = FALSE;
priv->draw_bg_color = FALSE;
priv->border_image = g_object_new (BIG_TYPE_RECTANGLE,
"color", &priv->bg_color,
@@ -623,6 +708,19 @@ st_widget_real_style_changed (StWidget *self)
has_changed = TRUE;
relayout_needed = TRUE;
}
+ else if (border_width > 0 && border_color.alpha != 0)
+ {
+ priv->draw_bg_color = TRUE;
+ priv->draw_border_internal = TRUE;
+ has_changed = TRUE;
+ relayout_needed = TRUE;
+ }
+ else if (priv->draw_border_internal)
+ {
+ priv->draw_border_internal = FALSE;
+ has_changed = TRUE;
+ relayout_needed = TRUE;
+ }
bg_file = st_theme_node_get_background_image (theme_node);
if (bg_file != NULL)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]