🔒 Repository is read-only – file editing is disabled.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
//! Skala ekranu: przeliczanie pikseli logicznych na fizyczne i z powrotem.
//!
//! Cały toolkit operuje na pikselach logicznych; [`Scale`] pojawia się dopiero
//! w warstwie rysowania i obsługi wejścia (Wayland przekazuje współrzędne
//! w pikselach logicznych, a bufor w fizycznych).
/// Współczynnik skalowania (np. `2.0` dla HiDPI, `1.0` dla zwykłego ekranu).
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Scale(f64);
impl Scale {
/// Skala 1:1.
pub const ONE: Scale = Scale(1.0);
pub const fn new(factor: f64) -> Self {
Self(factor)
}
/// Ze skali całkowitej — typowe wartości to 1, 2, 3.
pub const fn integer(factor: i32) -> Self {
Self(factor as f64)
}
pub const fn factor(&self) -> f64 {
self.0
}
pub fn to_physical(&self, logical: f64) -> f64 {
logical * self.0
}
pub fn to_logical(&self, physical: f64) -> f64 {
physical / self.0
}
/// Rozmiar fizyczny (zaokrąglony w górę), przydatny do alokacji bufora.
pub fn physical_size(&self, width: f64, height: f64) -> (u32, u32) {
(
self.to_physical(width).ceil().max(0.0) as u32,
self.to_physical(height).ceil().max(0.0) as u32,
)
}
}
impl Default for Scale {
fn default() -> Self {
Scale::ONE
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn conversion_roundtrip() {
let s = Scale::integer(2);
assert_eq!(s.to_physical(10.0), 20.0);
assert_eq!(s.to_logical(20.0), 10.0);
}
#[test]
fn physical_size_rounds_up() {
let s = Scale::new(1.5);
assert_eq!(s.physical_size(10.0, 3.0), (15, 5));
let s = Scale::new(1.25);
assert_eq!(s.physical_size(10.0, 10.0), (13, 13));
}
}