[gnome-shell] St: Implement CSS3 specification for reducing border-radius
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] St: Implement CSS3 specification for reducing border-radius
- Date: Sat, 9 Jul 2011 22:05:32 +0000 (UTC)
commit ee4ae6294627f947a1ef5aece7f21a52e2be0e20
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Thu May 5 16:57:10 2011 -0400
St: Implement CSS3 specification for reducing border-radius
Currently, any cases of overlapping corners were just ignored and rendered incorrectly.
Implement the corner overlap algorithm as specified by the W3C to fix this.
https://bugzilla.gnome.org/show_bug.cgi?id=649513
src/st/st-theme-node-drawing.c | 119 +++++++++++++++++++++++++++++-----------
1 files changed, 87 insertions(+), 32 deletions(-)
---
diff --git a/src/st/st-theme-node-drawing.c b/src/st/st-theme-node-drawing.c
index b47032d..fdef350 100644
--- a/src/st/st-theme-node-drawing.c
+++ b/src/st/st-theme-node-drawing.c
@@ -257,6 +257,57 @@ over (const ClutterColor *source,
unpremultiply (result);
}
+/*
+ * st_theme_node_reduce_border_radius:
+ * @node: a #StThemeNode
+ * @corners: (array length=4) (out): reduced corners
+ *
+ * Implements the corner overlap algorithm mentioned at
+ * http://www.w3.org/TR/css3-background/#corner-overlap
+ */
+static void
+st_theme_node_reduce_border_radius (StThemeNode *node,
+ guint *corners)
+{
+ gfloat scale;
+ guint sum;
+
+ scale = 1.0;
+
+ /* top */
+ sum = node->border_radius[ST_CORNER_TOPLEFT]
+ + node->border_radius[ST_CORNER_TOPRIGHT];
+
+ if (sum > 0)
+ scale = MIN (node->alloc_width / sum, scale);
+
+ /* right */
+ sum = node->border_radius[ST_CORNER_TOPRIGHT]
+ + node->border_radius[ST_CORNER_BOTTOMRIGHT];
+
+ if (sum > 0)
+ scale = MIN (node->alloc_height / sum, scale);
+
+ /* bottom */
+ sum = node->border_radius[ST_CORNER_BOTTOMLEFT]
+ + node->border_radius[ST_CORNER_BOTTOMRIGHT];
+
+ if (sum > 0)
+ scale = MIN (node->alloc_width / sum, scale);
+
+ /* left */
+ sum = node->border_radius[ST_CORNER_BOTTOMLEFT]
+ + node->border_radius[ST_CORNER_TOPLEFT];
+
+ if (sum > 0)
+ scale = MIN (node->alloc_height / sum, scale);
+
+ corners[ST_CORNER_TOPLEFT] = node->border_radius[ST_CORNER_TOPLEFT] * scale;
+ corners[ST_CORNER_TOPRIGHT] = node->border_radius[ST_CORNER_TOPRIGHT] * scale;
+ corners[ST_CORNER_BOTTOMLEFT] = node->border_radius[ST_CORNER_BOTTOMLEFT] * scale;
+ corners[ST_CORNER_BOTTOMRIGHT] = node->border_radius[ST_CORNER_BOTTOMRIGHT] * scale;
+}
+
static void
st_theme_node_get_corner_border_widths (StThemeNode *node,
StCorner corner_id,
@@ -301,13 +352,15 @@ st_theme_node_lookup_corner (StThemeNode *node,
StTextureCache *cache;
StCornerSpec corner;
LoadCornerData data;
+ guint radius[4];
if (node->border_radius[corner_id] == 0)
return COGL_INVALID_HANDLE;
cache = st_texture_cache_get_default ();
- corner.radius = node->border_radius[corner_id];
+ st_theme_node_reduce_border_radius (node, radius);
+ corner.radius = radius[corner_id];
corner.color = node->background_color;
st_theme_node_get_corner_border_widths (node, corner_id,
&corner.border_width_1,
@@ -877,7 +930,8 @@ st_theme_node_prerender_background (StThemeNode *node)
{
StBorderImage *border_image;
CoglHandle texture;
- int radius[4], i;
+ guint radius[4];
+ int i;
cairo_t *cr;
cairo_surface_t *surface;
StShadow *shadow_spec;
@@ -944,12 +998,10 @@ st_theme_node_prerender_background (StThemeNode *node)
/* TODO - support non-uniform border colors */
get_arbitrary_border_color (node, &border_color);
- for (i = 0; i < 4; i++)
- {
- border_width[i] = st_theme_node_get_border_width (node, i);
+ st_theme_node_reduce_border_radius (node, radius);
- radius[i] = st_theme_node_get_border_radius (node, i);
- }
+ for (i = 0; i < 4; i++)
+ border_width[i] = st_theme_node_get_border_width (node, i);
/* Note we don't support translucent background images on top
* of gradients. It's strictly either/or.
@@ -1457,6 +1509,7 @@ st_theme_node_paint_borders (StThemeNode *node,
{
float width, height;
int border_width[4];
+ guint border_radius[4];
int max_border_radius = 0;
int max_width_radius[4];
int corner_id, side_id;
@@ -1472,6 +1525,8 @@ st_theme_node_paint_borders (StThemeNode *node,
for (side_id = 0; side_id < 4; side_id++)
border_width[side_id] = st_theme_node_get_border_width(node, side_id);
+ st_theme_node_reduce_border_radius (node, border_radius);
+
for (corner_id = 0; corner_id < 4; corner_id++)
{
guint border_width_1, border_width_2;
@@ -1479,10 +1534,10 @@ st_theme_node_paint_borders (StThemeNode *node,
st_theme_node_get_corner_border_widths (node, corner_id,
&border_width_1, &border_width_2);
- if (node->border_radius[corner_id] > max_border_radius)
- max_border_radius = node->border_radius[corner_id];
+ if (border_radius[corner_id] > max_border_radius)
+ max_border_radius = border_radius[corner_id];
max_width_radius[corner_id] = MAX(MAX(border_width_1, border_width_2),
- node->border_radius[corner_id]);
+ border_radius[corner_id]);
}
/* borders */
@@ -1506,8 +1561,8 @@ st_theme_node_paint_borders (StThemeNode *node,
alpha);
/* NORTH */
- skip_corner_1 = node->border_radius[ST_CORNER_TOPLEFT] > 0;
- skip_corner_2 = node->border_radius[ST_CORNER_TOPRIGHT] > 0;
+ skip_corner_1 = border_radius[ST_CORNER_TOPLEFT] > 0;
+ skip_corner_2 = border_radius[ST_CORNER_TOPRIGHT] > 0;
x1 = skip_corner_1 ? max_width_radius[ST_CORNER_TOPLEFT] : 0;
y1 = 0;
@@ -1516,8 +1571,8 @@ st_theme_node_paint_borders (StThemeNode *node,
cogl_rectangle (x1, y1, x2, y2);
/* EAST */
- skip_corner_1 = node->border_radius[ST_CORNER_TOPRIGHT] > 0;
- skip_corner_2 = node->border_radius[ST_CORNER_BOTTOMRIGHT] > 0;
+ skip_corner_1 = border_radius[ST_CORNER_TOPRIGHT] > 0;
+ skip_corner_2 = border_radius[ST_CORNER_BOTTOMRIGHT] > 0;
x1 = width - border_width[ST_SIDE_RIGHT];
y1 = skip_corner_1 ? max_width_radius[ST_CORNER_TOPRIGHT]
@@ -1528,8 +1583,8 @@ st_theme_node_paint_borders (StThemeNode *node,
cogl_rectangle (x1, y1, x2, y2);
/* SOUTH */
- skip_corner_1 = node->border_radius[ST_CORNER_BOTTOMLEFT] > 0;
- skip_corner_2 = node->border_radius[ST_CORNER_BOTTOMRIGHT] > 0;
+ skip_corner_1 = border_radius[ST_CORNER_BOTTOMLEFT] > 0;
+ skip_corner_2 = border_radius[ST_CORNER_BOTTOMRIGHT] > 0;
x1 = skip_corner_1 ? max_width_radius[ST_CORNER_BOTTOMLEFT] : 0;
y1 = height - border_width[ST_SIDE_BOTTOM];
@@ -1539,8 +1594,8 @@ st_theme_node_paint_borders (StThemeNode *node,
cogl_rectangle (x1, y1, x2, y2);
/* WEST */
- skip_corner_1 = node->border_radius[ST_CORNER_TOPLEFT] > 0;
- skip_corner_2 = node->border_radius[ST_CORNER_BOTTOMLEFT] > 0;
+ skip_corner_1 = border_radius[ST_CORNER_TOPLEFT] > 0;
+ skip_corner_2 = border_radius[ST_CORNER_BOTTOMLEFT] > 0;
x1 = 0;
y1 = skip_corner_1 ? max_width_radius[ST_CORNER_TOPLEFT]
@@ -1610,32 +1665,32 @@ st_theme_node_paint_borders (StThemeNode *node,
int n_rects;
/* corner texture does not need padding */
- if (max_border_radius == node->border_radius[corner_id])
+ if (max_border_radius == border_radius[corner_id])
continue;
- n_rects = node->border_radius[corner_id] == 0 ? 1 : 2;
+ n_rects = border_radius[corner_id] == 0 ? 1 : 2;
switch (corner_id)
{
case ST_CORNER_TOPLEFT:
verts[0] = border_width[ST_SIDE_LEFT];
- verts[1] = MAX(node->border_radius[corner_id],
+ verts[1] = MAX(border_radius[corner_id],
border_width[ST_SIDE_TOP]);
verts[2] = max_border_radius;
verts[3] = max_border_radius;
if (n_rects == 2)
{
- verts[4] = MAX(node->border_radius[corner_id],
+ verts[4] = MAX(border_radius[corner_id],
border_width[ST_SIDE_LEFT]);
verts[5] = border_width[ST_SIDE_TOP];
verts[6] = max_border_radius;
- verts[7] = MAX(node->border_radius[corner_id],
+ verts[7] = MAX(border_radius[corner_id],
border_width[ST_SIDE_TOP]);
}
break;
case ST_CORNER_TOPRIGHT:
verts[0] = width - max_border_radius;
- verts[1] = MAX(node->border_radius[corner_id],
+ verts[1] = MAX(border_radius[corner_id],
border_width[ST_SIDE_TOP]);
verts[2] = width - border_width[ST_SIDE_RIGHT];
verts[3] = max_border_radius;
@@ -1643,9 +1698,9 @@ st_theme_node_paint_borders (StThemeNode *node,
{
verts[4] = width - max_border_radius;
verts[5] = border_width[ST_SIDE_TOP];
- verts[6] = width - MAX(node->border_radius[corner_id],
+ verts[6] = width - MAX(border_radius[corner_id],
border_width[ST_SIDE_RIGHT]);
- verts[7] = MAX(node->border_radius[corner_id],
+ verts[7] = MAX(border_radius[corner_id],
border_width[ST_SIDE_TOP]);
}
break;
@@ -1653,14 +1708,14 @@ st_theme_node_paint_borders (StThemeNode *node,
verts[0] = width - max_border_radius;
verts[1] = height - max_border_radius;
verts[2] = width - border_width[ST_SIDE_RIGHT];
- verts[3] = height - MAX(node->border_radius[corner_id],
+ verts[3] = height - MAX(border_radius[corner_id],
border_width[ST_SIDE_BOTTOM]);
if (n_rects == 2)
{
verts[4] = width - max_border_radius;
- verts[5] = height - MAX(node->border_radius[corner_id],
+ verts[5] = height - MAX(border_radius[corner_id],
border_width[ST_SIDE_BOTTOM]);
- verts[6] = width - MAX(node->border_radius[corner_id],
+ verts[6] = width - MAX(border_radius[corner_id],
border_width[ST_SIDE_RIGHT]);
verts[7] = height - border_width[ST_SIDE_BOTTOM];
}
@@ -1669,13 +1724,13 @@ st_theme_node_paint_borders (StThemeNode *node,
verts[0] = border_width[ST_SIDE_LEFT];
verts[1] = height - max_border_radius;
verts[2] = max_border_radius;
- verts[3] = height - MAX(node->border_radius[corner_id],
+ verts[3] = height - MAX(border_radius[corner_id],
border_width[ST_SIDE_BOTTOM]);
if (n_rects == 2)
{
- verts[4] = MAX(node->border_radius[corner_id],
+ verts[4] = MAX(border_radius[corner_id],
border_width[ST_SIDE_LEFT]);
- verts[5] = height - MAX(node->border_radius[corner_id],
+ verts[5] = height - MAX(border_radius[corner_id],
border_width[ST_SIDE_BOTTOM]);
verts[6] = max_border_radius;
verts[7] = height - border_width[ST_SIDE_BOTTOM];
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]