diff --git a/src/builtin/color.rs b/src/builtin/color.rs index 2ed5fd6..ec93262 100644 --- a/src/builtin/color.rs +++ b/src/builtin/color.rs @@ -227,4 +227,52 @@ pub(crate) fn register(f: &mut BTreeMap) { }; Some(Value::Color(color.desaturate(amount))) }); + decl!(f "opacify", |args, _| { + let color = match arg!(args, 0, "color").eval() { + Value::Color(c) => c, + _ => todo!("non-color given to builtin function `opacify()`") + }; + let amount = match arg!(args, 1, "amount").eval() { + Value::Dimension(n, Unit::None) => n, + Value::Dimension(n, Unit::Percent) => n / Number::from(100), + _ => todo!("expected either unitless or % number for amount"), + }; + Some(Value::Color(color.fade_in(amount))) + }); + decl!(f "fade-in", |args, _| { + let color = match arg!(args, 0, "color").eval() { + Value::Color(c) => c, + _ => todo!("non-color given to builtin function `fade-in()`") + }; + let amount = match arg!(args, 1, "amount").eval() { + Value::Dimension(n, Unit::None) => n, + Value::Dimension(n, Unit::Percent) => n / Number::from(100), + _ => todo!("expected either unitless or % number for amount"), + }; + Some(Value::Color(color.fade_in(amount))) + }); + decl!(f "transparentize", |args, _| { + let color = match arg!(args, 0, "color").eval() { + Value::Color(c) => c, + _ => todo!("non-color given to builtin function `transparentize()`") + }; + let amount = match arg!(args, 1, "amount").eval() { + Value::Dimension(n, Unit::None) => n, + Value::Dimension(n, Unit::Percent) => n / Number::from(100), + _ => todo!("expected either unitless or % number for amount"), + }; + Some(Value::Color(color.fade_out(amount))) + }); + decl!(f "fade-out", |args, _| { + let color = match arg!(args, 0, "color").eval() { + Value::Color(c) => c, + _ => todo!("non-color given to builtin function `fade-out()`") + }; + let amount = match arg!(args, 1, "amount").eval() { + Value::Dimension(n, Unit::None) => n, + Value::Dimension(n, Unit::Percent) => n / Number::from(100), + _ => todo!("expected either unitless or % number for amount"), + }; + Some(Value::Color(color.fade_out(amount))) + }); } diff --git a/src/color/mod.rs b/src/color/mod.rs index 9b3426c..9c155e9 100644 --- a/src/color/mod.rs +++ b/src/color/mod.rs @@ -171,6 +171,20 @@ impl Color { self.alpha.clone() } + /// Makes a color more opaque. + /// Takes a color and a number between 0 and 1, + /// and returns a color with the opacity increased by that amount. + pub fn fade_in(self, amount: Number) -> Self { + Color::from_rgba(self.red, self.green, self.blue, self.alpha + amount) + } + + /// Makes a color more transparent. + /// Takes a color and a number between 0 and 1, + /// and returns a color with the opacity decreased by that amount. + pub fn fade_out(self, amount: Number) -> Self { + Color::from_rgba(self.red, self.green, self.blue, self.alpha - amount) + } + /// Create RGBA representation from HSLA values /// Algorithm adapted from pub fn from_hsla( diff --git a/tests/color.rs b/tests/color.rs index 7faed60..3c9dc14 100644 --- a/tests/color.rs +++ b/tests/color.rs @@ -309,3 +309,23 @@ test!( "a {\n color: desaturate(plum, 14%);\n}\n", "a {\n color: #d4a9d4;\n}\n" ); +test!( + transparentize, + "a {\n color: transparentize(rgba(0, 0, 0, 0.5), 0.1);\n}\n", + "a {\n color: rgba(0, 0, 0, 0.4);\n}\n" +); +test!( + fade_out, + "a {\n color: fade-out(rgba(0, 0, 0, 0.8), 0.2);\n}\n", + "a {\n color: rgba(0, 0, 0, 0.6);\n}\n" +); +test!( + opacify, + "a {\n color: opacify(rgba(0, 0, 0, 0.5), 0.1);\n}\n", + "a {\n color: rgba(0, 0, 0, 0.6);\n}\n" +); +test!( + fade_in, + "a {\n color: opacify(rgba(0, 0, 17, 0.8), 0.2);\n}\n", + "a {\n color: #000011;\n}\n" +);