st-theme-node: Support non-uniform border widths
While non-uniform border widths were parsed correctly, an arbitrary side's width was picked when painting, so that each border ended up with the same width and the widths specified in CSS were ignored. At least for sides between non-rounded corners, using a different border width can be reasonable, for instance at screen edges. Different border widths around rounded corners are kind of crack, but then it would be lame not to support it ... https://bugzilla.gnome.org/show_bug.cgi?id=607500
This commit is contained in:
parent
cb2babb1a0
commit
cb5c18c783
@ -49,6 +49,22 @@ typedef struct {
|
||||
guint border_width_2;
|
||||
} StCornerSpec;
|
||||
|
||||
static void
|
||||
elliptical_arc (cairo_t *cr,
|
||||
double x_center,
|
||||
double y_center,
|
||||
double x_radius,
|
||||
double y_radius,
|
||||
double angle1,
|
||||
double angle2)
|
||||
{
|
||||
cairo_save (cr);
|
||||
cairo_translate (cr, x_center, y_center);
|
||||
cairo_scale (cr, x_radius, y_radius);
|
||||
cairo_arc (cr, 0, 0, 1.0, angle1, angle2);
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
static CoglHandle
|
||||
create_corner_material (StCornerSpec *corner)
|
||||
{
|
||||
@ -73,13 +89,11 @@ create_corner_material (StCornerSpec *corner)
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_scale (cr, size, size);
|
||||
|
||||
/* TODO support nonuniform border widths */
|
||||
|
||||
if (corner->border_width_1 < corner->radius)
|
||||
if (max_border_width <= corner->radius)
|
||||
{
|
||||
double internal_radius = 0.5 * (1.0 - (double) corner->border_width_1 / corner->radius);
|
||||
double x_radius, y_radius;
|
||||
|
||||
if (corner->border_width_1 != 0)
|
||||
if (max_border_width != 0)
|
||||
{
|
||||
cairo_set_source_rgba (cr,
|
||||
corner->border_color_1.red / 255.,
|
||||
@ -96,14 +110,41 @@ create_corner_material (StCornerSpec *corner)
|
||||
corner->color.green / 255.,
|
||||
corner->color.blue / 255.,
|
||||
corner->color.alpha / 255.);
|
||||
cairo_arc (cr, 0.5, 0.5, internal_radius, 0, 2 * M_PI);
|
||||
|
||||
x_radius = 0.5 * (1.0 - (double) corner->border_width_2 / corner->radius);
|
||||
y_radius = 0.5 * (1.0 - (double) corner->border_width_1 / corner->radius);
|
||||
|
||||
/* TOPRIGHT */
|
||||
elliptical_arc (cr,
|
||||
0.5, 0.5,
|
||||
x_radius, y_radius,
|
||||
3 * M_PI / 2, 2 * M_PI);
|
||||
|
||||
/* BOTTOMRIGHT */
|
||||
elliptical_arc (cr,
|
||||
0.5, 0.5,
|
||||
x_radius, y_radius,
|
||||
0, M_PI / 2);
|
||||
|
||||
/* TOPLEFT */
|
||||
elliptical_arc (cr,
|
||||
0.5, 0.5,
|
||||
x_radius, y_radius,
|
||||
M_PI, 3 * M_PI / 2);
|
||||
|
||||
/* BOTTOMLEFT */
|
||||
elliptical_arc (cr,
|
||||
0.5, 0.5,
|
||||
x_radius, y_radius,
|
||||
M_PI / 2, M_PI);
|
||||
|
||||
cairo_fill (cr);
|
||||
}
|
||||
else
|
||||
{
|
||||
double radius;
|
||||
|
||||
radius = (gdouble)corner->radius / corner->border_width_1;
|
||||
radius = (gdouble)corner->radius / max_border_width;
|
||||
|
||||
cairo_set_source_rgba (cr,
|
||||
corner->border_color_1.red / 255.,
|
||||
@ -216,6 +257,41 @@ over (const ClutterColor *source,
|
||||
unpremultiply (result);
|
||||
}
|
||||
|
||||
static void
|
||||
st_theme_node_get_corner_border_widths (StThemeNode *node,
|
||||
StCorner corner_id,
|
||||
guint *border_width_1,
|
||||
guint *border_width_2)
|
||||
{
|
||||
switch (corner_id)
|
||||
{
|
||||
case ST_CORNER_TOPLEFT:
|
||||
if (border_width_1)
|
||||
*border_width_1 = node->border_width[ST_SIDE_TOP];
|
||||
if (border_width_2)
|
||||
*border_width_2 = node->border_width[ST_SIDE_LEFT];
|
||||
break;
|
||||
case ST_CORNER_TOPRIGHT:
|
||||
if (border_width_1)
|
||||
*border_width_1 = node->border_width[ST_SIDE_TOP];
|
||||
if (border_width_2)
|
||||
*border_width_2 = node->border_width[ST_SIDE_RIGHT];
|
||||
break;
|
||||
case ST_CORNER_BOTTOMRIGHT:
|
||||
if (border_width_1)
|
||||
*border_width_1 = node->border_width[ST_SIDE_BOTTOM];
|
||||
if (border_width_2)
|
||||
*border_width_2 = node->border_width[ST_SIDE_RIGHT];
|
||||
break;
|
||||
case ST_CORNER_BOTTOMLEFT:
|
||||
if (border_width_1)
|
||||
*border_width_1 = node->border_width[ST_SIDE_BOTTOM];
|
||||
if (border_width_2)
|
||||
*border_width_2 = node->border_width[ST_SIDE_LEFT];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static CoglHandle
|
||||
st_theme_node_lookup_corner (StThemeNode *node,
|
||||
StCorner corner_id)
|
||||
@ -233,30 +309,25 @@ st_theme_node_lookup_corner (StThemeNode *node,
|
||||
|
||||
corner.radius = node->border_radius[corner_id];
|
||||
corner.color = node->background_color;
|
||||
st_theme_node_get_corner_border_widths (node, corner_id,
|
||||
&corner.border_width_1,
|
||||
&corner.border_width_2);
|
||||
|
||||
switch (corner_id)
|
||||
{
|
||||
case ST_CORNER_TOPLEFT:
|
||||
corner.border_width_1 = node->border_width[ST_SIDE_TOP];
|
||||
corner.border_width_2 = node->border_width[ST_SIDE_LEFT];
|
||||
over (&node->border_color[ST_SIDE_TOP], &corner.color, &corner.border_color_1);
|
||||
over (&node->border_color[ST_SIDE_LEFT], &corner.color, &corner.border_color_2);
|
||||
break;
|
||||
case ST_CORNER_TOPRIGHT:
|
||||
corner.border_width_1 = node->border_width[ST_SIDE_TOP];
|
||||
corner.border_width_2 = node->border_width[ST_SIDE_RIGHT];
|
||||
over (&node->border_color[ST_SIDE_TOP], &corner.color, &corner.border_color_1);
|
||||
over (&node->border_color[ST_SIDE_RIGHT], &corner.color, &corner.border_color_2);
|
||||
break;
|
||||
case ST_CORNER_BOTTOMRIGHT:
|
||||
corner.border_width_1 = node->border_width[ST_SIDE_BOTTOM];
|
||||
corner.border_width_2 = node->border_width[ST_SIDE_RIGHT];
|
||||
over (&node->border_color[ST_SIDE_BOTTOM], &corner.color, &corner.border_color_1);
|
||||
over (&node->border_color[ST_SIDE_RIGHT], &corner.color, &corner.border_color_2);
|
||||
break;
|
||||
case ST_CORNER_BOTTOMLEFT:
|
||||
corner.border_width_1 = node->border_width[ST_SIDE_BOTTOM];
|
||||
corner.border_width_2 = node->border_width[ST_SIDE_LEFT];
|
||||
over (&node->border_color[ST_SIDE_BOTTOM], &corner.color, &corner.border_color_1);
|
||||
over (&node->border_color[ST_SIDE_LEFT], &corner.color, &corner.border_color_2);
|
||||
break;
|
||||
@ -346,28 +417,14 @@ get_background_position (StThemeNode *self,
|
||||
}
|
||||
|
||||
/* Use of this function marks code which doesn't support
|
||||
* non-uniform widths and/or colors.
|
||||
* non-uniform colors.
|
||||
*/
|
||||
static gboolean
|
||||
get_arbitrary_border (StThemeNode *node,
|
||||
int *width,
|
||||
ClutterColor *color)
|
||||
static void
|
||||
get_arbitrary_border_color (StThemeNode *node,
|
||||
ClutterColor *color)
|
||||
{
|
||||
int w;
|
||||
|
||||
w = st_theme_node_get_border_width (node, ST_SIDE_TOP);
|
||||
if (w > 0)
|
||||
{
|
||||
if (width)
|
||||
*width = w;
|
||||
if (color)
|
||||
st_theme_node_get_border_color (node, ST_SIDE_TOP, color);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (width)
|
||||
*width = 0;
|
||||
return FALSE;
|
||||
if (color)
|
||||
st_theme_node_get_border_color (node, ST_SIDE_TOP, color);
|
||||
}
|
||||
|
||||
static CoglHandle
|
||||
@ -379,7 +436,7 @@ st_theme_node_render_gradient (StThemeNode *node)
|
||||
cairo_surface_t *surface;
|
||||
cairo_pattern_t *pattern;
|
||||
ClutterColor border_color;
|
||||
int border_width;
|
||||
int border_width[4];
|
||||
guint rowstride;
|
||||
guchar *data;
|
||||
|
||||
@ -392,11 +449,15 @@ st_theme_node_render_gradient (StThemeNode *node)
|
||||
rowstride);
|
||||
cr = cairo_create (surface);
|
||||
|
||||
/* TODO - support non-uniform border colors and widths */
|
||||
get_arbitrary_border (node, &border_width, &border_color);
|
||||
/* TODO - support non-uniform border colors */
|
||||
get_arbitrary_border_color (node, &border_color);
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
radius[i] = st_theme_node_get_border_radius (node, i);
|
||||
{
|
||||
border_width[i] = st_theme_node_get_border_width (node, i);
|
||||
|
||||
radius[i] = st_theme_node_get_border_radius (node, i);
|
||||
}
|
||||
|
||||
if (node->background_gradient_type == ST_GRADIENT_VERTICAL)
|
||||
pattern = cairo_pattern_create_linear (0, 0, 0, node->alloc_height);
|
||||
@ -437,13 +498,13 @@ st_theme_node_render_gradient (StThemeNode *node)
|
||||
radius[ST_CORNER_TOPRIGHT],
|
||||
radius[ST_CORNER_TOPRIGHT], 3 * M_PI / 2, 2 * M_PI);
|
||||
cairo_line_to (cr, node->alloc_width, node->alloc_height - radius[ST_CORNER_BOTTOMRIGHT]);
|
||||
if (radius[ST_CORNER_BOTTOMRIGHT])
|
||||
if (radius[ST_CORNER_BOTTOMRIGHT] > 0)
|
||||
cairo_arc (cr,
|
||||
node->alloc_width - radius[ST_CORNER_BOTTOMRIGHT],
|
||||
node->alloc_height - radius[ST_CORNER_BOTTOMRIGHT],
|
||||
radius[ST_CORNER_BOTTOMRIGHT], 0, M_PI / 2);
|
||||
cairo_line_to (cr, radius[ST_CORNER_BOTTOMLEFT], node->alloc_height);
|
||||
if (radius[ST_CORNER_BOTTOMLEFT])
|
||||
if (radius[ST_CORNER_BOTTOMLEFT] > 0)
|
||||
cairo_arc (cr,
|
||||
radius[ST_CORNER_BOTTOMLEFT],
|
||||
node->alloc_height - radius[ST_CORNER_BOTTOMLEFT],
|
||||
@ -456,7 +517,10 @@ st_theme_node_render_gradient (StThemeNode *node)
|
||||
* otherwise the outline shape is filled with the background
|
||||
* gradient directly
|
||||
*/
|
||||
if (border_width > 0)
|
||||
if (border_width[ST_SIDE_TOP] > 0 ||
|
||||
border_width[ST_SIDE_RIGHT] > 0 ||
|
||||
border_width[ST_SIDE_BOTTOM] > 0 ||
|
||||
border_width[ST_SIDE_LEFT] > 0)
|
||||
{
|
||||
cairo_set_source_rgba (cr,
|
||||
border_color.red / 255.,
|
||||
@ -465,47 +529,70 @@ st_theme_node_render_gradient (StThemeNode *node)
|
||||
border_color.alpha / 255.);
|
||||
cairo_fill (cr);
|
||||
|
||||
if (radius[ST_CORNER_TOPLEFT] > border_width)
|
||||
cairo_arc (cr,
|
||||
radius[ST_CORNER_TOPLEFT],
|
||||
radius[ST_CORNER_TOPLEFT],
|
||||
radius[ST_CORNER_TOPLEFT] - border_width,
|
||||
M_PI, 3 * M_PI / 2);
|
||||
if (radius[ST_CORNER_TOPLEFT] > MAX(border_width[ST_SIDE_TOP],
|
||||
border_width[ST_SIDE_LEFT]))
|
||||
elliptical_arc (cr,
|
||||
radius[ST_CORNER_TOPLEFT],
|
||||
radius[ST_CORNER_TOPLEFT],
|
||||
radius[ST_CORNER_TOPLEFT] - border_width[ST_SIDE_LEFT],
|
||||
radius[ST_CORNER_TOPLEFT] - border_width[ST_SIDE_TOP],
|
||||
M_PI, 3 * M_PI / 2);
|
||||
else
|
||||
cairo_move_to (cr, border_width, border_width);
|
||||
cairo_move_to (cr,
|
||||
border_width[ST_SIDE_LEFT],
|
||||
border_width[ST_SIDE_TOP]);
|
||||
|
||||
cairo_line_to (cr,
|
||||
node->alloc_width - MAX(radius[ST_CORNER_TOPRIGHT], border_width),
|
||||
border_width);
|
||||
node->alloc_width - MAX(radius[ST_CORNER_TOPRIGHT], border_width[ST_SIDE_RIGHT]),
|
||||
border_width[ST_SIDE_TOP]);
|
||||
|
||||
if (radius[ST_CORNER_TOPRIGHT] > border_width)
|
||||
cairo_arc (cr,
|
||||
node->alloc_width - radius[ST_CORNER_TOPRIGHT],
|
||||
radius[ST_CORNER_TOPRIGHT],
|
||||
radius[ST_CORNER_TOPRIGHT] - border_width,
|
||||
3 * M_PI / 2, 2 * M_PI);
|
||||
if (radius[ST_CORNER_TOPRIGHT] > MAX(border_width[ST_SIDE_TOP],
|
||||
border_width[ST_SIDE_RIGHT]))
|
||||
elliptical_arc (cr,
|
||||
node->alloc_width - radius[ST_CORNER_TOPRIGHT],
|
||||
radius[ST_CORNER_TOPRIGHT],
|
||||
radius[ST_CORNER_TOPRIGHT] - border_width[ST_SIDE_RIGHT],
|
||||
radius[ST_CORNER_TOPRIGHT] - border_width[ST_SIDE_TOP],
|
||||
3 * M_PI / 2, 2 * M_PI);
|
||||
else
|
||||
cairo_line_to (cr,
|
||||
node->alloc_width - border_width[ST_SIDE_RIGHT],
|
||||
border_width[ST_SIDE_TOP]);
|
||||
|
||||
cairo_line_to (cr,
|
||||
node->alloc_width - border_width,
|
||||
node->alloc_height - MAX(radius[ST_CORNER_BOTTOMRIGHT], border_width));
|
||||
node->alloc_width - border_width[ST_SIDE_RIGHT],
|
||||
node->alloc_height - MAX(radius[ST_CORNER_BOTTOMRIGHT], border_width[ST_SIDE_BOTTOM]));
|
||||
|
||||
if (radius[ST_CORNER_BOTTOMRIGHT] > border_width)
|
||||
cairo_arc (cr,
|
||||
node->alloc_width - radius[ST_CORNER_BOTTOMRIGHT],
|
||||
node->alloc_height - radius[ST_CORNER_BOTTOMRIGHT],
|
||||
radius[ST_CORNER_BOTTOMRIGHT] - border_width,
|
||||
0, M_PI / 2);
|
||||
if (radius[ST_CORNER_BOTTOMRIGHT] > MAX(border_width[ST_SIDE_BOTTOM],
|
||||
border_width[ST_SIDE_RIGHT]))
|
||||
elliptical_arc (cr,
|
||||
node->alloc_width - radius[ST_CORNER_BOTTOMRIGHT],
|
||||
node->alloc_height - radius[ST_CORNER_BOTTOMRIGHT],
|
||||
radius[ST_CORNER_BOTTOMRIGHT] - border_width[ST_SIDE_RIGHT],
|
||||
radius[ST_CORNER_BOTTOMRIGHT] - border_width[ST_SIDE_BOTTOM],
|
||||
0, M_PI / 2);
|
||||
else
|
||||
cairo_line_to (cr,
|
||||
node->alloc_width - border_width[ST_SIDE_RIGHT],
|
||||
node->alloc_height - border_width[ST_SIDE_BOTTOM]);
|
||||
|
||||
cairo_line_to (cr,
|
||||
MAX(radius[ST_CORNER_BOTTOMLEFT], border_width),
|
||||
node->alloc_height - border_width);
|
||||
MAX(radius[ST_CORNER_BOTTOMLEFT], border_width[ST_SIDE_LEFT]),
|
||||
node->alloc_height - border_width[ST_SIDE_BOTTOM]);
|
||||
|
||||
if (radius[ST_CORNER_BOTTOMLEFT] > MAX(border_width[ST_SIDE_BOTTOM],
|
||||
border_width[ST_SIDE_LEFT]))
|
||||
elliptical_arc (cr,
|
||||
radius[ST_CORNER_BOTTOMLEFT],
|
||||
node->alloc_height - radius[ST_CORNER_BOTTOMLEFT],
|
||||
radius[ST_CORNER_BOTTOMLEFT] - border_width[ST_SIDE_LEFT],
|
||||
radius[ST_CORNER_BOTTOMLEFT] - border_width[ST_SIDE_BOTTOM],
|
||||
M_PI / 2, M_PI);
|
||||
else
|
||||
cairo_line_to (cr,
|
||||
border_width[ST_SIDE_LEFT],
|
||||
node->alloc_height - border_width[ST_SIDE_BOTTOM]);
|
||||
|
||||
if (radius[ST_CORNER_BOTTOMLEFT] > border_width)
|
||||
cairo_arc (cr,
|
||||
radius[ST_CORNER_BOTTOMLEFT],
|
||||
node->alloc_height - radius[ST_CORNER_BOTTOMLEFT],
|
||||
radius[ST_CORNER_BOTTOMLEFT] - border_width,
|
||||
M_PI / 2, M_PI);
|
||||
cairo_close_path (cr);
|
||||
}
|
||||
|
||||
@ -706,27 +793,40 @@ st_theme_node_paint_borders (StThemeNode *node,
|
||||
|
||||
{
|
||||
float width, height;
|
||||
int border_width;
|
||||
int border_width[4];
|
||||
int max_border_radius = 0;
|
||||
int max_width_radius[4];
|
||||
int corner_id;
|
||||
int corner_id, side_id;
|
||||
ClutterColor border_color;
|
||||
guint8 alpha;
|
||||
|
||||
width = box->x2 - box->x1;
|
||||
height = box->y2 - box->y1;
|
||||
|
||||
get_arbitrary_border (node, &border_width, &border_color);
|
||||
/* TODO - support non-uniform border colors */
|
||||
get_arbitrary_border_color (node, &border_color);
|
||||
|
||||
for (side_id = 0; side_id < 4; side_id++)
|
||||
border_width[side_id] = st_theme_node_get_border_width(node, side_id);
|
||||
|
||||
for (corner_id = 0; corner_id < 4; corner_id++)
|
||||
{
|
||||
guint border_width_1, border_width_2;
|
||||
|
||||
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];
|
||||
max_width_radius[corner_id] = MAX(border_width,
|
||||
max_width_radius[corner_id] = MAX(MAX(border_width_1, border_width_2),
|
||||
node->border_radius[corner_id]);
|
||||
}
|
||||
|
||||
/* borders */
|
||||
if (border_width > 0)
|
||||
if (border_width[ST_SIDE_TOP] > 0 ||
|
||||
border_width[ST_SIDE_RIGHT] > 0 ||
|
||||
border_width[ST_SIDE_BOTTOM] > 0 ||
|
||||
border_width[ST_SIDE_LEFT] > 0)
|
||||
{
|
||||
ClutterColor effective_border;
|
||||
gboolean skip_corner_1, skip_corner_2;
|
||||
@ -749,18 +849,19 @@ st_theme_node_paint_borders (StThemeNode *node,
|
||||
x1 = skip_corner_1 ? max_width_radius[ST_CORNER_TOPLEFT] : 0;
|
||||
y1 = 0;
|
||||
x2 = skip_corner_2 ? width - max_width_radius[ST_CORNER_TOPRIGHT] : width;
|
||||
y2 = border_width;
|
||||
y2 = border_width[ST_SIDE_TOP];
|
||||
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;
|
||||
|
||||
x1 = width - border_width;
|
||||
y1 = skip_corner_1 ? max_width_radius[ST_CORNER_TOPRIGHT] : border_width;
|
||||
x1 = width - border_width[ST_SIDE_RIGHT];
|
||||
y1 = skip_corner_1 ? max_width_radius[ST_CORNER_TOPRIGHT]
|
||||
: border_width[ST_SIDE_TOP];
|
||||
x2 = width;
|
||||
y2 = skip_corner_2 ? height - max_width_radius[ST_CORNER_BOTTOMRIGHT]
|
||||
: height - border_width;
|
||||
: height - border_width[ST_SIDE_BOTTOM];
|
||||
cogl_rectangle (x1, y1, x2, y2);
|
||||
|
||||
/* SOUTH */
|
||||
@ -768,7 +869,7 @@ st_theme_node_paint_borders (StThemeNode *node,
|
||||
skip_corner_2 = node->border_radius[ST_CORNER_BOTTOMRIGHT] > 0;
|
||||
|
||||
x1 = skip_corner_1 ? max_width_radius[ST_CORNER_BOTTOMLEFT] : 0;
|
||||
y1 = height - border_width;
|
||||
y1 = height - border_width[ST_SIDE_BOTTOM];
|
||||
x2 = skip_corner_2 ? width - max_width_radius[ST_CORNER_BOTTOMRIGHT]
|
||||
: width;
|
||||
y2 = height;
|
||||
@ -779,10 +880,11 @@ st_theme_node_paint_borders (StThemeNode *node,
|
||||
skip_corner_2 = node->border_radius[ST_CORNER_BOTTOMLEFT] > 0;
|
||||
|
||||
x1 = 0;
|
||||
y1 = skip_corner_1 ? max_width_radius[ST_CORNER_TOPLEFT] : border_width;
|
||||
x2 = border_width;
|
||||
y1 = skip_corner_1 ? max_width_radius[ST_CORNER_TOPLEFT]
|
||||
: border_width[ST_SIDE_TOP];
|
||||
x2 = border_width[ST_SIDE_LEFT];
|
||||
y2 = skip_corner_2 ? height - max_width_radius[ST_CORNER_BOTTOMLEFT]
|
||||
: height - border_width;
|
||||
: height - border_width[ST_SIDE_BOTTOM];
|
||||
cogl_rectangle (x1, y1, x2, y2);
|
||||
}
|
||||
}
|
||||
@ -853,82 +955,99 @@ st_theme_node_paint_borders (StThemeNode *node,
|
||||
switch (corner_id)
|
||||
{
|
||||
case ST_CORNER_TOPLEFT:
|
||||
verts[0] = border_width;
|
||||
verts[1] = max_width_radius[ST_CORNER_TOPLEFT];
|
||||
verts[0] = border_width[ST_SIDE_LEFT];
|
||||
verts[1] = MAX(node->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_width_radius[ST_CORNER_TOPLEFT];
|
||||
verts[5] = border_width;
|
||||
verts[4] = MAX(node->border_radius[corner_id],
|
||||
border_width[ST_SIDE_LEFT]);
|
||||
verts[5] = border_width[ST_SIDE_TOP];
|
||||
verts[6] = max_border_radius;
|
||||
verts[7] = max_width_radius[ST_CORNER_TOPLEFT];
|
||||
verts[7] = MAX(node->border_radius[corner_id],
|
||||
border_width[ST_SIDE_TOP]);
|
||||
}
|
||||
break;
|
||||
case ST_CORNER_TOPRIGHT:
|
||||
verts[0] = width - max_border_radius;
|
||||
verts[1] = max_width_radius[ST_CORNER_TOPRIGHT];
|
||||
verts[2] = width - border_width;
|
||||
verts[1] = MAX(node->border_radius[corner_id],
|
||||
border_width[ST_SIDE_TOP]);
|
||||
verts[2] = width - border_width[ST_SIDE_RIGHT];
|
||||
verts[3] = max_border_radius;
|
||||
if (n_rects == 2)
|
||||
{
|
||||
verts[4] = width - max_border_radius;
|
||||
verts[5] = border_width;
|
||||
verts[6] = width - max_width_radius[ST_CORNER_TOPRIGHT];
|
||||
verts[7] = max_width_radius[ST_CORNER_TOPRIGHT];
|
||||
verts[5] = border_width[ST_SIDE_TOP];
|
||||
verts[6] = width - MAX(node->border_radius[corner_id],
|
||||
border_width[ST_SIDE_RIGHT]);
|
||||
verts[7] = MAX(node->border_radius[corner_id],
|
||||
border_width[ST_SIDE_TOP]);
|
||||
}
|
||||
break;
|
||||
case ST_CORNER_BOTTOMRIGHT:
|
||||
verts[0] = width - max_border_radius;
|
||||
verts[1] = height - max_border_radius;
|
||||
verts[2] = width - border_width;
|
||||
verts[3] = height - max_width_radius[ST_CORNER_BOTTOMRIGHT];
|
||||
verts[2] = width - border_width[ST_SIDE_RIGHT];
|
||||
verts[3] = height - MAX(node->border_radius[corner_id],
|
||||
border_width[ST_SIDE_BOTTOM]);
|
||||
if (n_rects == 2)
|
||||
{
|
||||
verts[4] = width - max_border_radius;
|
||||
verts[5] = height - max_width_radius[ST_CORNER_BOTTOMRIGHT];
|
||||
verts[6] = width - max_width_radius[ST_CORNER_BOTTOMRIGHT];
|
||||
verts[7] = height - border_width;
|
||||
verts[5] = height - MAX(node->border_radius[corner_id],
|
||||
border_width[ST_SIDE_BOTTOM]);
|
||||
verts[6] = width - MAX(node->border_radius[corner_id],
|
||||
border_width[ST_SIDE_RIGHT]);
|
||||
verts[7] = height - border_width[ST_SIDE_BOTTOM];
|
||||
}
|
||||
break;
|
||||
case ST_CORNER_BOTTOMLEFT:
|
||||
verts[0] = border_width;
|
||||
verts[0] = border_width[ST_SIDE_LEFT];
|
||||
verts[1] = height - max_border_radius;
|
||||
verts[2] = max_border_radius;
|
||||
verts[3] = height - max_width_radius[ST_CORNER_BOTTOMLEFT];
|
||||
verts[3] = height - MAX(node->border_radius[corner_id],
|
||||
border_width[ST_SIDE_BOTTOM]);
|
||||
if (n_rects == 2)
|
||||
{
|
||||
verts[4] = max_width_radius[ST_CORNER_BOTTOMLEFT];
|
||||
verts[5] = height - max_width_radius[ST_CORNER_BOTTOMLEFT];
|
||||
verts[4] = MAX(node->border_radius[corner_id],
|
||||
border_width[ST_SIDE_LEFT]);
|
||||
verts[5] = height - MAX(node->border_radius[corner_id],
|
||||
border_width[ST_SIDE_BOTTOM]);
|
||||
verts[6] = max_border_radius;
|
||||
verts[7] = height - border_width;
|
||||
verts[7] = height - border_width[ST_SIDE_BOTTOM];
|
||||
}
|
||||
break;
|
||||
}
|
||||
cogl_rectangles (verts, n_rects);
|
||||
}
|
||||
|
||||
if (max_border_radius > border_width)
|
||||
{
|
||||
/* Once we've drawn the borders and corners, if the corners are bigger
|
||||
* the the border width, the remaining area is shaped like
|
||||
*
|
||||
* ########
|
||||
* ##########
|
||||
* ##########
|
||||
* ########
|
||||
*
|
||||
* We draw it in 3 pieces - first the top and bottom, then the main
|
||||
* rectangle
|
||||
*/
|
||||
cogl_rectangle (max_border_radius, border_width,
|
||||
width - max_border_radius, max_border_radius);
|
||||
cogl_rectangle (max_border_radius, height - max_border_radius,
|
||||
width - max_border_radius, height - border_width);
|
||||
}
|
||||
/* Once we've drawn the borders and corners, if the corners are bigger
|
||||
* then the border width, the remaining area is shaped like
|
||||
*
|
||||
* ########
|
||||
* ##########
|
||||
* ##########
|
||||
* ########
|
||||
*
|
||||
* We draw it in at most 3 pieces - first the top and bottom if
|
||||
* necessary, then the main rectangle
|
||||
*/
|
||||
if (max_border_radius > border_width[ST_SIDE_TOP])
|
||||
cogl_rectangle (MAX(max_border_radius, border_width[ST_SIDE_LEFT]),
|
||||
border_width[ST_SIDE_TOP],
|
||||
width - MAX(max_border_radius, border_width[ST_SIDE_RIGHT]),
|
||||
max_border_radius);
|
||||
if (max_border_radius > border_width[ST_SIDE_BOTTOM])
|
||||
cogl_rectangle (MAX(max_border_radius, border_width[ST_SIDE_LEFT]),
|
||||
height - max_border_radius,
|
||||
width - MAX(max_border_radius, border_width[ST_SIDE_RIGHT]),
|
||||
height - border_width[ST_SIDE_BOTTOM]);
|
||||
|
||||
cogl_rectangle (border_width, MAX(border_width, max_border_radius),
|
||||
width - border_width, height - MAX(border_width, max_border_radius));
|
||||
cogl_rectangle (border_width[ST_SIDE_LEFT],
|
||||
MAX(border_width[ST_SIDE_TOP], max_border_radius),
|
||||
width - border_width[ST_SIDE_RIGHT],
|
||||
height - MAX(border_width[ST_SIDE_BOTTOM], max_border_radius));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1108,8 +1227,6 @@ st_theme_node_paint (StThemeNode *node,
|
||||
* 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.
|
||||
|
@ -4,6 +4,7 @@ EXTRA_DIST = run-test.sh.in
|
||||
TEST_JS = \
|
||||
interactive/borders.js \
|
||||
interactive/border-radius.js \
|
||||
interactive/border-width.js \
|
||||
interactive/box-layout.js \
|
||||
interactive/calendar.js \
|
||||
interactive/css-fonts.js \
|
||||
|
60
tests/interactive/border-width.js
Normal file
60
tests/interactive/border-width.js
Normal file
@ -0,0 +1,60 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const UI = imports.testcommon.ui;
|
||||
|
||||
UI.init();
|
||||
let stage = Clutter.Stage.get_default();
|
||||
stage.width = 640;
|
||||
stage.height = 480;
|
||||
|
||||
let vbox = new St.BoxLayout({ width: stage.width,
|
||||
height: stage.height,
|
||||
style: 'padding: 10px; background: #ffee88;'
|
||||
});
|
||||
stage.add_actor(vbox);
|
||||
|
||||
let scroll = new St.ScrollView();
|
||||
vbox.add(scroll, { expand: true });
|
||||
|
||||
let box = new St.BoxLayout({ vertical: true,
|
||||
style: 'spacing: 20px;' });
|
||||
scroll.add_actor(box);
|
||||
|
||||
function addTestCase(borders, useGradient) {
|
||||
let background;
|
||||
if (useGradient)
|
||||
background = 'background-gradient-direction: vertical;'
|
||||
+ 'background-gradient-start: white;'
|
||||
+ 'background-gradient-end: gray;';
|
||||
else
|
||||
background = 'background: white;';
|
||||
|
||||
let border_style = "border-top: " + borders[St.Side.TOP] + " solid black;\n" +
|
||||
"border-right: " + borders[St.Side.RIGHT] + " solid black;\n" +
|
||||
"border-bottom: " + borders[St.Side.BOTTOM] + " solid black;\n" +
|
||||
"border-left: " + borders[St.Side.LEFT] + " solid black;";
|
||||
box.add(new St.Label({ text: border_style,
|
||||
style: border_style
|
||||
+ 'border-radius: 0px 5px 15px 25px;'
|
||||
+ 'padding: 5px;' + background }),
|
||||
{ x_fill: false });
|
||||
}
|
||||
|
||||
// uniform backgrounds
|
||||
addTestCase([" 0px", " 5px", "10px", "15px"], false);
|
||||
addTestCase([" 5px", "10px", "15px", " 0px"], false);
|
||||
addTestCase(["10px", "15px", " 0px", " 5px"], false);
|
||||
addTestCase(["15px", " 0px", " 5px", "10px"], false);
|
||||
|
||||
// gradient backgrounds
|
||||
addTestCase([" 0px", " 5px", "10px", "15px"], true);
|
||||
addTestCase([" 5px", "10px", "15px", " 0px"], true);
|
||||
addTestCase(["10px", "15px", " 0px", " 5px"], true);
|
||||
addTestCase(["15px", " 0px", " 5px", "10px"], true);
|
||||
|
||||
stage.show();
|
||||
Clutter.main();
|
||||
stage.destroy();
|
Loading…
Reference in New Issue
Block a user