From a41b732f8f2fde14cd8f22cf165d614ffc69539a Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 16 Dec 2024 15:50:47 +0100 Subject: [PATCH 1/5] Reduce aliasing when painting thin box outlines --- crates/epaint/src/tessellator.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/crates/epaint/src/tessellator.rs b/crates/epaint/src/tessellator.rs index 9821e4021e1..01705f5f4b5 100644 --- a/crates/epaint/src/tessellator.rs +++ b/crates/epaint/src/tessellator.rs @@ -1702,6 +1702,18 @@ impl Tessellator { self.tessellate_line(line, stroke, out); // …and forth } } else { + let rect = if !stroke.is_empty() && stroke.width <= self.feathering { + // Very thin rectangle strokes create extreme aliasing when they move around. + // We can fix that by rounding the rectangle corners to pixel centers. + // TODO(#5164): maybe do this for all shapes and stroke sizes + Rect { + min: self.round_pos_to_pixel_center(rect.min), + max: self.round_pos_to_pixel_center(rect.max), + } + } else { + rect + }; + let path = &mut self.scratchpad_path; path.clear(); path::rounded_rectangle(&mut self.scratchpad_points, rect, rounding); From 204318adc1b7e588af2b9d4fc7c4bad5306f609d Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 16 Dec 2024 16:10:32 +0100 Subject: [PATCH 2/5] Fix rounding --- crates/epaint/src/tessellator.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/crates/epaint/src/tessellator.rs b/crates/epaint/src/tessellator.rs index 01705f5f4b5..3599146455e 100644 --- a/crates/epaint/src/tessellator.rs +++ b/crates/epaint/src/tessellator.rs @@ -1277,6 +1277,11 @@ impl Tessellator { ((point * self.pixels_per_point - 0.5).round() + 0.5) / self.pixels_per_point } + #[inline(always)] + pub fn round_pos_to_pixel(&self, pos: Pos2) -> Pos2 { + pos2(self.round_to_pixel(pos.x), self.round_to_pixel(pos.y)) + } + #[inline(always)] pub fn round_pos_to_pixel_center(&self, pos: Pos2) -> Pos2 { pos2( @@ -1707,8 +1712,8 @@ impl Tessellator { // We can fix that by rounding the rectangle corners to pixel centers. // TODO(#5164): maybe do this for all shapes and stroke sizes Rect { - min: self.round_pos_to_pixel_center(rect.min), - max: self.round_pos_to_pixel_center(rect.max), + min: self.round_pos_to_pixel(rect.min), + max: self.round_pos_to_pixel(rect.max), } } else { rect From 1dd214c386b284780e3043f05136359cef0d479b Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 16 Dec 2024 16:16:53 +0100 Subject: [PATCH 3/5] Add comment with TODO --- crates/epaint/src/tessellator.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/epaint/src/tessellator.rs b/crates/epaint/src/tessellator.rs index 3599146455e..c489b34ddaa 100644 --- a/crates/epaint/src/tessellator.rs +++ b/crates/epaint/src/tessellator.rs @@ -1711,6 +1711,10 @@ impl Tessellator { // Very thin rectangle strokes create extreme aliasing when they move around. // We can fix that by rounding the rectangle corners to pixel centers. // TODO(#5164): maybe do this for all shapes and stroke sizes + // TODO(emilk): since we use StrokeKind::Outside, we should probably round the + // corners after offsetting them with half the stroke width (see `translate_stroke_point`). + // The current code can create an effect where the top and left edges are thicker than the bottom and right edges, + // but at least they won't alias when translated. Rect { min: self.round_pos_to_pixel(rect.min), max: self.round_pos_to_pixel(rect.max), From b028a7277b621674e860396856e234ef91e10a89 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 16 Dec 2024 16:19:26 +0100 Subject: [PATCH 4/5] Only adjust if strictly smaller than the feathering --- crates/epaint/src/tessellator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/epaint/src/tessellator.rs b/crates/epaint/src/tessellator.rs index c489b34ddaa..a0ac697cb69 100644 --- a/crates/epaint/src/tessellator.rs +++ b/crates/epaint/src/tessellator.rs @@ -1707,7 +1707,7 @@ impl Tessellator { self.tessellate_line(line, stroke, out); // …and forth } } else { - let rect = if !stroke.is_empty() && stroke.width <= self.feathering { + let rect = if !stroke.is_empty() && stroke.width < self.feathering { // Very thin rectangle strokes create extreme aliasing when they move around. // We can fix that by rounding the rectangle corners to pixel centers. // TODO(#5164): maybe do this for all shapes and stroke sizes From d295caa7267ecc5be6dca83c5d1254fdc0c81b19 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 16 Dec 2024 16:23:41 +0100 Subject: [PATCH 5/5] Round to pixel cente --- crates/epaint/src/tessellator.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/epaint/src/tessellator.rs b/crates/epaint/src/tessellator.rs index a0ac697cb69..0594c8a2aa2 100644 --- a/crates/epaint/src/tessellator.rs +++ b/crates/epaint/src/tessellator.rs @@ -1713,11 +1713,9 @@ impl Tessellator { // TODO(#5164): maybe do this for all shapes and stroke sizes // TODO(emilk): since we use StrokeKind::Outside, we should probably round the // corners after offsetting them with half the stroke width (see `translate_stroke_point`). - // The current code can create an effect where the top and left edges are thicker than the bottom and right edges, - // but at least they won't alias when translated. Rect { - min: self.round_pos_to_pixel(rect.min), - max: self.round_pos_to_pixel(rect.max), + min: self.round_pos_to_pixel_center(rect.min), + max: self.round_pos_to_pixel_center(rect.max), } } else { rect