use std::sync::atomic::{AtomicUsize, Ordering};
pub const REF_PPI: usize = 300;
static PPI: AtomicUsize = AtomicUsize::new(REF_PPI);
pub fn ppi_for(w: usize, h: usize) -> usize {
let (lo, hi) = if w <= h { (w, h) } else { (h, w) };
match (lo, hi) {
(600, 800) => 167, (758, 1024) => 212, (1072, 1448) => 300, (1080, 1430) => 265, (1264, 1680) => 300, (1404, 1872) => 227, (1440, 1920) => 300, _ => REF_PPI,
}
}
pub fn init_ppi(w: usize, h: usize) {
PPI.store(ppi_for(w, h), Ordering::Relaxed);
}
pub fn ppi() -> usize {
PPI.load(Ordering::Relaxed)
}
pub fn dp(n: i32) -> i32 {
dp_at(n, ppi())
}
pub fn dp_at(n: i32, ppi: usize) -> i32 {
(n * ppi as i32) / REF_PPI as i32
}
pub fn dpf(n: f32) -> f32 {
n * ppi() as f32 / REF_PPI as f32
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ppi_table_hits_known_panels() {
assert_eq!(ppi_for(758, 1024), 212); assert_eq!(ppi_for(1072, 1448), 300); assert_eq!(ppi_for(1264, 1680), 300); assert_eq!(ppi_for(1404, 1872), 227); assert_eq!(ppi_for(1440, 1920), 300); }
#[test]
fn ppi_is_orientation_agnostic() {
assert_eq!(ppi_for(1024, 758), ppi_for(758, 1024));
}
#[test]
fn ppi_unknown_panel_falls_back_to_reference() {
assert_eq!(ppi_for(999, 999), REF_PPI);
}
#[test]
fn dp_is_identity_at_reference_density() {
PPI.store(REF_PPI, Ordering::Relaxed);
assert_eq!(dp(76), 76);
assert_eq!(dp(300), 300);
}
#[test]
fn dp_shrinks_on_low_density_panel() {
PPI.store(212, Ordering::Relaxed);
assert_eq!(dp(76), 76 * 212 / 300);
PPI.store(REF_PPI, Ordering::Relaxed); }
#[test]
fn dp_at_matches_dp_at_same_ppi() {
PPI.store(265, Ordering::Relaxed);
assert_eq!(dp_at(100, 265), dp(100));
assert_eq!(dp_at(0, 265), 0);
PPI.store(REF_PPI, Ordering::Relaxed);
}
#[test]
fn dp_at_is_identity_at_reference() {
assert_eq!(dp_at(300, REF_PPI), 300);
}
}