Skip to content

Commit 4784136

Browse files
authored
Better rounding of rectangles with thin outlines (emilk#5571)
Better positioning of rectangle outline when the stroke width is less than one pixel
1 parent 46b58e5 commit 4784136

File tree

2 files changed

+18
-38
lines changed

2 files changed

+18
-38
lines changed

crates/egui_kittest/src/snapshot.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ pub enum SnapshotError {
102102
}
103103

104104
const HOW_TO_UPDATE_SCREENSHOTS: &str =
105-
"Run `UPDATE_SNAPSHOTS=1 cargo test` to update the snapshots.";
105+
"Run `UPDATE_SNAPSHOTS=1 cargo test --all-features` to update the snapshots.";
106106

107107
impl Display for SnapshotError {
108108
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {

crates/epaint/src/tessellator.rs

Lines changed: 17 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,29 +1291,6 @@ impl Tessellator {
12911291
self.clip_rect = clip_rect;
12921292
}
12931293

1294-
#[inline(always)]
1295-
pub fn round_to_pixel(&self, point: f32) -> f32 {
1296-
(point * self.pixels_per_point).round() / self.pixels_per_point
1297-
}
1298-
1299-
#[inline(always)]
1300-
pub fn round_to_pixel_center(&self, point: f32) -> f32 {
1301-
((point * self.pixels_per_point - 0.5).round() + 0.5) / self.pixels_per_point
1302-
}
1303-
1304-
#[inline(always)]
1305-
pub fn round_pos_to_pixel(&self, pos: Pos2) -> Pos2 {
1306-
pos2(self.round_to_pixel(pos.x), self.round_to_pixel(pos.y))
1307-
}
1308-
1309-
#[inline(always)]
1310-
pub fn round_pos_to_pixel_center(&self, pos: Pos2) -> Pos2 {
1311-
pos2(
1312-
self.round_to_pixel_center(pos.x),
1313-
self.round_to_pixel_center(pos.y),
1314-
)
1315-
}
1316-
13171294
/// Tessellate a clipped shape into a list of primitives.
13181295
pub fn tessellate_clipped_shape(
13191296
&mut self,
@@ -1716,8 +1693,16 @@ impl Tessellator {
17161693
// Since the stroke extends outside of the rectangle,
17171694
// we can round the rectangle sides to the physical pixel edges,
17181695
// and the filled rect will appear crisp, as will the inside of the stroke.
1719-
let Stroke { .. } = stroke; // Make sure we remember to update this if we change `stroke` to `PathStroke`
1720-
rect = rect.round_to_pixels(self.pixels_per_point);
1696+
let Stroke { width, .. } = stroke; // Make sure we remember to update this if we change `stroke` to `PathStroke`
1697+
if width <= self.feathering && !stroke.is_empty() {
1698+
// If the stroke is thin, make sure its center is in the center of the pixel:
1699+
rect = rect
1700+
.expand(width / 2.0)
1701+
.round_to_pixel_center(self.pixels_per_point)
1702+
.shrink(width / 2.0);
1703+
} else {
1704+
rect = rect.round_to_pixels(self.pixels_per_point);
1705+
}
17211706
}
17221707

17231708
// It is common to (sometimes accidentally) create an infinitely sized rectangle.
@@ -1727,7 +1712,7 @@ impl Tessellator {
17271712

17281713
let old_feathering = self.feathering;
17291714

1730-
if old_feathering < blur_width {
1715+
if self.feathering < blur_width {
17311716
// We accomplish the blur by using a larger-than-normal feathering.
17321717
// Feathering is usually used to make the edges of a shape softer for anti-aliasing.
17331718

@@ -1836,10 +1821,7 @@ impl Tessellator {
18361821
// The contents of the galley are already snapped to pixel coordinates,
18371822
// but we need to make sure the galley ends up on the start of a physical pixel:
18381823
let galley_pos = if self.options.round_text_to_pixels {
1839-
pos2(
1840-
self.round_to_pixel(galley_pos.x),
1841-
self.round_to_pixel(galley_pos.y),
1842-
)
1824+
galley_pos.round_to_pixels(self.pixels_per_point)
18431825
} else {
18441826
*galley_pos
18451827
};
@@ -1917,13 +1899,11 @@ impl Tessellator {
19171899
);
19181900

19191901
if *underline != Stroke::NONE {
1920-
self.scratchpad_path.clear();
1921-
self.scratchpad_path.add_line_segment([
1922-
self.round_pos_to_pixel_center(row_rect.left_bottom()),
1923-
self.round_pos_to_pixel_center(row_rect.right_bottom()),
1924-
]);
1925-
self.scratchpad_path
1926-
.stroke_open(0.0, &PathStroke::from(*underline), out);
1902+
self.tessellate_line_segment(
1903+
[row_rect.left_bottom(), row_rect.right_bottom()],
1904+
*underline,
1905+
out,
1906+
);
19271907
}
19281908
}
19291909
}

0 commit comments

Comments
 (0)