1+ use tiny_skia:: { Mask , Pixmap , PixmapPaint } ;
2+
13use crate :: core:: text;
24use crate :: core:: { Background , Color , Font , Point , Rectangle , Size , Vector } ;
35use crate :: graphics:: backend;
@@ -212,17 +214,29 @@ impl Backend {
212214 height : bounds. height - border_width,
213215 } ;
214216
217+ // Make sure the border radius is correct
215218 let mut border_radius = * border_radius;
216- for radius in & mut border_radius {
217- * radius = radius
218- . min ( path_bounds. width / 2.0 )
219- . min ( path_bounds. height / 2.0 ) ;
219+ let mut border_radius_gt_half_border_width =
220+ [ true , true , true , true ] ;
221+ for ( i, radius) in & mut border_radius. iter_mut ( ) . enumerate ( ) {
222+ * radius = if * radius == 0.0 {
223+ // Path should handle this fine
224+ 0.0
225+ } else if * radius > border_width / 2.0 {
226+ * radius - border_width / 2.0
227+ } else {
228+ border_radius_gt_half_border_width[ i] = false ;
229+ 0.0
230+ }
231+ . min ( path_bounds. width / 2.0 )
232+ . min ( path_bounds. height / 2.0 ) ;
220233 }
221234
222- let border_radius_path =
223- rounded_rectangle ( path_bounds, border_radius) ;
235+ // Stroking a path works well in this case.
236+ if border_radius_gt_half_border_width. iter ( ) . all ( |b| * b) {
237+ let border_radius_path =
238+ rounded_rectangle ( path_bounds, border_radius) ;
224239
225- if border_width > 0.0 {
226240 pixels. stroke_path (
227241 & border_radius_path,
228242 & tiny_skia:: Paint {
@@ -239,6 +253,68 @@ impl Backend {
239253 transform,
240254 clip_mask,
241255 ) ;
256+ } else {
257+ // Draw corners that have to small border radii as having no border radius,
258+ // but mask them with the rounded rectangle with the correct border radius.
259+
260+ let mut temp_pixmap =
261+ Pixmap :: new ( bounds. width as u32 , bounds. height as u32 )
262+ . unwrap ( ) ;
263+
264+ let mut quad_mask =
265+ Mask :: new ( bounds. width as u32 , bounds. height as u32 )
266+ . unwrap ( ) ;
267+
268+ let zero_bounds = Rectangle {
269+ x : 0.0 ,
270+ y : 0.0 ,
271+ width : bounds. width ,
272+ height : bounds. height ,
273+ } ;
274+ let path =
275+ rounded_rectangle ( zero_bounds, fill_border_radius) ;
276+
277+ quad_mask. fill_path (
278+ & path,
279+ tiny_skia:: FillRule :: EvenOdd ,
280+ true ,
281+ transform,
282+ ) ;
283+ let path_bounds = Rectangle {
284+ x : border_width / 2.0 ,
285+ y : border_width / 2.0 ,
286+ width : bounds. width - border_width,
287+ height : bounds. height - border_width,
288+ } ;
289+
290+ let border_radius_path =
291+ rounded_rectangle ( path_bounds, border_radius) ;
292+
293+ temp_pixmap. stroke_path (
294+ & border_radius_path,
295+ & tiny_skia:: Paint {
296+ shader : tiny_skia:: Shader :: SolidColor ( into_color (
297+ * border_color,
298+ ) ) ,
299+ anti_alias : true ,
300+ ..tiny_skia:: Paint :: default ( )
301+ } ,
302+ & tiny_skia:: Stroke {
303+ width : border_width,
304+ ..tiny_skia:: Stroke :: default ( )
305+ } ,
306+ transform,
307+ Some ( & quad_mask) ,
308+ ) ;
309+
310+ pixels. draw_pixmap (
311+ bounds. x as i32 ,
312+ bounds. y as i32 ,
313+ temp_pixmap. as_ref ( ) ,
314+ & PixmapPaint :: default ( ) ,
315+ transform,
316+ clip_mask,
317+ ) ;
242318 }
243319 }
244320 Primitive :: Text {
0 commit comments