Allow .darker and .brighter on Brush

This commit is contained in:
Olivier Goffart 2022-04-12 10:07:56 +02:00 committed by Olivier Goffart
parent c825eee228
commit 54a6cb22ee
8 changed files with 113 additions and 15 deletions

View file

@ -15,6 +15,7 @@ All notable changes to this project are documented in this file.
- Added `VecModel::set_vec` to replace the entire contents with new data.
- Added a `cache-rendering-hint` boolean property that can be applied to any element, to hint to the renderer that it should cache the element and its children
into a cached layer. This may speed up rendering of complex sub-trees if they rarely change.
- The `brighter` and `lighter` functions also work on values of type brush.
### Fixed

View file

@ -82,6 +82,15 @@ public:
/// of the first stop.
inline Color color() const;
/// Returns a new version of this brush that has the brightness increased
/// by the specified factor. This is done by calling Color::brighter on
/// all the colors of this brush.
inline Brush brighter(float factor) const;
/// Returns a new version of this color that has the brightness decreased
/// by the specified factor. This is done by calling Color::darker on
/// all the colors of this brush.
inline Brush darker(float factor) const;
/// Returns true if \a a is equal to \a b. If \a a holds a color, then \a b must also hold a
/// color that is identical to \a a's color. If it holds a gradient, then the gradients must be
/// identical. Returns false if the brushes differ in what they hold or their respective color
@ -113,4 +122,41 @@ Color Brush::color() const
return result;
}
inline Brush Brush::brighter(float factor) const
{
Brush result = *this;
switch (data.tag) {
case Tag::SolidColor: {
cbindgen_private::types::slint_color_brighter(&data.solid_color._0, factor,
&result.data.solid_color._0);
break;
}
case Tag::LinearGradient:
for (std::size_t i = 1; i < data.linear_gradient._0.size(); ++i) {
cbindgen_private::types::slint_color_brighter(&data.linear_gradient._0[i].color, factor,
&result.data.linear_gradient._0[i].color);
}
break;
}
return result;
}
inline Brush Brush::darker(float factor) const
{
Brush result = *this;
switch (data.tag) {
case Tag::SolidColor: {
cbindgen_private::types::slint_color_darker(&data.solid_color._0, factor,
&result.data.solid_color._0);
break;
}
case Tag::LinearGradient:
for (std::size_t i = 1; i < data.linear_gradient._0.size(); ++i) {
cbindgen_private::types::slint_color_darker(&data.linear_gradient._0[i].color, factor,
&result.data.linear_gradient._0[i].color);
}
break;
}
return result;
}
}

View file

