use std::f64::consts::FRAC_1_PI;
use std::fmt;
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum Unit {
Em,
Ex,
Ch,
Rem,
Vw,
Vh,
Vmin,
Vmax,
Cm,
Mm,
Q,
In,
Pt,
Pc,
Px,
Deg,
Grad,
Rad,
Turn,
S,
Ms,
Hz,
Khz,
Dpi,
Dpcm,
Dppx,
Percent,
Fr,
None,
Unknown(String),
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum Dimension {
LengthAbs,
LengthVw,
LengthVh,
LengthVx,
LengthRem,
LenghtEm,
Angle,
Time,
Frequency,
Resolution,
None,
Unknown(String),
}
impl Unit {
pub fn dimension(&self) -> Dimension {
match *self {
Self::Cm
| Self::Mm
| Self::Q
| Self::In
| Self::Pc
| Self::Pt
| Self::Px => Dimension::LengthAbs,
Self::Vw => Dimension::LengthVw,
Self::Vh => Dimension::LengthVh,
Self::Vmin | Self::Vmax => Dimension::LengthVx,
Self::Ch | Self::Em | Self::Ex => Dimension::LenghtEm,
Self::Rem => Dimension::LengthRem,
Self::Deg | Self::Grad | Self::Rad | Self::Turn => {
Dimension::Angle
}
Self::S | Self::Ms => Dimension::Time,
Self::Hz | Self::Khz => Dimension::Frequency,
Self::Dpi | Self::Dpcm | Self::Dppx => Dimension::Resolution,
Self::Percent | Self::Fr | Self::None => Dimension::None,
Self::Unknown(ref name) => Dimension::Unknown(name.clone()),
}
}
pub fn scale_to(&self, other: &Self) -> Option<f64> {
if self == other {
Some(1.)
} else if self.dimension() == other.dimension() {
Some(self.scale_factor() / other.scale_factor())
} else {
None
}
}
pub(crate) fn scale_factor(&self) -> f64 {
#[allow(clippy::match_same_arms)]
match *self {
Self::Em | Self::Rem => 5.,
Self::Ex => 3.,
Self::Ch => 2.,
Self::Vw | Self::Vh | Self::Vmin | Self::Vmax => 1.,
Self::Cm => 10.,
Self::Mm => 1.,
Self::Q => 1. / 4.,
Self::In => 254. / 10.,
Self::Pt => 254. / 720.,
Self::Pc => 254. / 60.,
Self::Px => 254. / 960.,
Self::Deg => 1. / 360.,
Self::Grad => 1. / 400.,
Self::Rad => FRAC_1_PI / 2.0,
Self::Turn => 1.,
Self::S => 1.,
Self::Ms => 1. / 1000.,
Self::Hz => 1.,
Self::Khz => 1000.,
Self::Dpi => 1. / 96.,
Self::Dpcm => 254. / 9600.,
Self::Dppx => 1.,
Self::Percent => 1. / 100.,
Self::Fr => 1.,
Self::None => 1.,
Self::Unknown(_) => 1.,
}
}
}
impl fmt::Display for Unit {
fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result {
match *self {
Self::Em => write!(out, "em"),
Self::Ex => write!(out, "ex"),
Self::Ch => write!(out, "ch"),
Self::Rem => write!(out, "rem"),
Self::Vw => write!(out, "vw"),
Self::Vh => write!(out, "vh"),
Self::Vmin => write!(out, "vmin"),
Self::Vmax => write!(out, "vmax"),
Self::Cm => write!(out, "cm"),
Self::Mm => write!(out, "mm"),
Self::Q => write!(out, "Q"),
Self::In => write!(out, "in"),
Self::Pt => write!(out, "pt"),
Self::Pc => write!(out, "pc"),
Self::Px => write!(out, "px"),
Self::Deg => write!(out, "deg"),
Self::Grad => write!(out, "grad"),
Self::Rad => write!(out, "rad"),
Self::Turn => write!(out, "turn"),
Self::S => write!(out, "s"),
Self::Ms => write!(out, "ms"),
Self::Hz => write!(out, "Hz"),
Self::Khz => write!(out, "kHz"),
Self::Dpi => write!(out, "dpi"),
Self::Dpcm => write!(out, "dpcm"),
Self::Dppx => write!(out, "dppx"),
Self::Percent => write!(out, "%"),
Self::Fr => write!(out, "fr"),
Self::None => Ok(()),
Self::Unknown(ref name) => out.write_str(name),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum CssDimension {
Length,
Angle,
Time,
Frequency,
Resolution,
None,
Unknown(String),
}
impl From<Dimension> for CssDimension {
fn from(dim: Dimension) -> Self {
match dim {
Dimension::LengthAbs
| Dimension::LengthVw
| Dimension::LengthVh
| Dimension::LengthVx
| Dimension::LengthRem
| Dimension::LenghtEm => Self::Length,
Dimension::Angle => Self::Angle,
Dimension::Time => Self::Time,
Dimension::Frequency => Self::Frequency,
Dimension::Resolution => Self::Resolution,
Dimension::None => Self::None,
Dimension::Unknown(s) => Self::Unknown(s),
}
}
}