Implement builtin function scale-color()

This commit is contained in:
ConnorSkees 2020-02-14 19:51:24 -05:00
parent e2d1adf8b9
commit bb7e47a4fb
2 changed files with 76 additions and 0 deletions

View File

@ -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
}

View File

@ -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"
);