Initial implementation of invert()
(no support for weight
argument)
This commit is contained in:
parent
8638e2f251
commit
1269c9f662
@ -150,4 +150,10 @@ pub(crate) fn register(f: &mut BTreeMap<String, Builtin>) {
|
||||
_ => todo!("non-color given to builtin function `alpha()`")
|
||||
}
|
||||
});
|
||||
decl!(f "invert", |args, _| {
|
||||
match arg!(args, 0, "color") {
|
||||
Value::Color(c) => Some(Value::Color(c.invert())),
|
||||
_ => todo!("non-color given to builtin function `alpha()`")
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -10,15 +10,15 @@ mod name;
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub(crate) struct Color {
|
||||
red: u16,
|
||||
green: u16,
|
||||
blue: u16,
|
||||
red: u8,
|
||||
green: u8,
|
||||
blue: u8,
|
||||
alpha: Number,
|
||||
repr: String,
|
||||
}
|
||||
|
||||
impl Color {
|
||||
pub fn new(red: u16, green: u16, blue: u16, alpha: u16, repr: String) -> Self {
|
||||
pub fn new(red: u8, green: u8, blue: u8, alpha: u8, repr: String) -> Self {
|
||||
Color {
|
||||
red,
|
||||
green,
|
||||
@ -28,15 +28,15 @@ impl Color {
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn red(&self) -> u16 {
|
||||
pub const fn red(&self) -> u8 {
|
||||
self.red
|
||||
}
|
||||
|
||||
pub const fn blue(&self) -> u16 {
|
||||
pub const fn blue(&self) -> u8 {
|
||||
self.blue
|
||||
}
|
||||
|
||||
pub const fn green(&self) -> u16 {
|
||||
pub const fn green(&self) -> u8 {
|
||||
self.green
|
||||
}
|
||||
|
||||
@ -122,7 +122,7 @@ impl Color {
|
||||
};
|
||||
let val = (luminance.clone() * Number::from(255))
|
||||
.to_integer()
|
||||
.to_u16()
|
||||
.to_u8()
|
||||
.unwrap();
|
||||
let repr = repr(val, val, val, &alpha);
|
||||
return Color {
|
||||
@ -175,8 +175,8 @@ impl Color {
|
||||
} * Number::from(255))
|
||||
.round()
|
||||
.to_integer()
|
||||
.to_u16()
|
||||
.expect("expected channel to fit inside u16");
|
||||
.to_u8()
|
||||
.expect("expected channel to fit inside u8");
|
||||
};
|
||||
}
|
||||
|
||||
@ -198,11 +198,11 @@ impl Color {
|
||||
macro_rules! clamp {
|
||||
($channel:ident) => {
|
||||
let $channel = if $channel > Number::from(255) {
|
||||
255_u16
|
||||
255_u8
|
||||
} else if $channel < Number::from(0) {
|
||||
0_u16
|
||||
0_u8
|
||||
} else {
|
||||
$channel.round().to_integer().to_u16().unwrap()
|
||||
$channel.round().to_integer().to_u8().unwrap()
|
||||
};
|
||||
};
|
||||
}
|
||||
@ -211,6 +211,14 @@ impl Color {
|
||||
clamp!(green);
|
||||
clamp!(blue);
|
||||
|
||||
let alpha = if alpha > Number::from(1) {
|
||||
Number::from(1)
|
||||
} else if alpha < Number::from(0) {
|
||||
Number::from(0)
|
||||
} else {
|
||||
alpha
|
||||
};
|
||||
|
||||
let repr = repr(red, green, blue, &alpha);
|
||||
Color {
|
||||
red,
|
||||
@ -220,10 +228,24 @@ impl Color {
|
||||
repr,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn invert(&self) -> Self {
|
||||
let red = std::u8::MAX - self.red;
|
||||
let green = std::u8::MAX - self.green;
|
||||
let blue = std::u8::MAX - self.blue;
|
||||
let repr = repr(red, green, blue, &self.alpha);
|
||||
Color {
|
||||
red,
|
||||
green,
|
||||
blue,
|
||||
alpha: self.alpha.clone(),
|
||||
repr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the proper representation from RGBA values
|
||||
fn repr(red: u16, green: u16, blue: u16, alpha: &Number) -> String {
|
||||
fn repr(red: u8, green: u8, blue: u8, alpha: &Number) -> String {
|
||||
if alpha < &Number::from(1) {
|
||||
format!("rgba({}, {}, {}, {})", red, green, blue, alpha)
|
||||
} else if let Ok(c) = ColorName::try_from([red, green, blue]) {
|
||||
|
@ -469,10 +469,11 @@ impl TryFrom<&str> for ColorName {
|
||||
}
|
||||
}
|
||||
}
|
||||
impl TryFrom<[u16; 3]> for ColorName {
|
||||
|
||||
impl TryFrom<[u8; 3]> for ColorName {
|
||||
type Error = &'static str;
|
||||
|
||||
fn try_from(c: [u16; 3]) -> Result<Self, Self::Error> {
|
||||
fn try_from(c: [u8; 3]) -> Result<Self, Self::Error> {
|
||||
match c {
|
||||
[0xF0, 0xF8, 0xFF] => Ok(Self::AliceBlue),
|
||||
[0xFA, 0xEB, 0xD7] => Ok(Self::AntiqueWhite),
|
||||
|
@ -61,6 +61,7 @@ macro_rules! from_integer {
|
||||
from_integer!(u16);
|
||||
from_integer!(usize);
|
||||
from_integer!(i32);
|
||||
from_integer!(u8);
|
||||
|
||||
impl Display for Number {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
@ -20,32 +20,32 @@ fn parse_hex(s: String) -> Value {
|
||||
match s.len() {
|
||||
3 => {
|
||||
let v = u16::from_str_radix(&s, 16).unwrap();
|
||||
let red = ((v & 0xf00) >> 8) * 0x11;
|
||||
let green = ((v & 0x0f0) >> 4) * 0x11;
|
||||
let blue = (v & 0x00f) * 0x11;
|
||||
let red = (((v & 0xf00) >> 8) * 0x11) as u8;
|
||||
let green = (((v & 0x0f0) >> 4) * 0x11) as u8;
|
||||
let blue = ((v & 0x00f) * 0x11) as u8;
|
||||
Value::Color(Color::new(red, green, blue, 1, format!("#{}", s)))
|
||||
}
|
||||
4 => {
|
||||
let v = u16::from_str_radix(&s, 16).unwrap();
|
||||
let red = ((v & 0xf000) >> 12) * 0x11;
|
||||
let green = ((v & 0x0f00) >> 8) * 0x11;
|
||||
let blue = ((v & 0x00f0) >> 4) * 0x11;
|
||||
let alpha = (v & 0x000f) * 0x11;
|
||||
let red = (((v & 0xf000) >> 12) * 0x11) as u8;
|
||||
let green = (((v & 0x0f00) >> 8) * 0x11) as u8;
|
||||
let blue = (((v & 0x00f0) >> 4) * 0x11) as u8;
|
||||
let alpha = ((v & 0x000f) * 0x11) as u8;
|
||||
Value::Color(Color::new(red, green, blue, alpha, format!("#{}", s)))
|
||||
}
|
||||
6 => {
|
||||
let v = u32::from_str_radix(&s, 16).unwrap();
|
||||
let red: u16 = ((v & 0x00ff_0000) >> 16) as u16;
|
||||
let green: u16 = ((v & 0x0000_ff00) >> 8) as u16;
|
||||
let blue: u16 = (v & 0x0000_00ff) as u16;
|
||||
let red = ((v & 0x00ff_0000) >> 16) as u8;
|
||||
let green = ((v & 0x0000_ff00) >> 8) as u8;
|
||||
let blue = (v & 0x0000_00ff) as u8;
|
||||
Value::Color(Color::new(red, green, blue, 1, format!("#{}", s)))
|
||||
}
|
||||
8 => {
|
||||
let v = u32::from_str_radix(&s, 16).unwrap();
|
||||
let red = ((v & 0xff00_0000) >> 24) as u16;
|
||||
let green = ((v & 0x00ff_0000) >> 16) as u16;
|
||||
let blue = ((v & 0x0000_ff00) >> 8) as u16;
|
||||
let alpha = (v & 0x0000_00ff) as u16;
|
||||
let red = ((v & 0xff00_0000) >> 24) as u8;
|
||||
let green = ((v & 0x00ff_0000) >> 16) as u8;
|
||||
let blue = ((v & 0x0000_ff00) >> 8) as u8;
|
||||
let alpha = (v & 0x0000_00ff) as u8;
|
||||
Value::Color(Color::new(red, green, blue, alpha, format!("#{}", s)))
|
||||
}
|
||||
_ => Value::Ident(s, QuoteKind::None),
|
||||
|
@ -171,3 +171,8 @@ test!(
|
||||
"$a: hsl(193, 67%, 28%);\n\na {\n color: lightness($a);\n}\n",
|
||||
"a {\n color: 28%;\n}\n"
|
||||
);
|
||||
test!(
|
||||
invert_no_weight,
|
||||
"a {\n color: invert(white);\n}\n",
|
||||
"a {\n color: black;\n}\n"
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user