use crate::defs::str_to_f64;
use crate::errors::{err_invalid_length, Result};
enum CssUnit {
CM,
MM,
Q,
IN,
PC,
PT,
PX,
}
pub fn inches(lengths: Vec<String>) -> Result<Vec<f64>> {
lengths.iter().map(|s| to_inches(s)).collect()
}
pub fn to_inches(length: &str) -> Result<f64> {
if let Some(prefix) = length.strip_suffix("cm") {
return unit_to_inches(prefix, CssUnit::CM);
}
if let Some(prefix) = length.strip_suffix("mm") {
return unit_to_inches(prefix, CssUnit::MM);
}
if let Some(prefix) = length.strip_suffix('Q') {
return unit_to_inches(prefix, CssUnit::Q);
}
if let Some(prefix) = length.strip_suffix("in") {
return unit_to_inches(prefix, CssUnit::IN);
}
if let Some(prefix) = length.strip_suffix("pc") {
return unit_to_inches(prefix, CssUnit::PC);
}
if let Some(prefix) = length.strip_suffix("pt") {
return unit_to_inches(prefix, CssUnit::PT);
}
if let Some(prefix) = length.strip_suffix("px") {
return unit_to_inches(prefix, CssUnit::PX);
}
if str_to_f64(length)? < f64::EPSILON {
return Ok(0.0);
}
Err(err_invalid_length(length))
}
pub fn inches_to_millimeters(inches: f64) -> f64 {
(inches * 25.4).round()
}
pub fn inches_to_points(inches: f64) -> f64 {
round2(round2(inches) * 72.0)
}
pub fn round1(value: f64) -> f64 {
(value * 10.0).round() / 10.0
}
pub fn round2(value: f64) -> f64 {
(value * 100.0).round() / 100.0
}
fn unit_to_inches(s: &str, unit: CssUnit) -> Result<f64> {
let value = str_to_f64(s)?;
Ok(match unit {
CssUnit::CM => value * 25.2 / 64.0,
CssUnit::MM => value * 2.52 / 64.0,
CssUnit::Q => value * 2.52 / 256.0,
CssUnit::IN => value,
CssUnit::PC => value / 6.0,
CssUnit::PT => value / 72.0,
CssUnit::PX => value / 96.0,
})
}