@ -488,7 +488,7 @@ Example := Text {
}
```
### Colors
### Colors and Brushes
Color literals follow the syntax of CSS:
@ -509,15 +509,15 @@ colors from the `Colors` namespace.
#### Methods
All colors have methods that can be called on them:
All colors and brushes have methods that can be called on them:
* **`brighter(factor: float) -> Color`**
* **`brighter(factor: float) -> Brush`**
Returns a new color that is derived from this color but has its brightness increased by the specified factor.
For example if the factor is 0.5 (or for example 50%) the returned color is 50% brighter. Negative factors
decrease the brightness.
* **`darker(factor: float) -> Color`**
* **`darker(factor: float) -> Brush`**
Returns a new color that is derived from this color but has its brightness decreased by the specified factor.
For example if the factor is .5 (or for example 50%) the returned color is 50% darker. Negative factors

View file

@ -109,12 +109,12 @@ impl BuiltinFunction {
args: vec![Type::ElementReference],
},
BuiltinFunction::ColorBrighter => Type::Function {
return_type: Box::new(Type::Color),
args: vec![Type::Color, Type::Float32],
return_type: Box::new(Type::Brush),
args: vec![Type::Brush, Type::Float32],
},
BuiltinFunction::ColorDarker => Type::Function {
return_type: Box::new(Type::Color),
args: vec![Type::Color, Type::Float32],
return_type: Box::new(Type::Brush),
args: vec![Type::Brush, Type::Float32],
},
BuiltinFunction::ImageSize => Type::Function {
return_type: Box::new(Type::Struct {

View file

@ -635,7 +635,7 @@ impl LookupObject for Expression {
}
Type::Component(c) => c.root_element.for_each_entry(ctx, f),
Type::String => StringExpression(self).for_each_entry(ctx, f),
Type::Color => ColorExpression(self).for_each_entry(ctx, f),
Type::Brush | Type::Color => ColorExpression(self).for_each_entry(ctx, f),
Type::Image => ImageExpression(self).for_each_entry(ctx, f),
Type::Array(_) => ArrayExpression(self).for_each_entry(ctx, f),
_ => None,
@ -655,7 +655,7 @@ impl LookupObject for Expression {
}),
Type::Component(c) => c.root_element.lookup(ctx, name),
Type::String => StringExpression(self).lookup(ctx, name),
Type::Color => ColorExpression(self).lookup(ctx, name),
Type::Brush | Type::Color => ColorExpression(self).lookup(ctx, name),
Type::Image => ImageExpression(self).lookup(ctx, name),
Type::Array(_) => ArrayExpression(self).lookup(ctx, name),
_ => None,

View file

@ -61,6 +61,38 @@ impl Brush {
Brush::LinearGradient(_) => false,
}
}
/// Returns a new version of this brush that has the brightness increased
/// by the specified factor. This is done by calling [`Color::brighter`] on
/// all the colors of this brush.
#[must_use]
pub fn brighter(&self, factor: f32) -> Self {
match self {
Brush::SolidColor(c) => Brush::SolidColor(c.brighter(factor)),
Brush::LinearGradient(g) => Brush::LinearGradient(LinearGradientBrush::new(
g.angle(),
g.stops().map(|s| GradientStop {
color: s.color.brighter(factor),
position: s.position,
}),
)),
}
}
/// Returns a new version of this brush that has the brightness decreased
/// by the specified factor. This is done by calling [`Color::ligher`] on
/// all the color of this brush.
#[must_use]
pub fn darker(&self, factor: f32) -> Self {
match self {
Brush::SolidColor(c) => Brush::SolidColor(c.darker(factor)),
Brush::LinearGradient(g) => Brush::LinearGradient(LinearGradientBrush::new(
g.angle(),
g.stops()
.map(|s| GradientStop { color: s.color.darker(factor), position: s.position }),
)),
}
}
}
/// The LinearGradientBrush describes a way of filling a shape with different colors, which

View file

@ -369,9 +369,9 @@ pub fn eval_expression(expression: &Expression, local_context: &mut EvalLocalCon
if arguments.len() != 2 {
panic!("internal error: incorrect argument count to ColorBrighter")
}
if let Value::Brush(Brush::SolidColor(col)) = eval_expression(&arguments[0], local_context) {
if let Value::Brush(brush) = eval_expression(&arguments[0], local_context) {
if let Value::Number(factor) = eval_expression(&arguments[1], local_context) {
col.brighter(factor as _).into()
brush.brighter(factor as _).into()
} else {
panic!("Second argument not a number");
}
@ -383,9 +383,9 @@ pub fn eval_expression(expression: &Expression, local_context: &mut EvalLocalCon
if arguments.len() != 2 {
panic!("internal error: incorrect argument count to ColorDarker")
}
if let Value::Brush(Brush::SolidColor(col)) = eval_expression(&arguments[0], local_context) {
if let Value::Brush(brush) = eval_expression(&arguments[0], local_context) {
if let Value::Number(factor) = eval_expression(&arguments[1], local_context) {
col.darker(factor as _).into()
brush.darker(factor as _).into()
} else {
panic!("Second argument not a number");
}

View file

@ -4,6 +4,20 @@
Test := Rectangle {
// allow declaring brush properties and assigning colors
property<brush> color_brush: blue;
// allow to use brighter and darker on a brush
property<brush> ligher: true ? color_brush.brighter(50%) : color_brush.darker(50%);
VerticalLayout {
r1 := Rectangle {
background: @linear-gradient(1.2rad, red, blue);
}
r2 := Rectangle {
background: r1.background.darker(50%);
}
}
property <color> r2_col: r2.background;
property<bool> test: ligher == Colors.blue.brighter(50%) && r2_col == Colors.red.darker(50%);
}
/*
@ -11,28 +25,33 @@ Test := Rectangle {
auto handle = Test::create();
const Test &t = *handle;
assert_eq(t.get_color_brush().color(), slint::Color::from_rgb_uint8(0, 0, 0xff));
assert(t.get_test());
auto green = slint::Color::from_rgb_uint8(0, 0xff, 0);
t.set_color_brush(green);
assert_eq(t.get_color_brush().color(), green);
```
```
```rust
let t = Test::new();
assert_eq!(t.get_color_brush().color(), slint::Color::from_rgb_u8(0, 0, 0xff));
assert!(t.get_test());
let green = slint::Color::from_rgb_u8(0, 0xff, 0);
t.set_color_brush(green.into());
assert_eq!(t.get_color_brush().color(), green);
```
```js
var t = new slint.Test({});
assert.equal(t.color_brush, "#0000ffff");
assert(t.test);
let green = "#00ff00ff";
t.color_brush = "#00ff00"; // css-color-parser2 can't parse #rrggbbaa yet
assert.equal(t.color_brush, green);
```
*/