mirror of
				https://github.com/labwc/labwc.git
				synced 2025-11-03 09:01:51 -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_set_operator(cairo, CAIRO_OPERATOR_CLEAR);
 | 
				
			||||||
	cairo_paint(cairo);
 | 
						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_set_line_width(cairo, 0.0);
 | 
				
			||||||
	cairo_new_sub_path(cairo);
 | 
						cairo_new_sub_path(cairo);
 | 
				
			||||||
	switch (ctx->corner) {
 | 
						switch (ctx->corner) {
 | 
				
			||||||
| 
						 | 
					@ -479,28 +493,102 @@ rounded_rect(struct rounded_corner_ctx *ctx)
 | 
				
			||||||
	cairo_fill_preserve(cairo);
 | 
						cairo_fill_preserve(cairo);
 | 
				
			||||||
	cairo_stroke(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);
 | 
						set_cairo_color(cairo, ctx->border_color);
 | 
				
			||||||
	cairo_set_line_width(cairo, ctx->line_width);
 | 
						cairo_set_line_width(cairo, ctx->line_width);
 | 
				
			||||||
	double half_line_width = ctx->line_width / 2.0;
 | 
						double half_line_width = ctx->line_width / 2.0;
 | 
				
			||||||
	switch (ctx->corner) {
 | 
						switch (ctx->corner) {
 | 
				
			||||||
	case LAB_CORNER_TOP_LEFT:
 | 
						case LAB_CORNER_TOP_LEFT:
 | 
				
			||||||
		cairo_move_to(cairo, half_line_width, h);
 | 
							cairo_move_to(cairo, half_line_width, h);
 | 
				
			||||||
		cairo_line_to(cairo, half_line_width, r + half_line_width);
 | 
							cairo_line_to(cairo, half_line_width, r);
 | 
				
			||||||
		cairo_arc(cairo, r, r, r - half_line_width, 180 * deg, 270 * deg);
 | 
							cairo_move_to(cairo, r, half_line_width);
 | 
				
			||||||
		cairo_line_to(cairo, w, half_line_width);
 | 
							cairo_line_to(cairo, w, half_line_width);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case LAB_CORNER_TOP_RIGHT:
 | 
						case LAB_CORNER_TOP_RIGHT:
 | 
				
			||||||
		cairo_move_to(cairo, 0, half_line_width);
 | 
							cairo_move_to(cairo, 0, half_line_width);
 | 
				
			||||||
		cairo_line_to(cairo, w - r, 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);
 | 
							cairo_line_to(cairo, w - half_line_width, h);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		wlr_log(WLR_ERROR, "unknown corner type");
 | 
							wlr_log(WLR_ERROR, "unknown corner type");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	cairo_stroke(cairo);
 | 
						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);
 | 
						cairo_surface_flush(surf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return buffer;
 | 
						return buffer;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue