Implement builtin function scale-color()
This commit is contained in:
parent
e2d1adf8b9
commit
bb7e47a4fb
@ -118,4 +118,65 @@ pub(crate) fn register(f: &mut BTreeMap<String, Builtin>) {
|
||||
color
|
||||
}))
|
||||
});
|
||||
decl!(f "scale-color", |args, _| {
|
||||
let color = match arg!(args, 0, "color").eval() {
|
||||
Value::Color(c) => c.clone(),
|
||||
_ => todo!("non-color given to builtin function `scale-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(
|
||||
scale(color.red(), red.unwrap_or(Number::from(0)), Number::from(255)),
|
||||
scale(color.green(), green.unwrap_or(Number::from(0)), Number::from(255)),
|
||||
scale(color.blue(), blue.unwrap_or(Number::from(0)), Number::from(255)),
|
||||
scale(color.alpha(), alpha.unwrap_or(Number::from(0)), Number::from(1)),
|
||||
)
|
||||
))
|
||||
}
|
||||
|
||||
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(
|
||||
scale(this_hue, hue.unwrap_or(Number::from(0)), Number::from(360)),
|
||||
scale(this_saturation, saturation.unwrap_or(Number::from(0)), Number::from(1)),
|
||||
scale(this_luminance, luminance.unwrap_or(Number::from(0)), Number::from(1)),
|
||||
scale(this_alpha, alpha.unwrap_or(Number::from(0)), Number::from(1)),
|
||||
)
|
||||
))
|
||||
}
|
||||
|
||||
Some(Value::Color(if let Some(a) = alpha {
|
||||
let temp_alpha = color.alpha();
|
||||
color.with_alpha(scale(temp_alpha, a, Number::from(1)))
|
||||
} else {
|
||||
color
|
||||
}))
|
||||
});
|
||||
}
|
||||
|
||||
fn scale(val: Number, by: Number, max: Number) -> Number {
|
||||
if by == Number::from(0) {
|
||||
return val;
|
||||
}
|
||||
val.clone() + (if by > Number::from(0) { max - val } else { val }) * by
|
||||
}
|
||||
|
@ -421,3 +421,18 @@ test!(
|
||||
"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"
|
||||
);
|
||||
test!(
|
||||
scale_color_lightness,
|
||||
"a {\n color: scale-color(hsl(120, 70%, 80%), $lightness: 50%);\n}\n",
|
||||
"a {\n color: #d4f7d4;\n}\n"
|
||||
);
|
||||
test!(
|
||||
scale_color_negative,
|
||||
"a {\n color: scale-color(rgb(200, 150%, 170%), $green: -40%, $blue: 70%);\n}\n",
|
||||
"a {\n color: #c899ff;\n}\n"
|
||||
);
|
||||
test!(
|
||||
scale_color_alpha,
|
||||
"a {\n color: scale-color(hsl(200, 70%, 80%), $saturation: -90%, $alpha: -30%);\n}\n",
|
||||
"a {\n color: rgba(200, 205, 208, 0.7);\n}\n"
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user