summaryrefslogtreecommitdiffstats
path: root/tiny_skia
diff options
context:
space:
mode:
authorLibravatar Ashley Wulber <ashley@system76.com>2023-05-11 19:21:36 -0400
committerLibravatar Ashley Wulber <ashley@system76.com>2023-05-11 19:21:36 -0400
commit102c78abd8085d06b72da8edfa83a15ff9df89f2 (patch)
tree1964719bec03029d0b00642d79875cfc8824bd44 /tiny_skia
parent5ee26cc8ec1a49c78d1f3f99ebf6696f827ea5d1 (diff)
downloadiced-102c78abd8085d06b72da8edfa83a15ff9df89f2.tar.gz
iced-102c78abd8085d06b72da8edfa83a15ff9df89f2.tar.bz2
iced-102c78abd8085d06b72da8edfa83a15ff9df89f2.zip
fix: tiny-skia quad handle case where border_radius < border_width / 2.0
Diffstat (limited to 'tiny_skia')
-rw-r--r--tiny_skia/src/backend.rs90
1 files changed, 83 insertions, 7 deletions
diff --git a/tiny_skia/src/backend.rs b/tiny_skia/src/backend.rs
index 583b8dac..d0d24b23 100644
--- a/tiny_skia/src/backend.rs
+++ b/tiny_skia/src/backend.rs
@@ -1,3 +1,5 @@
+use tiny_skia::{Mask, Pixmap, PixmapPaint};
+
use crate::core::text;
use crate::core::{Background, Color, Font, Point, Rectangle, Size, Vector};
use crate::graphics::backend;
@@ -212,17 +214,29 @@ impl Backend {
height: bounds.height - border_width,
};
+ // Make sure the border radius is correct
let mut border_radius = *border_radius;
- for radius in &mut border_radius {
- *radius = radius
- .min(path_bounds.width / 2.0)
- .min(path_bounds.height / 2.0);
+ let mut border_radius_gt_half_border_width =
+ [true, true, true, true];
+ for (i, radius) in &mut border_radius.iter_mut().enumerate() {
+ *radius = if *radius == 0.0 {
+ // Path should handle this fine
+ 0.0
+ } else if *radius > border_width / 2.0 {
+ *radius - border_width / 2.0
+ } else {
+ border_radius_gt_half_border_width[i] = false;
+ 0.0
+ }
+ .min(path_bounds.width / 2.0)
+ .min(path_bounds.height / 2.0);
}
- let border_radius_path =
- rounded_rectangle(path_bounds, border_radius);
+ // Stroking a path works well in this case.
+ if border_radius_gt_half_border_width.iter().all(|b| *b) {
+ let border_radius_path =
+ rounded_rectangle(path_bounds, border_radius);
- if border_width > 0.0 {
pixels.stroke_path(
&border_radius_path,
&tiny_skia::Paint {
@@ -239,6 +253,68 @@ impl Backend {
transform,
clip_mask,
);
+ } else {
+ // Draw corners that have to small border radii as having no border radius,
+ // but mask them with the rounded rectangle with the correct border radius.
+
+ let mut temp_pixmap =
+ Pixmap::new(bounds.width as u32, bounds.height as u32)
+ .unwrap();
+
+ let mut quad_mask =
+ Mask::new(bounds.width as u32, bounds.height as u32)
+ .unwrap();
+
+ let zero_bounds = Rectangle {
+ x: 0.0,
+ y: 0.0,
+ width: bounds.width,
+ height: bounds.height,
+ };
+ let path =
+ rounded_rectangle(zero_bounds, fill_border_radius);
+
+ quad_mask.fill_path(
+ &path,
+ tiny_skia::FillRule::EvenOdd,
+ true,
+ transform,
+ );
+ let path_bounds = Rectangle {
+ x: border_width / 2.0,
+ y: border_width / 2.0,
+ width: bounds.width - border_width,
+ height: bounds.height - border_width,
+ };
+
+ let border_radius_path =
+ rounded_rectangle(path_bounds, border_radius);
+
+ temp_pixmap.stroke_path(
+ &border_radius_path,
+ &tiny_skia::Paint {
+ shader: tiny_skia::Shader::SolidColor(into_color(
+ *border_color,
+ )),
+ anti_alias: true,
+ ..tiny_skia::Paint::default()
+ },
+ &tiny_skia::Stroke {
+ width: border_width,
+ ..tiny_skia::Stroke::default()
+ },
+ transform,
+ Some(&quad_mask),
+ );
+
+ pixels.draw_pixmap(
+ bounds.x as i32,
+ bounds.y as i32,
+ temp_pixmap.as_ref(),
+ &PixmapPaint::default(),
+ transform,
+ clip_mask,
+ );
}
}
Primitive::Text {