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