feat: color: add channel properties to color

Add extra properties to the `color` type.
- `red`
- `green`
- `blue`
- `alpha`
This commit is contained in:
Luke D. Jones 2024-03-05 17:37:22 +13:00 committed by Olivier Goffart
parent 0409cb0140
commit 8c60cc74be
8 changed files with 73 additions and 3 deletions

View file

@ -22,6 +22,7 @@ All notable changes to this project are documented in this file.
- Image: Added support for 9 slice scaling - Image: Added support for 9 slice scaling
- Image: Added `horizontal-` and `vertical-tiling` - Image: Added `horizontal-` and `vertical-tiling`
- Flickable: Added `flicked` callback - Flickable: Added `flicked` callback
- Slint: Expose `.red`, `.green`, `.blue`, and `.alpha` properties on `color`
### Widgets ### Widgets

View file

@ -66,6 +66,17 @@ draw the outline.
CSS Color names are only in scope in expressions of type `color` or `brush`. Otherwise, you can access CSS Color names are only in scope in expressions of type `color` or `brush`. Otherwise, you can access
colors from the `Colors` namespace. colors from the `Colors` namespace.
### Properties
The following properties are exposed:
- **`red`**
- **`green`**
- **`blue`**
- **`alpha`**
All properties are in the range 0-255.
### Methods ### Methods
All colors and brushes define the following methods: All colors and brushes define the following methods:

View file

