diff --git a/src/builtin/color/other.rs b/src/builtin/color/other.rs index 5769542..f18eee9 100644 --- a/src/builtin/color/other.rs +++ b/src/builtin/color/other.rs @@ -64,4 +64,58 @@ pub(crate) fn register(f: &mut BTreeMap) { color })) }); + decl!(f "adjust-color", |args, _| { + let color = match arg!(args, 0, "color").eval() { + Value::Color(c) => c.clone(), + _ => todo!("non-color given to builtin function `adjust-color()`") + }; + + opt_arg!(args, alpha, "alpha"); + opt_arg!(args, red, "red"); + opt_arg!(args, green, "green"); + opt_arg!(args, blue, "blue"); + + if red.is_some() || green.is_some() || blue.is_some() { + return + Some(Value::Color( + Color::from_rgba( + color.red() + red.unwrap_or(Number::from(0)), + color.green() + green.unwrap_or(Number::from(0)), + color.blue() + blue.unwrap_or(Number::from(0)), + color.alpha() + alpha.unwrap_or(Number::from(0)) + ) + )) + } + + let hue = match arg!(args, -1, "hue"=Value::Null).eval() { + Value::Dimension(n, Unit::None) + | Value::Dimension(n, Unit::Percent) + | Value::Dimension(n, Unit::Deg) => Some(n), + Value::Null => None, + _ => todo!("expected either unitless or % number for hue"), + }; + + opt_arg!(hsl: args, saturation, "saturation"); + opt_arg!(hsl: args, luminance, "lightness"); + + if hue.is_some() || saturation.is_some() || luminance.is_some() { + // Color::as_hsla() returns more exact values than Color::hue(), etc. + let (this_hue, this_saturation, this_luminance, this_alpha) = color.as_hsla(); + return Some(Value::Color( + Color::from_hsla( + this_hue + hue.unwrap_or(Number::from(0)), + this_saturation + saturation.unwrap_or(Number::from(0)), + this_luminance + luminance.unwrap_or(Number::from(0)), + this_alpha + alpha.unwrap_or(Number::from(0)) + ) + )) + } + + Some(Value::Color(if let Some(a) = alpha { + let temp_alpha = color.alpha(); + color.with_alpha(temp_alpha + a) + } else { + color + })) + }); } diff --git a/tests/color.rs b/tests/color.rs index 2c33039..6ba79fd 100644 --- a/tests/color.rs +++ b/tests/color.rs @@ -406,3 +406,18 @@ test!( "a {\n color: change-color(hsl(25, 100%, 80%), $lightness: 40%, $alpha: 0.8);\n}\n", "a {\n color: rgba(204, 85, 0, 0.8);\n}\n" ); +test!( + adjust_color_blue, + "a {\n color: adjust-color(#102030, $blue: 5);\n}\n", + "a {\n color: #102035;\n}\n" +); +test!( + adjust_color_negative, + "a {\n color: adjust-color(#102030, $red: -5, $blue: 5);\n}\n", + "a {\n color: #0b2035;\n}\n" +); +test!( + adjust_color_lum_alpha, + "a {\n color: adjust-color(hsl(25, 100%, 80%), $lightness: -30%, $alpha: -0.4);\n}\n", + "a {\n color: rgba(255, 106, 0, 0.6);\n}\n" +);