mirror of
https://github.com/labwc/labwc.git
synced 2025-11-04 13:30:07 -05:00
theme: fix rounded-corner bug
Make top left/right corner pieces with large border thickness pixel perfect. Fixes: issue #988
This commit is contained in:
parent
b816c16701
commit
318d881650
1 changed files with 94 additions and 6 deletions
100
src/theme.c
100
src/theme.c
|
|
@ -454,7 +454,21 @@ rounded_rect(struct rounded_corner_ctx *ctx)
|
|||
cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR);
|
||||
cairo_paint(cairo);
|
||||
|
||||
/* fill */
|
||||
/*
|
||||
* Create outline path and fill. Illustration of top-left corner buffer:
|
||||
*
|
||||
* _,,ooO"""""""""+
|
||||
* ,oO"' ^ |
|
||||
* ,o" | |
|
||||
* o" |r |
|
||||
* o' | |
|
||||
* O r v |
|
||||
* O<--------->+ |
|
||||
* O |
|
||||
* O |
|
||||
* O |
|
||||
* +--------------------+
|
||||
*/
|
||||
cairo_set_line_width(cairo, 0.0);
|
||||
cairo_new_sub_path(cairo);
|
||||
switch (ctx->corner) {
|
||||
|
|
@ -479,28 +493,102 @@ rounded_rect(struct rounded_corner_ctx *ctx)
|
|||
cairo_fill_preserve(cairo);
|
||||
cairo_stroke(cairo);
|
||||
|
||||
/* border */
|
||||
cairo_set_line_cap(cairo, CAIRO_LINE_CAP_ROUND);
|
||||
/*
|
||||
* Stroke horizontal and vertical borders, shown by Xs and Ys
|
||||
* respectively in the figure below:
|
||||
*
|
||||
* _,,ooO"XXXXXXXXX
|
||||
* ,oO"' |
|
||||
* ,o" |
|
||||
* o" |
|
||||
* o' |
|
||||
* O |
|
||||
* Y |
|
||||
* Y |
|
||||
* Y |
|
||||
* Y |
|
||||
* Y--------------------+
|
||||
*/
|
||||
cairo_set_line_cap(cairo, CAIRO_LINE_CAP_BUTT);
|
||||
set_cairo_color(cairo, ctx->border_color);
|
||||
cairo_set_line_width(cairo, ctx->line_width);
|
||||
double half_line_width = ctx->line_width / 2.0;
|
||||
switch (ctx->corner) {
|
||||
case LAB_CORNER_TOP_LEFT:
|
||||
cairo_move_to(cairo, half_line_width, h);
|
||||
cairo_line_to(cairo, half_line_width, r + half_line_width);
|
||||
cairo_arc(cairo, r, r, r - half_line_width, 180 * deg, 270 * deg);
|
||||
cairo_line_to(cairo, half_line_width, r);
|
||||
cairo_move_to(cairo, r, half_line_width);
|
||||
cairo_line_to(cairo, w, half_line_width);
|
||||
break;
|
||||
case LAB_CORNER_TOP_RIGHT:
|
||||
cairo_move_to(cairo, 0, half_line_width);
|
||||
cairo_line_to(cairo, w - r, half_line_width);
|
||||
cairo_arc(cairo, w - r, r, r - half_line_width, -90 * deg, 0 * deg);
|
||||
cairo_move_to(cairo, w - half_line_width, r);
|
||||
cairo_line_to(cairo, w - half_line_width, h);
|
||||
break;
|
||||
default:
|
||||
wlr_log(WLR_ERROR, "unknown corner type");
|
||||
}
|
||||
cairo_stroke(cairo);
|
||||
|
||||
/*
|
||||
* If radius==0 the borders stroked above go right up to (and including)
|
||||
* the corners, so there is not need to do any more.
|
||||
*/
|
||||
if (!r) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stroke the arc section of the border of the corner piece.
|
||||
*
|
||||
* Note: This figure is drawn at a more zoomed in scale compared with
|
||||
* those above.
|
||||
*
|
||||
* ,,ooooO"" ^
|
||||
* ,ooo""' | |
|
||||
* ,oOO" | | line-thickness
|
||||
* ,OO" | |
|
||||
* ,OO" _,,ooO"" v
|
||||
* ,O" ,oO"'
|
||||
* ,O' ,o"
|
||||
* ,O' o"
|
||||
* o' o'
|
||||
* O O
|
||||
* O---------O +
|
||||
* <----------------->
|
||||
* radius
|
||||
*
|
||||
* We handle the edge-case where line-thickness > radius by merely
|
||||
* setting line-thickness = radius and in effect drawing a quadrant of a
|
||||
* circle. In this case the X and Y borders butt up against the arc and
|
||||
* overlap each other (as their line-thickessnes are greater than the
|
||||
* linethickness of the arc). As a result, there is no inner rounded
|
||||
* corners.
|
||||
*
|
||||
* So, in order to have inner rounded corners cornerRadius should be
|
||||
* greater than border.width.
|
||||
*
|
||||
* Also, see diagrams in https://github.com/labwc/labwc/pull/990
|
||||
*/
|
||||
double line_width = MIN(ctx->line_width, r);
|
||||
cairo_set_line_width(cairo, line_width);
|
||||
half_line_width = line_width / 2.0;
|
||||
switch (ctx->corner) {
|
||||
case LAB_CORNER_TOP_LEFT:
|
||||
cairo_move_to(cairo, half_line_width, r);
|
||||
cairo_arc(cairo, r, r, r - half_line_width, 180 * deg, 270 * deg);
|
||||
break;
|
||||
case LAB_CORNER_TOP_RIGHT:
|
||||
cairo_move_to(cairo, w - r, half_line_width);
|
||||
cairo_arc(cairo, w - r, r, r - half_line_width, -90 * deg, 0 * deg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
cairo_stroke(cairo);
|
||||
|
||||
out:
|
||||
cairo_surface_flush(surf);
|
||||
|
||||
return buffer;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue