Implement builtin function change-color()
This commit is contained in:
parent
af95658953
commit
a328617001
@ -1,7 +1,77 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use super::Builtin;
|
use super::Builtin;
|
||||||
|
use crate::color::Color;
|
||||||
|
use crate::units::Unit;
|
||||||
|
use crate::value::{Number, Value};
|
||||||
|
|
||||||
pub(crate) fn register(_f: &mut BTreeMap<String, Builtin>) {
|
pub(crate) fn register(f: &mut BTreeMap<String, Builtin>) {
|
||||||
|
decl!(f "change-color", |args, _| {
|
||||||
|
let color = match arg!(args, 0, "color").eval() {
|
||||||
|
Value::Color(c) => c,
|
||||||
|
_ => todo!("non-color given to builtin function `change-color()`")
|
||||||
|
};
|
||||||
|
|
||||||
|
let alpha = match arg!(args, -1, "alpha"=Value::Null).eval() {
|
||||||
|
Value::Dimension(n, Unit::None) => Some(n),
|
||||||
|
Value::Dimension(n, Unit::Percent) => Some(n / Number::from(100)),
|
||||||
|
Value::Null => None,
|
||||||
|
_ => todo!("expected either unitless or % number for $alpha")
|
||||||
|
};
|
||||||
|
|
||||||
|
let red = match arg!(args, -1, "red"=Value::Null).eval() {
|
||||||
|
Value::Dimension(n, Unit::None) => Some(n),
|
||||||
|
Value::Dimension(n, Unit::Percent) => Some(n / Number::from(100)),
|
||||||
|
Value::Null => None,
|
||||||
|
_ => todo!("expected either unitless or % number for $red")
|
||||||
|
};
|
||||||
|
let green = match arg!(args, -1, "green"=Value::Null).eval() {
|
||||||
|
Value::Dimension(n, Unit::None) => Some(n),
|
||||||
|
Value::Dimension(n, Unit::Percent) => Some(n / Number::from(100)),
|
||||||
|
Value::Null => None,
|
||||||
|
_ => todo!("expected either unitless or % number for $green")
|
||||||
|
};
|
||||||
|
let blue = match arg!(args, -1, "blue"=Value::Null).eval() {
|
||||||
|
Value::Dimension(n, Unit::None) => Some(n),
|
||||||
|
Value::Dimension(n, Unit::Percent) => Some(n / Number::from(100)),
|
||||||
|
Value::Null => None,
|
||||||
|
_ => todo!("expected either unitless or % number for $blue")
|
||||||
|
};
|
||||||
|
|
||||||
|
if !red.is_none() || !green.is_none() || !blue.is_none() {
|
||||||
|
return Some(Value::Color(Color::from_rgba(red.unwrap_or(color.red()), green.unwrap_or(color.green()), blue.unwrap_or(color.blue()), alpha.unwrap_or(color.alpha()))))
|
||||||
|
}
|
||||||
|
|
||||||
|
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"),
|
||||||
|
};
|
||||||
|
let saturation = match arg!(args, -1, "saturation"=Value::Null).eval() {
|
||||||
|
Value::Dimension(n, Unit::None)
|
||||||
|
| Value::Dimension(n, Unit::Percent) => Some(n / Number::from(100)),
|
||||||
|
Value::Null => None,
|
||||||
|
_ => todo!("expected either unitless or % number for saturation"),
|
||||||
|
};
|
||||||
|
let luminance = match arg!(args, -1, "lightness"=Value::Null).eval() {
|
||||||
|
Value::Dimension(n, Unit::None)
|
||||||
|
| Value::Dimension(n, Unit::Percent) => Some(n / Number::from(100)),
|
||||||
|
Value::Null => None,
|
||||||
|
_ => todo!("expected either unitless or % number for luminance"),
|
||||||
|
};
|
||||||
|
|
||||||
|
if !hue.is_none() || !saturation.is_none() || !luminance.is_none() {
|
||||||
|
// 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(hue.unwrap_or(this_hue), saturation.unwrap_or(this_saturation), luminance.unwrap_or(this_luminance), alpha.unwrap_or(this_alpha))))
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(Value::Color(if !alpha.is_none() {
|
||||||
|
color.with_alpha(alpha.unwrap())
|
||||||
|
} else {
|
||||||
|
color
|
||||||
|
}))
|
||||||
|
});
|
||||||
}
|
}
|
@ -179,7 +179,7 @@ impl Color {
|
|||||||
(((min + max) / Number::from(2)) * Number::from(100)).round()
|
(((min + max) / Number::from(2)) * Number::from(100)).round()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_hsla(&self) -> (Number, Number, Number, Number) {
|
pub fn as_hsla(&self) -> (Number, Number, Number, Number) {
|
||||||
let red = self.red.clone() / Number::from(255);
|
let red = self.red.clone() / Number::from(255);
|
||||||
let green = self.green.clone() / Number::from(255);
|
let green = self.green.clone() / Number::from(255);
|
||||||
let blue = self.blue.clone() / Number::from(255);
|
let blue = self.blue.clone() / Number::from(255);
|
||||||
|
@ -376,3 +376,18 @@ test!(
|
|||||||
"a {\n color: mix(black, white);\n}\n",
|
"a {\n color: mix(black, white);\n}\n",
|
||||||
"a {\n color: gray;\n}\n"
|
"a {\n color: gray;\n}\n"
|
||||||
);
|
);
|
||||||
|
test!(
|
||||||
|
change_color_blue,
|
||||||
|
"a {\n color: change-color(#102030, $blue: 5);\n}\n",
|
||||||
|
"a {\n color: #102005;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
change_color_red_blue,
|
||||||
|
"a {\n color: change-color(#102030, $red: 120, $blue: 5);\n}\n",
|
||||||
|
"a {\n color: #782005;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
change_color_lum_alpha,
|
||||||
|
"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"
|
||||||
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user