diff --git a/src/builtin/color.rs b/src/builtin/color.rs index d1ab180..e464aec 100644 --- a/src/builtin/color.rs +++ b/src/builtin/color.rs @@ -151,8 +151,13 @@ pub(crate) fn register(f: &mut BTreeMap) { } }); decl!(f "invert", |args, _| { + let weight = match arg!(args, 1, "weight"=Value::Dimension(Number::from(100), Unit::Percent)) { + Value::Dimension(n, Unit::None) + | Value::Dimension(n, Unit::Percent) => n / Number::from(100), + _ => todo!("non-number weight in given to builtin function `invert()`") + }; match arg!(args, 0, "color") { - Value::Color(c) => Some(Value::Color(c.invert())), + Value::Color(c) => Some(Value::Color(c.invert(weight))), _ => todo!("non-color given to builtin function `alpha()`") } }); diff --git a/src/builtin/macros.rs b/src/builtin/macros.rs index 861fdf0..51c8bc5 100644 --- a/src/builtin/macros.rs +++ b/src/builtin/macros.rs @@ -8,11 +8,11 @@ macro_rules! arg { }, }; }; - ($args:ident, $idx:literal, $name:literal=$default:literal) => { + ($args:ident, $idx:literal, $name:literal=$default:expr) => { match $args.get(stringify!($idx)) { - Some(v) => v, + Some(v) => v.clone(), None => match $args.get($name) { - Some(v) => v, + Some(v) => v.clone(), None => $default, }, }; diff --git a/src/color/mod.rs b/src/color/mod.rs index 52cdfc4..c7c65fc 100644 --- a/src/color/mod.rs +++ b/src/color/mod.rs @@ -229,10 +229,17 @@ impl Color { } } - pub fn invert(&self) -> Self { - let red = std::u8::MAX - self.red; - let green = std::u8::MAX - self.green; - let blue = std::u8::MAX - self.blue; + pub fn invert(&self, weight: Number) -> Self { + let weight = if weight > Number::from(1) { + Number::from(1) + } else if weight < Number::from(0) { + Number::from(0) + } else { + weight + }; + let red = (Number::from(std::u8::MAX) - (Number::from(self.red) * weight.clone())).round().to_integer().to_u8().unwrap(); + let green = (Number::from(std::u8::MAX) - (Number::from(self.green) * weight.clone())).round().to_integer().to_u8().unwrap(); + let blue = (Number::from(std::u8::MAX) - (Number::from(self.blue) * weight)).round().to_integer().to_u8().unwrap(); let repr = repr(red, green, blue, &self.alpha); Color { red, diff --git a/tests/color.rs b/tests/color.rs index b0e92e1..1fe008a 100644 --- a/tests/color.rs +++ b/tests/color.rs @@ -176,3 +176,13 @@ test!( "a {\n color: invert(white);\n}\n", "a {\n color: black;\n}\n" ); +test!( + invert_weight_percent, + "a {\n color: invert(white, 20%);\n}\n", + "a {\n color: #cccccc;\n}\n" +); +test!( + invert_weight_no_unit, + "a {\n color: invert(white, 20);\n}\n", + "a {\n color: #cccccc;\n}\n" +);