Skip to content

Commit ceb2779

Browse files
committed
Fix web UI on Firefox and rendering on Safari iOS
As it turns out, the logic to compute the font height based on the TextMetrics object of the canvas was flawed: it resulting in glitches on Safari iOS (overlapping lines) and an outright crash on Firefox because some of the properties are not implemented there. Simplify this by just relying on the font size we provided as an input to the canvas... which we happen to know statically.
1 parent 23ec766 commit ceb2779

1 file changed

Lines changed: 13 additions & 15 deletions

File tree

web/src/canvas.rs

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,12 @@ const DEFAULT_BG_COLOR: RGB = (0, 0, 0);
4444

4545
/// Default fonts to use. The first font in the list should match whichever font is loaded in
4646
/// `style.css`. The rest are only provided as fallbacks.
47-
const DEFAULT_FONT: &str = "16px \"IBM Plex Mono\", SFMono-Regular, Menlo, Monaco, Consolas, \
47+
const DEFAULT_FONT_FACE: &str = "\"IBM Plex Mono\", SFMono-Regular, Menlo, Monaco, Consolas, \
4848
\"Liberation Mono\", \"Courier New\", monospace";
4949

50+
/// Size of the default font to use in pixels.
51+
const DEFAULT_FONT_SIZE: u16 = 16;
52+
5053
/// Converts a `JsValue` error to an `io::Error`.
5154
pub(crate) fn js_value_to_io_error(e: JsValue) -> io::Error {
5255
if let Some(str) = e.as_string() {
@@ -142,10 +145,6 @@ pub(crate) struct CanvasConsole {
142145
/// Size of each character.
143146
glyph_size: SizeInPixels,
144147

145-
/// Vertical pixels to offset the rendering of each individual character so that it appears
146-
/// correctly centered within its bounding box.
147-
glyph_y_offset: i16,
148-
149148
/// Size of the console in characters. This is derived from `size_pixels` and `glyph_size`.
150149
size_chars: CharsXY,
151150

@@ -199,19 +198,15 @@ impl CanvasConsole {
199198
};
200199

201200
let context = html_canvas_to_2d_context(canvas)?;
202-
context.set_font(DEFAULT_FONT);
203-
context.set_text_baseline("top");
201+
context.set_font(&format!("{}px {}", DEFAULT_FONT_SIZE, DEFAULT_FONT_FACE));
202+
context.set_text_baseline("middle");
204203

205-
let text_metrics = context.measure_text("X").map_err(js_value_to_io_error)?;
206204
let glyph_size = {
205+
let text_metrics = context.measure_text("X").map_err(js_value_to_io_error)?;
207206
let width = text_metrics.width().ceil() as u16;
208-
let height = (text_metrics.font_bounding_box_ascent()
209-
+ text_metrics.font_bounding_box_descent()) as u16;
210-
207+
let height = DEFAULT_FONT_SIZE + 2; // Pad lines a little bit.
211208
SizeInPixels { width, height }
212209
};
213-
let glyph_y_offset = (text_metrics.font_bounding_box_descent()
214-
- text_metrics.actual_bounding_box_descent()) as i16;
215210

216211
let size_chars = {
217212
let width = match size_pixels.width.checked_div(glyph_size.width) {
@@ -240,7 +235,6 @@ impl CanvasConsole {
240235
input,
241236
size_pixels,
242237
glyph_size,
243-
glyph_y_offset,
244238
size_chars,
245239
cursor_pos: CharsXY::new(0, 0),
246240
cursor_visible: true,
@@ -389,6 +383,10 @@ impl CanvasConsole {
389383
Ok(width) => width,
390384
Err(e) => log_and_panic!("Glyph size is too big: {}", e),
391385
};
386+
let y_offset = match i16::try_from(self.glyph_size.height) {
387+
Ok(height) => height / 2,
388+
Err(e) => log_and_panic!("Glyph height is too big: {}", e),
389+
};
392390
for b in bytes {
393391
let bs = &[*b];
394392
let sb = match std::str::from_utf8(bs) {
@@ -401,7 +399,7 @@ impl CanvasConsole {
401399
}
402400
};
403401
self.context
404-
.fill_text(sb, f64::from(x), f64::from(start.y + self.glyph_y_offset))
402+
.fill_text(sb, f64::from(x), f64::from(start.y + y_offset))
405403
.map_err(js_value_to_io_error)?;
406404

407405
x += advance;

0 commit comments

Comments
 (0)