Skip to content

Commit f553cba

Browse files
committed
feat(backend): add CellSized trait for querying cell dimensions in physical and CSS pixels
1 parent 2030bc3 commit f553cba

6 files changed

Lines changed: 92 additions & 1 deletion

File tree

examples/shared/src/backend.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use ratzilla::{
44
error::Error,
55
event::{KeyEvent, MouseEvent},
66
ratatui::{backend::Backend, prelude::backend::ClearType, Terminal, TerminalOptions},
7-
CanvasBackend, DomBackend, WebEventHandler, WebGl2Backend,
7+
CanvasBackend, CellSized, DomBackend, WebEventHandler, WebGl2Backend,
88
};
99
use std::{convert::TryFrom, fmt, io};
1010
use web_sys::{window, Url};
@@ -78,6 +78,24 @@ impl RatzillaBackend {
7878
}
7979
}
8080

81+
impl CellSized for RatzillaBackend {
82+
fn cell_size_px(&self) -> (f64, f64) {
83+
match self {
84+
RatzillaBackend::Dom(backend) => backend.cell_size_px(),
85+
RatzillaBackend::Canvas(backend) => backend.cell_size_px(),
86+
RatzillaBackend::WebGl2(backend) => backend.cell_size_px(),
87+
}
88+
}
89+
90+
fn cell_size_css_px(&self) -> (f64, f64) {
91+
match self {
92+
RatzillaBackend::Dom(backend) => backend.cell_size_css_px(),
93+
RatzillaBackend::Canvas(backend) => backend.cell_size_css_px(),
94+
RatzillaBackend::WebGl2(backend) => backend.cell_size_css_px(),
95+
}
96+
}
97+
}
98+
8199
impl Backend for RatzillaBackend {
82100
type Error = io::Error;
83101

@@ -244,6 +262,16 @@ impl From<RatzillaBackend> for FpsTrackingBackend {
244262
}
245263
}
246264

265+
impl CellSized for FpsTrackingBackend {
266+
fn cell_size_px(&self) -> (f64, f64) {
267+
self.inner.cell_size_px()
268+
}
269+
270+
fn cell_size_css_px(&self) -> (f64, f64) {
271+
self.inner.cell_size_css_px()
272+
}
273+
}
274+
247275
impl Backend for FpsTrackingBackend {
248276
type Error = io::Error;
249277

src/backend/canvas.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use crate::{
1010
},
1111
utils::*,
1212
},
13+
cell_sized::CellSized,
1314
error::Error,
1415
event::{KeyEvent, MouseEvent},
1516
render::WebEventHandler,
@@ -438,6 +439,18 @@ impl CanvasBackend {
438439
}
439440
}
440441

442+
impl CellSized for CanvasBackend {
443+
fn cell_size_px(&self) -> (f64, f64) {
444+
let dpr = get_window().map(|w| w.device_pixel_ratio()).unwrap_or(1.0);
445+
446+
(CELL_WIDTH * dpr, CELL_HEIGHT * dpr)
447+
}
448+
449+
fn cell_size_css_px(&self) -> (f64, f64) {
450+
(CELL_WIDTH, CELL_HEIGHT)
451+
}
452+
}
453+
441454
impl Backend for CanvasBackend {
442455
type Error = IoError;
443456

src/backend/dom.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use crate::{
2121
},
2222
utils::*,
2323
},
24+
cell_sized::CellSized,
2425
error::Error,
2526
event::{KeyEvent, MouseEvent},
2627
render::WebEventHandler,
@@ -265,6 +266,18 @@ impl DomBackend {
265266
}
266267
}
267268

269+
impl CellSized for DomBackend {
270+
fn cell_size_px(&self) -> (f64, f64) {
271+
let dpr = get_window().map(|w| w.device_pixel_ratio()).unwrap_or(1.0);
272+
273+
(self.cell_size.0 * dpr, self.cell_size.1 * dpr)
274+
}
275+
276+
fn cell_size_css_px(&self) -> (f64, f64) {
277+
self.cell_size
278+
}
279+
}
280+
268281
impl Backend for DomBackend {
269282
type Error = IoError;
270283

src/backend/webgl2.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::{
44
event_callback::{EventCallback, KEY_EVENT_TYPES},
55
utils::*,
66
},
7+
cell_sized::CellSized,
78
error::Error,
89
event::{KeyEvent, MouseEvent},
910
render::WebEventHandler,
@@ -702,6 +703,19 @@ impl WebGl2Backend {
702703
}
703704
}
704705

706+
impl CellSized for WebGl2Backend {
707+
fn cell_size_px(&self) -> (f64, f64) {
708+
let (w, h) = self.beamterm.cell_size();
709+
(w as f64, h as f64)
710+
}
711+
712+
fn cell_size_css_px(&self) -> (f64, f64) {
713+
let (w, h) = self.beamterm.cell_size();
714+
let dpr = get_window().map(|w| w.device_pixel_ratio()).unwrap_or(1.0);
715+
(w as f64 / dpr, h as f64 / dpr)
716+
}
717+
}
718+
705719
impl Backend for WebGl2Backend {
706720
type Error = IoError;
707721

src/cell_sized.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/// A type that knows the pixel dimensions of its terminal cells.
2+
///
3+
/// # Physical vs. CSS pixels
4+
///
5+
/// On HiDPI / Retina displays the device pixel ratio (DPR) causes one
6+
/// CSS pixel to map to multiple physical (device) pixels.
7+
///
8+
/// - **Physical pixels** (`cell_size_px`): the actual device pixels
9+
/// occupied by a cell. Useful for pixel-perfect rendering and GPU work.
10+
/// - **CSS pixels** (`cell_size_css_px`): the logical size as seen by
11+
/// the browser layout engine. Useful for DOM positioning, mouse
12+
/// coordinate translation, and canvas drawing.
13+
pub trait CellSized {
14+
/// Returns the size of a cell in physical (device) pixels as `(width, height)`.
15+
fn cell_size_px(&self) -> (f64, f64);
16+
17+
/// Returns the size of a cell in CSS (logical) pixels as `(width, height)`.
18+
fn cell_size_css_px(&self) -> (f64, f64);
19+
}

src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ pub mod backend;
1919
/// Rendering.
2020
mod render;
2121

22+
/// Cell size metrics for backends.
23+
pub mod cell_sized;
24+
2225
// Re-export ratatui crate.
2326
pub use ratatui;
2427

@@ -31,4 +34,5 @@ pub use backend::{
3134
dom::DomBackend,
3235
webgl2::{FontAtlasConfig, SelectionMode, WebGl2Backend},
3336
};
37+
pub use cell_sized::CellSized;
3438
pub use render::{WebEventHandler, WebRenderer};

0 commit comments

Comments
 (0)