@ -47,6 +47,7 @@ pub enum BuiltinFunction {
StringToFloat, StringToFloat,
/// the "42".is_float() /// the "42".is_float()
StringIsFloat, StringIsFloat,
ColorRgbaStruct,
ColorBrighter, ColorBrighter,
ColorDarker, ColorDarker,
ColorTransparentize, ColorTransparentize,
@ -153,6 +154,21 @@ impl BuiltinFunction {
return_type: Box::new(crate::layout::layout_info_type()), return_type: Box::new(crate::layout::layout_info_type()),
args: vec![Type::ElementReference], args: vec![Type::ElementReference],
}, },
BuiltinFunction::ColorRgbaStruct => Type::Function {
return_type: Box::new(Type::Struct {
fields: IntoIterator::into_iter([
("red".to_string(), Type::Int32),
("green".to_string(), Type::Int32),
("blue".to_string(), Type::Int32),
("alpha".to_string(), Type::Int32),
])
.collect(),
name: Some("Color".into()),
node: None,
rust_attributes: None,
}),
args: vec![Type::Color],
},
BuiltinFunction::ColorBrighter => Type::Function { BuiltinFunction::ColorBrighter => Type::Function {
return_type: Box::new(Type::Brush), return_type: Box::new(Type::Brush),
args: vec![Type::Brush, Type::Float32], args: vec![Type::Brush, Type::Float32],
@ -256,7 +272,8 @@ impl BuiltinFunction {
BuiltinFunction::SetSelectionOffsets => false, BuiltinFunction::SetSelectionOffsets => false,
BuiltinFunction::ItemMemberFunction(..) => false, BuiltinFunction::ItemMemberFunction(..) => false,
BuiltinFunction::StringToFloat | BuiltinFunction::StringIsFloat => true, BuiltinFunction::StringToFloat | BuiltinFunction::StringIsFloat => true,
BuiltinFunction::ColorBrighter BuiltinFunction::ColorRgbaStruct
| BuiltinFunction::ColorBrighter
| BuiltinFunction::ColorDarker | BuiltinFunction::ColorDarker
| BuiltinFunction::ColorTransparentize | BuiltinFunction::ColorTransparentize
| BuiltinFunction::ColorMix | BuiltinFunction::ColorMix
@ -310,7 +327,8 @@ impl BuiltinFunction {
BuiltinFunction::SetSelectionOffsets => false, BuiltinFunction::SetSelectionOffsets => false,
BuiltinFunction::ItemMemberFunction(..) => false, BuiltinFunction::ItemMemberFunction(..) => false,
BuiltinFunction::StringToFloat | BuiltinFunction::StringIsFloat => true, BuiltinFunction::StringToFloat | BuiltinFunction::StringIsFloat => true,
BuiltinFunction::ColorBrighter BuiltinFunction::ColorRgbaStruct
| BuiltinFunction::ColorBrighter
| BuiltinFunction::ColorDarker | BuiltinFunction::ColorDarker
| BuiltinFunction::ColorTransparentize | BuiltinFunction::ColorTransparentize
| BuiltinFunction::ColorMix | BuiltinFunction::ColorMix

View file

@ -3048,6 +3048,9 @@ fn compile_builtin_function_call(
ctx.generator_state.conditional_includes.cstdlib.set(true); ctx.generator_state.conditional_includes.cstdlib.set(true);
format!("[](const auto &a){{ auto e1 = std::end(a); auto e2 = const_cast<char*>(e1); auto r = std::strtod(std::begin(a), &e2); return e1 == e2 ? r : 0; }}({})", a.next().unwrap()) format!("[](const auto &a){{ auto e1 = std::end(a); auto e2 = const_cast<char*>(e1); auto r = std::strtod(std::begin(a), &e2); return e1 == e2 ? r : 0; }}({})", a.next().unwrap())
} }
BuiltinFunction::ColorRgbaStruct => {
format!("{}.to_argb_u8()", a.next().unwrap())
}
BuiltinFunction::ColorBrighter => { BuiltinFunction::ColorBrighter => {
format!("{}.brighter({})", a.next().unwrap(), a.next().unwrap()) format!("{}.brighter({})", a.next().unwrap(), a.next().unwrap())
} }

View file

@ -2492,6 +2492,7 @@ fn compile_builtin_function_call(
quote!(#(#a)*.as_str().parse::<f64>().unwrap_or_default()) quote!(#(#a)*.as_str().parse::<f64>().unwrap_or_default())
} }
BuiltinFunction::StringIsFloat => quote!(#(#a)*.as_str().parse::<f64>().is_ok()), BuiltinFunction::StringIsFloat => quote!(#(#a)*.as_str().parse::<f64>().is_ok()),
BuiltinFunction::ColorRgbaStruct => quote!( #(#a)*.to_argb_u8()),
BuiltinFunction::ColorBrighter => { BuiltinFunction::ColorBrighter => {
let x = a.next().unwrap(); let x = a.next().unwrap();
let factor = a.next().unwrap(); let factor = a.next().unwrap();

View file

@ -87,6 +87,7 @@ fn builtin_function_cost(function: &BuiltinFunction) -> isize {
BuiltinFunction::ItemMemberFunction(..) => isize::MAX, BuiltinFunction::ItemMemberFunction(..) => isize::MAX,
BuiltinFunction::StringToFloat => 50, BuiltinFunction::StringToFloat => 50,
BuiltinFunction::StringIsFloat => 50, BuiltinFunction::StringIsFloat => 50,
BuiltinFunction::ColorRgbaStruct => 50,
BuiltinFunction::ColorBrighter => 50, BuiltinFunction::ColorBrighter => 50,
BuiltinFunction::ColorDarker => 50, BuiltinFunction::ColorDarker => 50,
BuiltinFunction::ColorTransparentize => 50, BuiltinFunction::ColorTransparentize => 50,

View file

@ -996,7 +996,24 @@ impl<'a> LookupObject for ColorExpression<'a> {
)), )),
}) })
}; };
None.or_else(|| f("brighter", member_function(BuiltinFunction::ColorBrighter))) let field_access = |f: &str| {
LookupResult::from(Expression::StructFieldAccess {
base: Box::new(Expression::FunctionCall {
function: Box::new(Expression::BuiltinFunctionReference(
BuiltinFunction::ColorRgbaStruct,
ctx.current_token.as_ref().map(|t| t.to_source_location()),
)),
source_location: ctx.current_token.as_ref().map(|t| t.to_source_location()),
arguments: vec![self.0.clone()],
}),
name: f.into(),
})
};
None.or_else(|| f("red", field_access("red")))
.or_else(|| f("green", field_access("green")))
.or_else(|| f("blue", field_access("blue")))
.or_else(|| f("alpha", field_access("alpha")))
.or_else(|| f("brighter", member_function(BuiltinFunction::ColorBrighter)))
.or_else(|| f("darker", member_function(BuiltinFunction::ColorDarker))) .or_else(|| f("darker", member_function(BuiltinFunction::ColorDarker)))
.or_else(|| f("transparentize", member_function(BuiltinFunction::ColorTransparentize))) .or_else(|| f("transparentize", member_function(BuiltinFunction::ColorTransparentize)))
.or_else(|| f("with-alpha", member_function(BuiltinFunction::ColorWithAlpha))) .or_else(|| f("with-alpha", member_function(BuiltinFunction::ColorWithAlpha)))

View file

@ -739,6 +739,24 @@ fn call_builtin_function(
panic!("Argument not a string"); panic!("Argument not a string");
} }
} }
BuiltinFunction::ColorRgbaStruct => {
if arguments.len() != 1 {
panic!("internal error: incorrect argument count to ColorRGBAComponents")
}
if let Value::Brush(brush) = eval_expression(&arguments[0], local_context) {
let color = brush.color();
let values = IntoIterator::into_iter([
("red".to_string(), Value::Number(color.red().into())),
("green".to_string(), Value::Number(color.green().into())),
("blue".to_string(), Value::Number(color.blue().into())),
("alpha".to_string(), Value::Number(color.alpha().into())),
])
.collect();
Value::Struct(values)
} else {
panic!("First argument not a color");
}
}
BuiltinFunction::ColorBrighter => { BuiltinFunction::ColorBrighter => {
if arguments.len() != 2 { if arguments.len() != 2 {
panic!("internal error: incorrect argument count to ColorBrighter") panic!("internal error: incorrect argument count to ColorBrighter")