Skip to content

Commit 11ea38e

Browse files
committed
Fix blurry rendering in some browsers (#4299)
* Closes #4241 I would love some more testers of this. I'm not sure if we really need the round-to-even code, but I'm hesitant to out-right revert #151 when I cannot reproduce its problem. Keeping it seems quite safe though. --- # Testing Checkout the branch and run: * `./scripts/start_server.sh` * `./scripts/build_demo_web.sh` and then open `http://localhost:8888/index.html#Rendering` * `./scripts/build_demo_web.sh --wgpu` and then open `http://localhost:8888/index.html#Rendering` Check the "Rendering test" that the squares in the pixel alignment test are perfectly sharp, like this: <img width="576" alt="Screenshot 2024-04-01 at 13 27 20" src="https://github.com/emilk/egui/assets/1148717/fb6c4824-9e25-4304-bc0c-3c50fbd44a52"> If it looks something like this, something is WRONG: <img width="488" alt="Screenshot 2024-04-01 at 13 29 07" src="https://github.com/emilk/egui/assets/1148717/04bd93ff-2108-40c5-95f6-76e3bcb9cd7f"> Please try it on different zoom levels in different browsers, and if possible on different monitors with different native dpi scaling. Report back the results! ### Mac I have tested on a high-DPI Mac: * Chromium (Brave): ✅ Can reproduce problem on `master`, and it's now fixed * Firefox: ✅ Can reproduce problem on `master`, and it's now fixed * Safari: ❌ Can't get it to work; giving up for now
1 parent dce49e4 commit 11ea38e

File tree

2 files changed

+29
-29
lines changed

2 files changed

+29
-29
lines changed

crates/eframe/src/web/mod.rs

+23-28
Original file line numberDiff line numberDiff line change
@@ -130,51 +130,46 @@ fn resize_canvas_to_screen_size(
130130
) -> Option<()> {
131131
let parent = canvas.parent_element()?;
132132

133+
// In this function we use "pixel" to mean physical pixel,
134+
// and "point" to mean "logical CSS pixel".
135+
let pixels_per_point = native_pixels_per_point();
136+
133137
// Prefer the client width and height so that if the parent
134138
// element is resized that the egui canvas resizes appropriately.
135-
let width = parent.client_width();
136-
let height = parent.client_height();
137-
138-
let canvas_real_size = Vec2 {
139-
x: width as f32,
140-
y: height as f32,
139+
let parent_size_points = Vec2 {
140+
x: parent.client_width() as f32,
141+
y: parent.client_height() as f32,
141142
};
142143

143-
if width <= 0 || height <= 0 {
144-
log::error!("egui canvas parent size is {}x{}. Try adding `html, body {{ height: 100%; width: 100% }}` to your CSS!", width, height);
144+
if parent_size_points.x <= 0.0 || parent_size_points.y <= 0.0 {
145+
log::error!("The parent element of the egui canvas is {}x{}. Try adding `html, body {{ height: 100%; width: 100% }}` to your CSS!", parent_size_points.x, parent_size_points.y);
145146
}
146147

147-
let pixels_per_point = native_pixels_per_point();
148+
// We take great care here to ensure the rendered canvas aligns
149+
// perfectly to the physical pixel grid, lest we get blurry text.
150+
// At the time of writing, we get pixel perfection on Chromium and Firefox on Mac,
151+
// but Desktop Safari will be blurry on most zoom levels.
152+
// See https://github.com/emilk/egui/issues/4241 for more.
148153

149-
let max_size_pixels = pixels_per_point * max_size_points;
154+
let canvas_size_pixels = pixels_per_point * parent_size_points.min(max_size_points);
150155

151-
let canvas_size_pixels = pixels_per_point * canvas_real_size;
152-
let canvas_size_pixels = canvas_size_pixels.min(max_size_pixels);
153-
let canvas_size_points = canvas_size_pixels / pixels_per_point;
154-
155-
// Make sure that the height and width are always even numbers.
156+
// Make sure that the size is always an even number of pixels,
156157
// otherwise, the page renders blurry on some platforms.
157158
// See https://github.com/emilk/egui/issues/103
158-
fn round_to_even(v: f32) -> f32 {
159-
(v / 2.0).round() * 2.0
160-
}
159+
let canvas_size_pixels = (canvas_size_pixels / 2.0).round() * 2.0;
160+
161+
let canvas_size_points = canvas_size_pixels / pixels_per_point;
161162

162163
canvas
163164
.style()
164-
.set_property(
165-
"width",
166-
&format!("{}px", round_to_even(canvas_size_points.x)),
167-
)
165+
.set_property("width", &format!("{}px", canvas_size_points.x))
168166
.ok()?;
169167
canvas
170168
.style()
171-
.set_property(
172-
"height",
173-
&format!("{}px", round_to_even(canvas_size_points.y)),
174-
)
169+
.set_property("height", &format!("{}px", canvas_size_points.y))
175170
.ok()?;
176-
canvas.set_width(round_to_even(canvas_size_pixels.x) as u32);
177-
canvas.set_height(round_to_even(canvas_size_pixels.y) as u32);
171+
canvas.set_width(canvas_size_pixels.x as u32);
172+
canvas.set_height(canvas_size_pixels.y as u32);
178173

179174
Some(())
180175
}

web_demo/index.html

+6-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,12 @@
3737
width: 100%;
3838
}
3939

40-
/* Position canvas in center-top: */
40+
/* Position canvas in center-top.
41+
This is rather arbitrarily chosen.
42+
In particular, it seems like both Chromium and Firefox will still align
43+
the canvas on the physical pixel grid, which is required to get
44+
pixel-perfect (non-blurry) rendering in egui.
45+
See https://github.com/emilk/egui/issues/4241 for more */
4146
canvas {
4247
margin-right: auto;
4348
margin-left: auto;

0 commit comments

Comments
 (0)