diff --git a/rsass/src/sass/functions/color/hsl.rs b/rsass/src/sass/functions/color/hsl.rs index e0dd745d..36e2c7c3 100644 --- a/rsass/src/sass/functions/color/hsl.rs +++ b/rsass/src/sass/functions/color/hsl.rs @@ -7,9 +7,8 @@ use super::{ use crate::css::{CallArgs, Value}; use crate::output::Format; use crate::sass::{ArgsError, FormalArgs, Name}; -use crate::value::{Color, Hsla, Numeric, Rational, Unit}; +use crate::value::{Color, Hsla, Numeric, Unit}; use crate::Scope; -use num_traits::{one, zero}; pub fn register(f: &mut Scope) { def_va!(f, _hsl(kwargs), |s| do_hsla(&name!(hsl), s)); @@ -32,10 +31,8 @@ pub fn register(f: &mut Scope) { Value::Color(col, _) => { let is_rgb = col.is_rgb(); let col = col.to_hsla(); - Ok( - Hsla::new(col.hue(), zero(), col.lum(), col.alpha(), !is_rgb) - .into(), - ) + Ok(Hsla::new(col.hue(), 0., col.lum(), col.alpha(), !is_rgb) + .into()) } v @ Value::Numeric(..) => Ok(Value::call("grayscale", [v])), v => Err(is_not(&v, "a color")).named(name!(color)), @@ -77,8 +74,10 @@ pub fn expose(m: &Scope, global: &mut FunctionMap) { def!(f, grayscale(color), |args| match args.get(name!(color))? { Value::Color(col, _) => { let col = col.to_hsla(); - Ok(Hsla::new(col.hue(), zero(), col.lum(), col.alpha(), false) - .into()) + Ok( + Hsla::new(col.hue(), 0., col.lum(), col.alpha(), false) + .into(), + ) } v => NumOrSpecial::try_from(v) .map_err(|e| is_not(e.value(), "a color")) @@ -94,7 +93,7 @@ pub fn expose(m: &Scope, global: &mut FunctionMap) { let col = s.get::(name!(color))?; let sat = s.get_map(name!(amount), check_amount)?; let col = col.to_hsla(); - let sat = (col.sat() + sat).clamp(zero(), one()); + let sat = (col.sat() + sat).clamp(0., 1.); Ok(Hsla::new(col.hue(), sat, col.lum(), col.alpha(), false) .into()) } @@ -186,7 +185,7 @@ fn hsla_from_values( } else { Ok(Hsla::new( check_hue(h).named(name!(hue))?, - check_pct_opt(s).named(name!(saturation))?, + f64::max(0., check_pct_opt(s).named(name!(saturation))?), check_pct_opt(l).named(name!(lightness))?, check_alpha(a).named(name!(alpha))?, true, // ?? @@ -195,13 +194,13 @@ fn hsla_from_values( } } -pub fn percentage(v: Rational) -> Value { +pub fn percentage(v: f64) -> Value { Numeric::percentage(v).into() } /// Gets a percentage as a fraction 0 .. 1. /// If v is not a percentage, keep it as it is. -fn check_pct_opt(v: Value) -> Result { +fn check_pct_opt(v: Value) -> Result { let v = Numeric::try_from(v)?; if !v.unit.is_percent() { // Note: The deprecation warning should include the parameter name @@ -214,7 +213,7 @@ fn check_pct_opt(v: Value) -> Result { v.unit ); } - Ok(v.as_ratio()? / 100) + Ok(f64::from(v.value) / 100.) } #[test] diff --git a/rsass/src/sass/functions/color/hwb.rs b/rsass/src/sass/functions/color/hwb.rs index a13955a2..2774218e 100644 --- a/rsass/src/sass/functions/color/hwb.rs +++ b/rsass/src/sass/functions/color/hwb.rs @@ -1,17 +1,14 @@ use super::super::FunctionMap; use super::hsl::percentage; use super::{ - check_alpha, check_expl_pct, eval_inner, is_not, relative_color, + check_alpha, check_expl_pct_norange, eval_inner, is_not, relative_color, CallError, CheckedArg, ResolvedArgs, }; use crate::css::{CallArgs, Value}; use crate::output::Format; use crate::sass::FormalArgs; -use crate::value::{ - Color, Hwba, ListSeparator, Numeric, Rational, Rgba, Unit, -}; +use crate::value::{Color, Hwba, ListSeparator, Numeric, Rgba, Unit}; use crate::Scope; -use num_traits::{one, zero}; pub fn register(f: &mut Scope) { def_va!(f, hwb(kwargs), hwb); @@ -57,14 +54,14 @@ fn hwb(s: &ResolvedArgs) -> Result { })? }; let hue = check_hue(hue).named(name!(hue))?; - let w = check_expl_pct(w).named(name!(whiteness))?; - let b = check_expl_pct(b).named(name!(blackness))?; + let w = check_expl_pct_norange(w).named(name!(whiteness))?; + let b = check_expl_pct_norange(b).named(name!(blackness))?; let a = check_alpha(a).named(name!(alpha))?; // I don't really agree with this, but it makes tests pass. - let hue = if w + b >= one() { zero() } else { hue }; + let hue = if w + b >= 1. { 0. } else { hue }; let hwba = Hwba::new(hue, w, b, a); let rgba = Rgba::from(&hwba); - if rgba.is_integer() { + if rgba.is_integer() && w >= 0. { Ok(rgba.into()) } else { Ok(hwba.into()) @@ -129,10 +126,10 @@ fn badchannels(v: &Value) -> CallError { )) } -fn check_hue(v: Value) -> Result { +fn check_hue(v: Value) -> Result { let vv = Numeric::try_from(v)?; if let Some(scaled) = vv.as_unit_def(Unit::Deg) { - Ok(scaled.as_ratio()?) + Ok(scaled.into()) } else { Err(is_not(&vv, "an angle")) } diff --git a/rsass/src/sass/functions/color/mod.rs b/rsass/src/sass/functions/color/mod.rs index 4a2c3b95..d7804869 100644 --- a/rsass/src/sass/functions/color/mod.rs +++ b/rsass/src/sass/functions/color/mod.rs @@ -6,9 +6,9 @@ use crate::css::{CallArgs, CssString, Value}; use crate::input::SourcePos; use crate::output::Format; use crate::sass::{FormalArgs, Name}; -use crate::value::{ListSeparator, Number, Numeric, Quotes, Rational, Unit}; +use crate::value::{ListSeparator, Numeric, Quotes, Unit}; use crate::Scope; -use num_traits::{one, zero, Signed}; +use num_traits::{one, zero}; mod channels; mod hsl; mod hwb; @@ -61,7 +61,7 @@ pub fn expose(m: &Scope, global: &mut FunctionMap) { /// For the alpha parameter of rgba, hsla, hwba functions /// Special perk: Defaults to 1.0 if the value is null. -fn check_alpha(v: Value) -> Result { +fn check_alpha(v: Value) -> Result { Ok(match v { Value::Null => one(), v => { @@ -70,31 +70,29 @@ fn check_alpha(v: Value) -> Result { .ok_or_else(|| { expected_to(num, "have unit \"%\" or no units") })? - .as_ratio()? + .into() } }) } /// Get a rational number in the 0..1 range. -fn check_alpha_range(v: Value) -> Result { +fn check_alpha_range(v: Value) -> Result { let v = Numeric::try_from(v)?; - let r = v.as_ratio()?; - if r < zero() || r > one() { + if v.value < zero() || v.value > one() { Err(expected_to(v, "be within 0 and 1")) } else { - Ok(r) + Ok(v.value.into()) } } -fn check_alpha_pm(v: Value) -> Result { +fn check_alpha_pm(v: Value) -> Result { let v = Numeric::try_from(v)?; - let r = v.as_ratio()?; - if r.abs() > one() { + if v.value.abs() > one() { Err(expected_to(v, "be within -1 and 1")) } else { - Ok(r) + Ok(v.value.into()) } } -fn check_hue(v: Value) -> Result { +fn check_hue(v: Value) -> Result { let v = Numeric::try_from(v)?; let v = match v.as_unit_def(Unit::Deg) { Some(v) => v, @@ -109,13 +107,13 @@ fn check_hue(v: Value) -> Result { v.value } }; - v.as_ratio().map_err(|e| e.to_string()) + Ok(v.into()) } -fn check_pct(v: Value) -> Result { +fn check_pct(v: Value) -> Result { let val = Numeric::try_from(v)?; match val.as_unit_def(Unit::Percent) { - Some(v) => Ok(v / 100), + Some(v) => Ok(f64::from(v) / 100.), None => { dep_warn!( "Passing a number without unit % ({}) is deprecated.\ @@ -124,12 +122,20 @@ fn check_pct(v: Value) -> Result { val.format(Format::introspect()), val.unit ); - Ok(val.value / 100) + Ok(f64::from(val.value) / 100.) } } } -fn check_expl_pct(v: Value) -> Result { +fn check_expl_pct_norange(v: Value) -> Result { + let val = Numeric::try_from(v)?; + if !val.unit.is_percent() { + Err(expected_to(val, "have unit \"%\"")) + } else { + Ok(f64::from(val.value) / 100.) + } +} +fn check_expl_pct(v: Value) -> Result { let val = Numeric::try_from(v)?; if !val.unit.is_percent() { return Err(expected_to(val, "have unit \"%\"")); @@ -137,11 +143,11 @@ fn check_expl_pct(v: Value) -> Result { if val.value < zero() || val.value > 100.into() { Err(expected_to(val, "be within 0% and 100%")) } else { - Ok(val.as_ratio()? / 100) + Ok(f64::from(val.value) / 100.) } } -fn check_pct_range(v: Value) -> Result { +fn check_pct_range(v: Value) -> Result { let val = check_pct(v)?; if val < zero() || val > one() { Err(expected_to( @@ -149,44 +155,47 @@ fn check_pct_range(v: Value) -> Result { "be within 0% and 100%", )) } else { - Ok(val.as_ratio()?) + Ok(val) } } -fn check_amount(v: Value) -> Result { +fn check_amount(v: Value) -> Result { let val = check_pct(v)?; if val < zero() || val > one() { - Err(expected_to(Value::scalar(val * 100), "be within 0 and 100")) + Err(expected_to( + Value::scalar(val * 100.), + "be within 0 and 100", + )) } else { - Ok(val.as_ratio()?) + Ok(val) } } -fn check_channel(v: Value) -> Result { +fn check_channel(v: Value) -> Result { num2chan(&Numeric::try_from(v)?) } -fn check_channel_range(v: Value) -> Result { +fn check_channel_range(v: Value) -> Result { let v = Numeric::try_from(v)?; let r = num2chan(&v)?; - if r > Rational::from_integer(255) || r < zero() { + if r > 255. || r < zero() { Err(expected_to(v, "be within 0 and 255")) } else { Ok(r) } } -fn check_channel_pm(v: Value) -> Result { +fn check_channel_pm(v: Value) -> Result { let v = Numeric::try_from(v)?; let r = num2chan(&v)?; - if r.abs() > Rational::from_integer(255) { + if r.abs() > 255. { Err(expected_to(v, "be within -255 and 255")) } else { Ok(r) } } -fn num2chan(v: &Numeric) -> Result { - let r = v.as_ratio()?; +fn num2chan(v: &Numeric) -> Result { + let r: f64 = v.value.clone().into(); if v.unit.is_percent() { - Ok(r * 255 / 100) + Ok(r * 255. / 100.) } else { Ok(r) } diff --git a/rsass/src/sass/functions/color/other.rs b/rsass/src/sass/functions/color/other.rs index d4a7064b..57b61743 100644 --- a/rsass/src/sass/functions/color/other.rs +++ b/rsass/src/sass/functions/color/other.rs @@ -1,16 +1,15 @@ use super::{ check_alpha_pm, check_alpha_range, check_channel_pm, check_channel_range, - check_expl_pct, check_hue, expected_to, CallError, CheckedArg, - FunctionMap, Name, + check_expl_pct, check_hue, check_pct, check_pct_range, expected_to, + CallError, CheckedArg, FunctionMap, Name, }; use crate::css::{CallArgs, Value}; -use crate::value::{Color, Hsla, Hwba, Numeric, Rational, RgbFormat, Rgba}; +use crate::value::{Color, Hsla, Hwba, Numeric, RgbFormat, Rgba}; use crate::Scope; -use num_traits::{one, zero, Signed}; pub fn register(f: &mut Scope) { def_va!(f, adjust(color, kwargs), |s| { - fn opt_add(a: Rational, b: Option) -> Rational { + fn opt_add(a: f64, b: Option) -> f64 { if let Some(b) = b { a + b } else { @@ -66,10 +65,7 @@ pub fn register(f: &mut Scope) { sat, lum, opt_add(hsla.alpha(), a_adj), - hsla.hsla_format - || sat > one() - || lum > one() - || lum < zero(), + hsla.hsla_format || sat > 1. || lum > 1. || lum < 0., ) .into()) } else { @@ -80,19 +76,18 @@ pub fn register(f: &mut Scope) { } }); def_va!(f, scale(color, kwargs), |s| { - let cmb = |orig: Rational, x: Option, max: Rational| match x - { + let cmb = |orig: f64, x: Option, max: f64| match x { None => orig, Some(x) => { - if x.is_positive() { + if x.is_sign_positive() { orig + (max - orig) * x } else { orig + orig * x } } }; - let one: Rational = one(); - let ff = Rational::from_integer(255); + let one = 1.0; + let ff = 255.0; let color: Color = s.get(name!(color))?; let mut args = s.get_map(name!(kwargs), CallArgs::from_value)?; @@ -188,9 +183,8 @@ pub fn register(f: &mut Scope) { return Ok(rgba.into()); } let hue = take_opt(&mut args, name!(hue), check_hue)?; - let sat = - take_opt(&mut args, name!(saturation), check_pct_opt_range)?; - let lig = take_opt(&mut args, name!(lightness), check_pct_opt_range)?; + let sat = take_opt(&mut args, name!(saturation), check_pct_range)?; + let lig = take_opt(&mut args, name!(lightness), check_pct_range)?; if sat.is_some() || lig.is_some() { no_more_in_space(&args, "hsl")?; } @@ -294,27 +288,15 @@ where args.named.remove(&name).map(check).transpose().named(name) } -fn check_pct(v: Value) -> Result { - Ok(Numeric::try_from(v)?.as_ratio()? / 100) -} -fn check_pct_expl_pm(v: Value) -> Result { +fn check_pct_expl_pm(v: Value) -> Result { let val = Numeric::try_from(v)?; if !val.unit.is_percent() { return Err(expected_to(val, "have unit \"%\"")); } - if val.value.abs() > 100.into() { + if f64::from(val.value.abs()) > 100. { Err(expected_to(val, "be within -100% and 100%")) } else { - Ok(val.as_ratio()? / 100) - } -} - -fn check_pct_opt_range(v: Value) -> Result { - let val = Numeric::try_from(v)?; - if val.value < zero() || val.value > 100.into() { - Err(expected_to(val, "be within 0% and 100%")) - } else { - Ok(val.as_ratio()? / 100) + Ok(f64::from(val.value) / 100.) } } diff --git a/rsass/src/sass/functions/color/rgb.rs b/rsass/src/sass/functions/color/rgb.rs index b539f150..bbd3f543 100644 --- a/rsass/src/sass/functions/color/rgb.rs +++ b/rsass/src/sass/functions/color/rgb.rs @@ -6,9 +6,8 @@ use super::{ }; use crate::css::{CallArgs, Value}; use crate::sass::{ArgsError, FormalArgs, Name}; -use crate::value::{Color, Rational, RgbFormat, Rgba}; +use crate::value::{Color, RgbFormat, Rgba}; use crate::Scope; -use num_traits::{one, Zero}; pub fn register(f: &mut Scope) { def_va!(f, _rgb(kwargs), |s| do_rgba(&name!(rgb), s)); @@ -31,26 +30,25 @@ pub fn register(f: &mut Scope) { let b: Color = s.get(name!(color2))?; let b = b.to_rgba(); let w = s.get_map(name!(weight), check_pct_range)?; - let one: Rational = one(); let w_a = { let wa = a.alpha() - b.alpha(); - let w2 = w * 2 - 1; - let divis = w2 * wa + 1; - if divis.is_zero() { + let w2 = w * 2. - 1.; + let divis = w2 * wa + 1.; + if divis == 0. { w } else { - (((w2 + wa) / divis) + 1) / 2 + (((w2 + wa) / divis) + 1.) / 2. } }; - let w_b = one - w_a; + let w_b = 1. - w_a; let m_c = |c_a, c_b| w_a * c_a + w_b * c_b; Ok(Rgba::new( m_c(a.red(), b.red()), m_c(a.green(), b.green()), m_c(a.blue(), b.blue()), - a.alpha() * w + b.alpha() * (one - w), + a.alpha() * w + b.alpha() * (1. - w), RgbFormat::Name, ) .into()) @@ -63,7 +61,7 @@ pub fn register(f: &mut Scope) { } col => { let w = s.get_map(name!(weight), check_pct_range)?; - if w == one() { + if w == 1. { match col { v @ Value::Numeric(..) => { Ok(Value::call("invert", [v])) @@ -98,7 +96,7 @@ pub fn expose(m: &Scope, global: &mut FunctionMap) { } col => { let w = s.get_map(name!(weight), check_pct_range)?; - if w == one() { + if w == 1. { NumOrSpecial::try_from(col) .map_err(|e| is_not(e.value(), "a color")) .named(name!(color)) diff --git a/rsass/src/value/colors/convert.rs b/rsass/src/value/colors/convert.rs index a6cb3e60..49da3fa6 100644 --- a/rsass/src/value/colors/convert.rs +++ b/rsass/src/value/colors/convert.rs @@ -1,34 +1,34 @@ -use super::*; +use super::{Hsla, Hwba, RgbFormat, Rgba}; impl From<&Hsla> for Rgba { fn from(hsla: &Hsla) -> Self { - let hue = hsla.hue() / 360; + let hue = hsla.hue() / 360.; let sat = hsla.sat(); let lum = hsla.lum(); - if sat.is_zero() { - let gray = lum * 255; + if sat == 0. { + let gray = lum * 255.; Self::new(gray, gray, gray, hsla.alpha(), RgbFormat::Name) } else { - fn hue2rgb(p: Rational, q: Rational, t: Rational) -> Rational { - let t = (t - t.floor()) * 6; - match t.to_integer() { + fn hue2rgb(p: f64, q: f64, t: f64) -> f64 { + let t = (t - t.floor()) * 6.; + match t as u8 { 0 => p + (q - p) * t, 1 | 2 => q, - 3 => p + (p - q) * (t - 4), + 3 => p + (p - q) * (t - 4.), _ => p, } } - let q = if lum < Rational::new(1, 2) { - lum * (sat + 1) + let q = if lum < 0.5 { + lum * (sat + 1.) } else { lum + sat - lum * sat }; - let p = lum * 2 - q; - + let p = lum * 2. - q; + const THIRD: f64 = 1. / 3.; Self::new( - hue2rgb(p, q, hue + Rational::new(1, 3)) * 255, - hue2rgb(p, q, hue) * 255, - hue2rgb(p, q, hue - Rational::new(1, 3)) * 255, + hue2rgb(p, q, hue + THIRD) * 255., + hue2rgb(p, q, hue) * 255., + hue2rgb(p, q, hue - THIRD) * 255., hsla.alpha(), RgbFormat::Name, ) @@ -46,34 +46,39 @@ impl From<&Hwba> for Hsla { fn from(hwba: &Hwba) -> Self { let w = hwba.whiteness(); let b = hwba.blackness(); - let l = (Rational::one() - b + w) / 2; - let s = if l.is_zero() || l.is_one() { - zero() + let l = (1. - b + w) / 2.; + let s = if l == 0. || l == 1. { + 0. + } else { + (1. - b - l) / f64::min(l, 1. - l) + }; + let (hue, lum) = if w.is_finite() && b.is_finite() { + (hwba.hue(), l) } else { - (Rational::one() - b - l) / std::cmp::min(l, Rational::one() - l) + (f64::NAN, f64::NAN) }; - Self::new(hwba.hue(), s, l, hwba.alpha(), false) + Self::new(hue, s, lum, hwba.alpha(), false) } } impl From<&Rgba> for Hsla { fn from(rgba: &Rgba) -> Self { let (red, green, blue) = - (rgba.red() / 255, rgba.green() / 255, rgba.blue() / 255); + (rgba.red() / 255., rgba.green() / 255., rgba.blue() / 255.); let (max, min, largest) = max_min_largest(red, green, blue); if max == min { - Self::new(zero(), zero(), max, rgba.alpha(), false) + Self::new(0., 0., max, rgba.alpha(), false) } else { let d = max - min; let hue = match largest { - 0 => (green - blue) / d + if green < blue { 6 } else { 0 }, - 1 => (blue - red) / d + 2, - _ => (red - green) / d + 4, - } * (360 / 6); + 0 => (green - blue) / d + if green < blue { 6. } else { 0. }, + 1 => (blue - red) / d + 2., + _ => (red - green) / d + 4., + } * (360. / 6.); let mm = max + min; - let sat = d / if mm > one() { -mm + 2 } else { mm }; - Self::new(hue, sat, mm / 2, rgba.alpha(), false) + let sat = d / if mm > 1. { -mm + 2. } else { mm }; + Self::new(hue, sat, mm / 2., rgba.alpha(), false) } } } @@ -81,11 +86,10 @@ impl From<&Rgba> for Hsla { impl From<&Rgba> for Hwba { fn from(rgba: &Rgba) -> Self { let hsla = Hsla::from(rgba); - let arr = [rgba.red(), rgba.blue(), rgba.green()]; Self::new( hsla.hue(), - *arr.iter().min().unwrap() / 255, - Rational::one() - *arr.iter().max().unwrap() / 255, + rgba.red().min(rgba.blue()).min(rgba.green()) / 255., + 1. - rgba.red().max(rgba.blue()).max(rgba.green()) / 255., hsla.alpha(), ) } @@ -93,24 +97,26 @@ impl From<&Rgba> for Hwba { impl From<&Hsla> for Hwba { fn from(hsla: &Hsla) -> Self { let rgba = Rgba::from(hsla); - let arr = [rgba.red(), rgba.blue(), rgba.green()]; Self::new( hsla.hue(), - Rational::one() - *arr.iter().max().unwrap() / 255, - *arr.iter().min().unwrap() / 255, + rgba.red().min(rgba.blue()).min(rgba.green()) / 255., + 1. - rgba.red().max(rgba.blue()).max(rgba.green()) / 255., + // f64::one() - *arr.iter().max().unwrap() / 255, + // *arr.iter().min().unwrap() / 255, hsla.alpha(), ) } } // Find which of three numbers are largest and smallest -fn max_min_largest( - a: Rational, - b: Rational, - c: Rational, -) -> (Rational, Rational, u32) { - let v = [(a, 0), (b, 1), (c, 2)]; - let max = v.iter().max().unwrap(); - let min = v.iter().min().unwrap(); - (max.0, min.0, max.1) +fn max_min_largest(a: f64, b: f64, c: f64) -> (f64, f64, u32) { + let (max, largest) = if a > b && a > c { + (a, 0) + } else if b > a && b > c { + (b, 1) + } else { + (c, 2) + }; + let min = a.min(b).min(c); + (max, min, largest) } diff --git a/rsass/src/value/colors/hsla.rs b/rsass/src/value/colors/hsla.rs index 70a9e762..55bed948 100644 --- a/rsass/src/value/colors/hsla.rs +++ b/rsass/src/value/colors/hsla.rs @@ -1,67 +1,66 @@ +use crate::css::Value; use crate::output::{Format, Formatted}; -use crate::value::{Number, Rational}; -use num_traits::{one, zero, One as _, Signed}; +use crate::value::{Number, Numeric}; use std::fmt::{self, Display}; /// A color defined by hue, saturation, luminance, and alpha. -#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] +#[derive(Clone, Debug, PartialEq, PartialOrd)] pub struct Hsla { - hue: Rational, - sat: Rational, - lum: Rational, - alpha: Rational, + hue: f64, + sat: f64, + lum: f64, + alpha: f64, pub(crate) hsla_format: bool, } impl Hsla { /// Create a new hsla color. pub fn new( - hue: Rational, - sat: Rational, - lum: Rational, - alpha: Rational, + hue: f64, + sat: f64, + lum: f64, + alpha: f64, hsla_format: bool, ) -> Self { Self { hue: deg_mod(hue), - sat: sat.max(zero()), + sat: sat.clamp(0., f64::INFINITY), lum, - alpha: alpha.clamp(zero(), one()), + alpha: alpha.max(0.).min(1.), hsla_format, } } /// Get the hue of this color. - pub fn hue(&self) -> Rational { + pub fn hue(&self) -> f64 { self.hue } /// Get the saturation of this color. - pub fn sat(&self) -> Rational { + pub fn sat(&self) -> f64 { self.sat } /// Get the lumination of this color. - pub fn lum(&self) -> Rational { + pub fn lum(&self) -> f64 { self.lum } /// Get the alpha value of this color. /// /// Zero is fully transparent, one is fully opaque. - pub fn alpha(&self) -> Rational { + pub fn alpha(&self) -> f64 { self.alpha } /// Set the alpha value of this color. /// /// Zero is fully transparent, one is fully opaque. - pub fn set_alpha(&mut self, alpha: Rational) { - self.alpha = alpha.clamp(zero(), one()); + pub fn set_alpha(&mut self, alpha: f64) { + self.alpha = alpha.clamp(0., 1.); } - pub(crate) fn invert(&self, weight: Rational) -> Self { - let one = Rational::one(); + pub(crate) fn invert(&self, weight: f64) -> Self { Self { - hue: deg_mod(self.hue + 180), + hue: deg_mod(self.hue + 180.), sat: self.sat, - lum: (one - self.lum) * weight + self.lum * (one - weight), + lum: (1. - self.lum) * weight + self.lum * (1. - weight), alpha: self.alpha, hsla_format: self.hsla_format, } @@ -81,10 +80,10 @@ impl Hsla { } /// Value is an angle in degrees, return same angle, but 0 <= value < 360.x -fn deg_mod(value: Rational) -> Rational { - let turn = Rational::from_integer(360); +fn deg_mod(value: f64) -> f64 { + let turn = 360.; let value = value % turn; - if value.is_negative() { + if value.is_sign_negative() { value + turn } else { value @@ -94,26 +93,28 @@ fn deg_mod(value: Rational) -> Rational { impl<'a> Display for Formatted<'a, Hsla> { fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result { let hsla = self.value; - let hue = Number::from(hsla.hue); - let sat = Number::from(hsla.sat * 100); - let lum = Number::from(hsla.lum * 100); + // Special: Don't round the hue to 360! + let hue = if hsla.hue + 1e-7 > 360. { 0. } else { hsla.hue }; + let hue = Value::scalar(hue); + let sat = Value::from(Numeric::percentage(hsla.sat)); + let lum = Value::from(Numeric::percentage(hsla.lum)); let a = hsla.alpha; - if a >= one() { + if a >= 1. { write!( out, - "hsl({}, {}%, {}%)", - hue.format(self.format), - sat.format(self.format), - lum.format(self.format), + "hsl({}, {}, {})", + hue.to_string(self.format), + sat.to_string(self.format), + lum.to_string(self.format), ) } else { let a = Number::from(a); write!( out, - "hsla({}, {}%, {}%, {})", - hue.format(self.format), - sat.format(self.format), - lum.format(self.format), + "hsla({}, {}, {}, {})", + hue.to_string(self.format), + sat.to_string(self.format), + lum.to_string(self.format), a.format(self.format) ) } diff --git a/rsass/src/value/colors/hwba.rs b/rsass/src/value/colors/hwba.rs index 17f35da5..d76aced0 100644 --- a/rsass/src/value/colors/hwba.rs +++ b/rsass/src/value/colors/hwba.rs @@ -1,6 +1,3 @@ -use super::Rational; -use num_traits::{one, zero}; - /// A color defined by hue, whiteness, blackness, and alpha. /// /// All components are rational numbers. @@ -8,12 +5,12 @@ use num_traits::{one, zero}; /// The whiteness, blackness, and alpha are all in the zero to one /// range (inclusive), whith the additional invariant that whiteness + /// blackness will never be more than one. -#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] +#[derive(Clone, Debug, PartialEq, PartialOrd)] pub struct Hwba { - hue: Rational, - w: Rational, - b: Rational, - alpha: Rational, + hue: f64, + w: f64, + b: f64, + alpha: f64, } impl Hwba { @@ -21,16 +18,11 @@ impl Hwba { /// /// Hue is modulo 360 degrees. Other inputs will be clamped to /// their ranges. - pub fn new( - hue: Rational, - w: Rational, - b: Rational, - alpha: Rational, - ) -> Self { - let mut w = w.clamp(zero(), one()); - let mut b = b.clamp(zero(), one()); + pub fn new(hue: f64, w: f64, b: f64, alpha: f64) -> Self { + let mut w = w; + let mut b = b; let wbsum = w + b; - if w + b > one() { + if !(wbsum < 1.) { w /= wbsum; b /= wbsum; } @@ -38,36 +30,36 @@ impl Hwba { hue, w, b, - alpha: alpha.clamp(zero(), one()), + alpha: alpha.clamp(0., 1.), } } /// Get the hue of this color. - pub fn hue(&self) -> Rational { + pub fn hue(&self) -> f64 { self.hue } /// Get the whiteness of this color. /// /// Zero is no whiteness, one means this color is white. - pub fn whiteness(&self) -> Rational { + pub fn whiteness(&self) -> f64 { self.w } /// Get the black of this color. /// /// Zero is no blackness, one means this color is black. - pub fn blackness(&self) -> Rational { + pub fn blackness(&self) -> f64 { self.b } /// Get the alpha value of this color. /// /// Zero is fully transparent, one is fully opaque. - pub fn alpha(&self) -> Rational { + pub fn alpha(&self) -> f64 { self.alpha } /// Set the alpha value of this color. /// /// Zero is fully transparent, one is fully opaque. - pub fn set_alpha(&mut self, alpha: Rational) { - self.alpha = alpha.clamp(zero(), one()); + pub fn set_alpha(&mut self, alpha: f64) { + self.alpha = alpha.clamp(0., 1.); } } diff --git a/rsass/src/value/colors/mod.rs b/rsass/src/value/colors/mod.rs index fbd33653..42f94e0a 100644 --- a/rsass/src/value/colors/mod.rs +++ b/rsass/src/value/colors/mod.rs @@ -7,14 +7,12 @@ mod rgba; pub use self::hsla::Hsla; pub use self::hwba::Hwba; pub use self::rgba::{RgbFormat, Rgba}; -use super::Rational; use crate::output::{Format, Formatted}; -use num_traits::{one, zero, One, Zero}; use std::borrow::Cow; use std::fmt::{self, Display}; /// A color in sass/css. May be a Rgba, Hsla, or Hwba value. -#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] +#[derive(Clone, Debug, PartialEq)] pub enum Color { /// A rgba color, defined by red, green, blue and alpha components. Rgba(Rgba), @@ -24,6 +22,27 @@ pub enum Color { Hwba(Hwba), } +impl Eq for Color {} +impl Ord for Color { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + match (self, other) { + (Color::Hsla(a), Color::Hsla(b)) => a.partial_cmp(b).unwrap(), + (Color::Hsla(a), Color::Hwba(b)) => { + a.partial_cmp(&Hsla::from(b)).unwrap() + } + (Color::Hwba(a), Color::Hsla(b)) => { + Hsla::from(a).partial_cmp(b).unwrap() + } + (a, b) => a.to_rgba().cmp(&b.to_rgba()), + } + } +} +impl PartialOrd for Color { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + impl Color { pub(crate) fn is_rgb(&self) -> bool { matches!(self, Self::Rgba(_)) @@ -66,7 +85,7 @@ impl Color { /// Get the alpha channel of this color. /// /// The alpha channel is a rational value between 0 and 1. - pub fn get_alpha(&self) -> Rational { + pub fn get_alpha(&self) -> f64 { match self { Self::Rgba(rgba) => rgba.alpha(), Self::Hsla(hsla) => hsla.alpha(), @@ -76,8 +95,8 @@ impl Color { /// Set the alpha channel of this color. /// /// The alpha channel is a rational value between 0 and 1. - pub fn set_alpha(&mut self, alpha: Rational) { - let alpha = alpha.clamp(zero(), one()); + pub fn set_alpha(&mut self, alpha: f64) { + let alpha = alpha.clamp(0., 1.); match self { Self::Rgba(ref mut rgba) => rgba.set_alpha(alpha), Self::Hsla(ref mut hsla) => hsla.set_alpha(alpha), @@ -85,7 +104,7 @@ impl Color { } } /// Rotate the hue of this color by a specific number of degrees. - pub fn rotate_hue(&self, val: Rational) -> Self { + pub fn rotate_hue(&self, val: f64) -> Self { match self { Self::Rgba(rgba) => { let hsla = Hsla::from(rgba); @@ -115,7 +134,7 @@ impl Color { .into(), } } - pub(crate) fn invert(&self, weight: Rational) -> Self { + pub(crate) fn invert(&self, weight: f64) -> Self { match self { Color::Rgba(rgba) => rgba.invert(weight).into(), Color::Hsla(hsla) => hsla.invert(weight).into(), diff --git a/rsass/src/value/colors/rgba.rs b/rsass/src/value/colors/rgba.rs index fd7bd3d0..a4cf7d10 100644 --- a/rsass/src/value/colors/rgba.rs +++ b/rsass/src/value/colors/rgba.rs @@ -1,10 +1,8 @@ //! Color names from #![allow(clippy::unreadable_literal)] -use super::Rational; use crate::output::{Format, Formatted}; use crate::value::Number; use lazy_static::lazy_static; -use num_traits::{one, zero, One, Signed, Zero}; use std::cmp::Ordering; use std::collections::BTreeMap; use std::fmt::{self, Display}; @@ -12,10 +10,10 @@ use std::fmt::{self, Display}; /// A color defined by red, green, blue, and alpha components. #[derive(Clone, Debug)] pub struct Rgba { - red: Rational, - green: Rational, - blue: Rational, - alpha: Rational, + red: f64, + green: f64, + blue: f64, + alpha: f64, source: RgbFormat, } @@ -34,46 +32,39 @@ pub enum RgbFormat { impl Rgba { /// Create a new rgba color. - pub fn new( - r: Rational, - g: Rational, - b: Rational, - a: Rational, - s: RgbFormat, - ) -> Self { - let ff = Rational::new(255, 1); - let one = Rational::one(); + pub fn new(r: f64, g: f64, b: f64, a: f64, s: RgbFormat) -> Self { + let ff = 255.; Self { - red: cap(r, &ff), - green: cap(g, &ff), - blue: cap(b, &ff), - alpha: cap(a, &one), + red: cap(r, ff), + green: cap(g, ff), + blue: cap(b, ff), + alpha: cap(a, 1.), source: s, } } /// Create a color from rgb byte values. pub fn from_rgb(r: u8, g: u8, b: u8) -> Self { Self { - red: Rational::from_integer(r.into()), - green: Rational::from_integer(g.into()), - blue: Rational::from_integer(b.into()), - alpha: Rational::one(), + red: r.into(), + green: g.into(), + blue: b.into(), + alpha: 1.0, source: RgbFormat::LongHex, } } /// Create a color from rgba byte values. pub fn from_rgba(r: u8, g: u8, b: u8, a: u8) -> Self { Self { - red: Rational::from_integer(r.into()), - green: Rational::from_integer(g.into()), - blue: Rational::from_integer(b.into()), - alpha: Rational::from_integer(a.into()) / 255, + red: r.into(), + green: g.into(), + blue: b.into(), + alpha: f64::from(a) / 255., source: RgbFormat::LongHex, } } fn is_opaque(&self) -> bool { - self.alpha >= one() + self.alpha >= 1. } /// If this color is equal to a named color, get the name. pub fn name(&self) -> Option<&'static str> { @@ -86,46 +77,37 @@ impl Rgba { let name = name.to_lowercase(); let name: &str = &name; if name == "transparent" { - return Some(Self::new( - zero(), - zero(), - zero(), - zero(), - RgbFormat::Name, - )); + return Some(Self::new(0., 0., 0., 0., RgbFormat::Name)); } LOOKUP.n2v.get(name).map(|n| { let [_, r, g, b] = n.to_be_bytes(); - Self::new( - i64::from(r).into(), - i64::from(g).into(), - i64::from(b).into(), - one(), - RgbFormat::Name, - ) + Self::new(r.into(), g.into(), b.into(), 1., RgbFormat::Name) }) } /// Return true if all chanels are zero. pub fn all_zero(&self) -> bool { - self.alpha.is_zero() - && self.red.is_zero() - && self.green.is_zero() - && self.blue.is_zero() + self.alpha == 0. + && self.red == 0. + && self.green == 0. + && self.blue == 0. } pub(crate) fn is_integer(&self) -> bool { - self.red.is_integer() - && self.green.is_integer() - && self.blue.is_integer() + near_integer(self.red) + && near_integer(self.green) + && near_integer(self.blue) && self.is_opaque() } /// Get a (r, g, b, a) byte-value tuple for this color. pub fn to_bytes(&self) -> (u8, u8, u8, u8) { - fn byte(v: Rational) -> u8 { - v.round().to_integer() as u8 + fn byte(v: f64) -> u8 { + v.round() as u8 } - let a = self.alpha * 255; - (byte(self.red), byte(self.green), byte(self.blue), byte(a)) + fn fb(v: f64) -> u8 { + v.round() as u8 + } + let a = self.alpha * 255.; + (byte(self.red), byte(self.green), byte(self.blue), fb(a)) } /// Get a (r, g, b) byte-value tuple for this color. /// @@ -135,9 +117,9 @@ impl Rgba { if !self.is_opaque() { return None; } - fn byte(v: Rational) -> Option { - if v.is_integer() { - Some(v.round().to_integer() as u8) + fn byte(v: f64) -> Option { + if (v.round() - v).abs() < 1e-7 { + Some(v.round() as u8) } else { None } @@ -151,32 +133,32 @@ impl Rgba { } } /// Get the red component. - pub fn red(&self) -> Rational { + pub fn red(&self) -> f64 { self.red } /// Get the green component. - pub fn green(&self) -> Rational { + pub fn green(&self) -> f64 { self.green } /// Get the blue component. - pub fn blue(&self) -> Rational { + pub fn blue(&self) -> f64 { self.blue } /// Get the alpha value of this color. /// /// Zero is fully transparent, one is fully opaque. - pub fn alpha(&self) -> Rational { + pub fn alpha(&self) -> f64 { self.alpha } /// Set the alpha value of this color. /// /// Zero is fully transparent, one is fully opaque. - pub fn set_alpha(&mut self, alpha: Rational) { - self.alpha = cap(alpha, &one()); + pub fn set_alpha(&mut self, alpha: f64) { + self.alpha = alpha.clamp(0., 1.); } - pub(crate) fn invert(&self, weight: Rational) -> Self { - let inv = |v: Rational| -(v - 255) * weight + v * -(weight - 1); + pub(crate) fn invert(&self, weight: f64) -> Self { + let inv = |v: f64| -(v - 255.) * weight + v * (1. - weight); Rgba::new( inv(self.red()), inv(self.green()), @@ -216,10 +198,11 @@ impl Ord for Rgba { fn cmp(&self, other: &Self) -> Ordering { // ignores source! self.red - .cmp(&other.red) - .then_with(|| self.green.cmp(&other.green)) - .then_with(|| self.blue.cmp(&other.blue)) - .then_with(|| self.alpha.cmp(&other.alpha)) + .partial_cmp(&other.red) + .unwrap() + .then_with(|| self.green.partial_cmp(&other.green).unwrap()) + .then_with(|| self.blue.partial_cmp(&other.blue).unwrap()) + .then_with(|| self.alpha.partial_cmp(&other.alpha).unwrap()) } } impl PartialOrd for Rgba { @@ -228,14 +211,8 @@ impl PartialOrd for Rgba { } } -fn cap(n: Rational, max: &Rational) -> Rational { - if n > *max { - *max - } else if n.is_negative() { - Rational::zero() - } else { - n - } +fn cap(n: f64, max: f64) -> f64 { + f64::min(f64::max(0., n), max) } #[test] @@ -508,3 +485,7 @@ fn write_rgba( } } } + +fn near_integer(v: f64) -> bool { + (v - v.round()).abs() < 1e-7 +} diff --git a/rsass/tests/spec/core_functions/color/adjust/hwb.rs b/rsass/tests/spec/core_functions/color/adjust/hwb.rs index bfdb26b4..5fcde0b7 100644 --- a/rsass/tests/spec/core_functions/color/adjust/hwb.rs +++ b/rsass/tests/spec/core_functions/color/adjust/hwb.rs @@ -90,7 +90,6 @@ mod blackness { ); } #[test] - #[ignore] // wrong result fn max() { assert_eq!( runner().ok("@use \"sass:color\";\ @@ -179,7 +178,6 @@ mod whiteness { ); } #[test] - #[ignore] // wrong result fn max() { assert_eq!( runner().ok("@use \"sass:color\";\ diff --git a/rsass/tests/spec/core_functions/color/hsl/four_args/out_of_gamut.rs b/rsass/tests/spec/core_functions/color/hsl/four_args/out_of_gamut.rs index 90f3e92f..3c18740a 100644 --- a/rsass/tests/spec/core_functions/color/hsl/four_args/out_of_gamut.rs +++ b/rsass/tests/spec/core_functions/color/hsl/four_args/out_of_gamut.rs @@ -14,7 +14,6 @@ mod alpha { use super::runner; #[test] - #[ignore] // unexepected error fn nan() { assert_eq!( runner().ok("a {b: hsl(0, 100%, 50%, calc(NaN))}\n"), @@ -24,7 +23,6 @@ mod alpha { ); } #[test] - #[ignore] // unexepected error fn negative_infinity() { assert_eq!( runner().ok("a {b: hsl(0, 100%, 50%, calc(-infinity))}\n"), @@ -34,7 +32,6 @@ mod alpha { ); } #[test] - #[ignore] // unexepected error fn positive_infinity() { assert_eq!( runner().ok("a {b: hsl(0, 100%, 50%, calc(infinity))}\n"), @@ -77,7 +74,6 @@ mod hue { use super::runner; #[test] - #[ignore] // unexepected error fn nan() { assert_eq!( runner().ok("a {b: hsl(calc(NaN), 100%, 50%)}\n"), @@ -87,7 +83,6 @@ mod hue { ); } #[test] - #[ignore] // unexepected error fn negative_infinity() { assert_eq!( runner().ok("a {b: hsl(calc(-infinity), 100%, 50%)}\n"), @@ -97,7 +92,6 @@ mod hue { ); } #[test] - #[ignore] // unexepected error fn positive_infinity() { assert_eq!( runner().ok("a {b: hsl(calc(infinity), 100%, 50%)}\n"), @@ -117,7 +111,6 @@ mod lightness { use super::runner; #[test] - #[ignore] // unexepected error fn nan() { assert_eq!( runner().ok("a {b: hsl(0, 100%, calc(NaN))}\n"), @@ -127,7 +120,6 @@ mod lightness { ); } #[test] - #[ignore] // unexepected error fn negative_infinity() { assert_eq!( runner().ok("a {b: hsl(0, 100%, calc(-infinity))}\n"), @@ -137,7 +129,6 @@ mod lightness { ); } #[test] - #[ignore] // unexepected error fn positive_infinity() { assert_eq!( runner().ok("a {b: hsl(0, 100%, calc(infinity))}\n"), @@ -166,7 +157,6 @@ mod saturation { use super::runner; #[test] - #[ignore] // unexepected error fn nan() { assert_eq!( runner().ok("a {b: hsl(0, calc(NaN), 50%)}\n"), @@ -176,7 +166,6 @@ mod saturation { ); } #[test] - #[ignore] // unexepected error fn negative_infinity() { assert_eq!( runner().ok("a {b: hsl(0, calc(-infinity), 50%)}\n"), @@ -186,7 +175,6 @@ mod saturation { ); } #[test] - #[ignore] // unexepected error fn positive_infinity() { assert_eq!( runner().ok("a {b: hsl(0, calc(infinity), 50%)}\n"), diff --git a/rsass/tests/spec/core_functions/color/hwb/four_args.rs b/rsass/tests/spec/core_functions/color/hwb/four_args.rs index 189594c4..76e95793 100644 --- a/rsass/tests/spec/core_functions/color/hwb/four_args.rs +++ b/rsass/tests/spec/core_functions/color/hwb/four_args.rs @@ -14,7 +14,6 @@ mod alpha { use super::runner; #[test] - #[ignore] // unexepected error fn nan() { assert_eq!( runner().ok("@use \"sass:color\";\ @@ -25,7 +24,6 @@ mod alpha { ); } #[test] - #[ignore] // unexepected error fn negative_infinity() { assert_eq!( runner().ok("@use \"sass:color\";\ @@ -36,7 +34,6 @@ mod alpha { ); } #[test] - #[ignore] // unexepected error fn positive_infinity() { assert_eq!( runner().ok("@use \"sass:color\";\ @@ -174,7 +171,6 @@ mod blackness { use super::runner; #[test] - #[ignore] // unexepected error fn above_max() { assert_eq!( runner().ok("@use \"sass:color\";\ @@ -185,7 +181,6 @@ mod blackness { ); } #[test] - #[ignore] // unexepected error fn below_min() { assert_eq!( runner().ok("@use \"sass:color\";\ @@ -200,7 +195,6 @@ mod blackness { use super::runner; #[test] - #[ignore] // unexepected error fn nan() { assert_eq!( runner().ok("@use \"sass:color\";\ @@ -211,7 +205,6 @@ mod blackness { ); } #[test] - #[ignore] // unexepected error fn negative_infinity() { assert_eq!( runner().ok("@use \"sass:color\";\ @@ -222,7 +215,6 @@ mod blackness { ); } #[test] - #[ignore] // unexepected error fn positive_infinity() { assert_eq!( runner().ok("@use \"sass:color\";\ @@ -254,7 +246,7 @@ mod hue { use super::runner; #[test] - #[ignore] // unexepected error + #[ignore] // wrong result fn nan() { assert_eq!( runner().ok("@use \"sass:color\";\ @@ -265,7 +257,7 @@ mod hue { ); } #[test] - #[ignore] // unexepected error + #[ignore] // wrong result fn negative_infinity() { assert_eq!( runner().ok("@use \"sass:color\";\ @@ -276,7 +268,7 @@ mod hue { ); } #[test] - #[ignore] // unexepected error + #[ignore] // wrong result fn positive_infinity() { assert_eq!( runner().ok("@use \"sass:color\";\ @@ -316,7 +308,6 @@ mod whiteness { use super::runner; #[test] - #[ignore] // unexepected error fn above_max() { assert_eq!( runner().ok("@use \"sass:color\";\ @@ -327,7 +318,6 @@ mod whiteness { ); } #[test] - #[ignore] // unexepected error fn below_min() { assert_eq!( runner().ok("@use \"sass:color\";\ @@ -342,7 +332,6 @@ mod whiteness { use super::runner; #[test] - #[ignore] // unexepected error fn nan() { assert_eq!( runner().ok("@use \"sass:color\";\ @@ -353,7 +342,6 @@ mod whiteness { ); } #[test] - #[ignore] // unexepected error fn negative_infinity() { assert_eq!( runner().ok("@use \"sass:color\";\ @@ -364,7 +352,6 @@ mod whiteness { ); } #[test] - #[ignore] // unexepected error fn positive_infinity() { assert_eq!( runner().ok("@use \"sass:color\";\ diff --git a/rsass/tests/spec/core_functions/color/hwb/one_arg.rs b/rsass/tests/spec/core_functions/color/hwb/one_arg.rs index d9174252..8a157e71 100644 --- a/rsass/tests/spec/core_functions/color/hwb/one_arg.rs +++ b/rsass/tests/spec/core_functions/color/hwb/one_arg.rs @@ -109,7 +109,6 @@ mod blackness { use super::runner; #[test] - #[ignore] // unexepected error fn above_max() { assert_eq!( runner().ok("@use \"sass:color\";\ @@ -120,7 +119,6 @@ mod blackness { ); } #[test] - #[ignore] // unexepected error fn below_min() { assert_eq!( runner().ok("@use \"sass:color\";\ @@ -382,7 +380,6 @@ mod whiteness { use super::runner; #[test] - #[ignore] // unexepected error fn above_max() { assert_eq!( runner().ok("@use \"sass:color\";\ @@ -393,7 +390,6 @@ mod whiteness { ); } #[test] - #[ignore] // unexepected error fn below_min() { assert_eq!( runner().ok("@use \"sass:color\";\ diff --git a/rsass/tests/spec/core_functions/color/rgb/four_args/clamped.rs b/rsass/tests/spec/core_functions/color/rgb/four_args/clamped.rs index d19d382c..559087fe 100644 --- a/rsass/tests/spec/core_functions/color/rgb/four_args/clamped.rs +++ b/rsass/tests/spec/core_functions/color/rgb/four_args/clamped.rs @@ -32,7 +32,6 @@ mod alpha { use super::runner; #[test] - #[ignore] // unexepected error fn nan() { assert_eq!( runner().ok("a {b: rgb(0, 0, 0, calc(NaN))}\n"), @@ -42,7 +41,6 @@ mod alpha { ); } #[test] - #[ignore] // unexepected error fn negative_infinity() { assert_eq!( runner().ok("a {b: rgb(0, 0, 0, calc(-infinity))}\n"), @@ -52,7 +50,6 @@ mod alpha { ); } #[test] - #[ignore] // unexepected error fn positive_infinity() { assert_eq!( runner().ok("a {b: rgb(0, 0, 0, calc(infinity))}\n"), @@ -72,7 +69,6 @@ mod blue { use super::runner; #[test] - #[ignore] // unexepected error fn nan() { assert_eq!( runner().ok("a {b: rgb(0, 0, calc(NaN), 0.5)}\n"), @@ -82,7 +78,6 @@ mod blue { ); } #[test] - #[ignore] // unexepected error fn negative_infinity() { assert_eq!( runner().ok("a {b: rgb(0, 0, calc(-infinity), 0.5)}\n"), @@ -92,7 +87,6 @@ mod blue { ); } #[test] - #[ignore] // unexepected error fn positive_infinity() { assert_eq!( runner().ok("a {b: rgb(0, 0, calc(infinity), 0.5)}\n"), @@ -121,7 +115,6 @@ mod green { use super::runner; #[test] - #[ignore] // unexepected error fn nan() { assert_eq!( runner().ok("a {b: rgb(0, calc(NaN), 0, 0.5)}\n"), @@ -131,7 +124,6 @@ mod green { ); } #[test] - #[ignore] // unexepected error fn negative_infinity() { assert_eq!( runner().ok("a {b: rgb(0, calc(-infinity), 0, 0.5)}\n"), @@ -141,7 +133,6 @@ mod green { ); } #[test] - #[ignore] // unexepected error fn positive_infinity() { assert_eq!( runner().ok("a {b: rgb(0, calc(infinity), 0, 0.5)}\n"), @@ -170,7 +161,6 @@ mod red { use super::runner; #[test] - #[ignore] // unexepected error fn nan() { assert_eq!( runner().ok("a {b: rgb(calc(NaN), 0, 0, 0.5)}\n"), @@ -180,7 +170,6 @@ mod red { ); } #[test] - #[ignore] // unexepected error fn negative_infinity() { assert_eq!( runner().ok("a {b: rgb(calc(-infinity), 0, 0, 0.5)}\n"), @@ -190,7 +179,6 @@ mod red { ); } #[test] - #[ignore] // unexepected error fn positive_infinity() { assert_eq!( runner().ok("a {b: rgb(calc(infinity), 0, 0, 0.5)}\n"),