Add some color and brush manipulation funcs (#2565)

The added functions enable mixing colors and manipulating the opacity
of colors and brushes.

They enable the behavior of some of the available functions from SASS and are
added for future use for adding the Adwaita style (future PR).
This commit is contained in:
Arthur Araruna 2023-04-16 10:50:16 -03:00 committed by Olivier Goffart
parent 0c64312383
commit 64ad1ce357
14 changed files with 553 additions and 8 deletions

View file

@ -136,6 +136,30 @@ public:
/// all the colors of this brush.
inline Brush darker(float factor) const;
/// Returns a new version of this brush with the opacity decreased by \a factor,
/// meaning the new opacity will be the current one times `factor`.
///
/// The reference is the opacity's normalized value as `u8` and \a factor is
/// clamped to be between `0.0` and `1.0` before applying it.
///
/// For _increasing_ the opacity, see Brush::opaque(float) and
/// Brush::with_alpha(float).
inline Brush translucent(float factor) const;
/// Returns a new version of this brush with the opacity increased by \a factor,
/// meaning the new opacity will be scaled up by `1.0 + factor`.
///
/// The reference is the opacity's normalized value as `u8` and \a factor is
/// changed to be at least `0.0` before applying it, and thus the current
/// value cannot be decreased.
///
/// For _decreasing_ the opacity, see Brush::translucent(float)
/// and Brush::with_alpha(float).
inline Brush opaque(float factor) const;
/// Returns a new version of this brush with the related color's opacities
/// set to \a alpha.
inline Brush with_alpha(float alpha) 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
@ -218,4 +242,80 @@ inline Brush Brush::darker(float factor) const
}
return result;
}
inline Brush Brush::translucent(float factor) const
{
Brush result = *this;
switch (data.tag) {
case Tag::SolidColor:
cbindgen_private::types::slint_color_translucent(&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_translucent(
&data.linear_gradient._0[i].color, factor,
&result.data.linear_gradient._0[i].color);
}
break;
case Tag::RadialGradient:
for (std::size_t i = 0; i < data.linear_gradient._0.size(); ++i) {
cbindgen_private::types::slint_color_translucent(
&data.radial_gradient._0[i].color, factor,
&result.data.radial_gradient._0[i].color);
}
break;
}
return result;
}
inline Brush Brush::opaque(float factor) const
{
Brush result = *this;
switch (data.tag) {
case Tag::SolidColor:
cbindgen_private::types::slint_color_opaque(&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_opaque(&data.linear_gradient._0[i].color, factor,
&result.data.linear_gradient._0[i].color);
}
break;
case Tag::RadialGradient:
for (std::size_t i = 0; i < data.linear_gradient._0.size(); ++i) {
cbindgen_private::types::slint_color_opaque(&data.radial_gradient._0[i].color, factor,
&result.data.radial_gradient._0[i].color);
}
break;
}
return result;
}
inline Brush Brush::with_alpha(float alpha) const
{
Brush result = *this;
switch (data.tag) {
case Tag::SolidColor:
cbindgen_private::types::slint_color_with_alpha(&data.solid_color._0, alpha,
&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_with_alpha(
&data.linear_gradient._0[i].color, alpha,
&result.data.linear_gradient._0[i].color);
}
break;
case Tag::RadialGradient:
for (std::size_t i = 0; i < data.linear_gradient._0.size(); ++i) {
cbindgen_private::types::slint_color_with_alpha(
&data.radial_gradient._0[i].color, alpha,
&result.data.radial_gradient._0[i].color);
}
break;
}
return result;
}
}

View file

@ -147,6 +147,33 @@ public:
/// So for example `darker(0.3)` will decrease the brightness by 30%.
inline Color darker(float factor) const;
/// Returns a new version of this color with the opacity decreased by \a factor,
/// meaning the new opacity will be the current one times \a factor.
///
/// The reference is the opacity's normalized value as `u8` and \a factor is
/// clamped to be between `0.0` and `1.0` before applying it.
///
/// For _increasing_ the opacity, see Color::opaque(float) and
/// Color::with_alpha(float).
inline Color translucent(float factor) const;
/// Returns a new version of this color with the opacity increased by \a factor,
/// meaning the new opacity will be scaled up by `1.0 + factor`.
///
/// The reference is the opacity's normalized value as `u8` and \a factor is
/// changed to be at least `0.0` before applying it, and thus the current
/// value cannot be decreased.
///
/// For _decreasing_ the opacity, see Color::translucent(float) and
/// Color::with_alpha(float).
inline Color opaque(float factor) const;
/// Returns a new color that is a mix of \a this and \a other, with a proportion
/// factor given by \a factor (which will be clamped to be between `0.0` and `1.0`).
inline Color mixed(const Color &other, float factor) const;
/// Returns a new version of this color with the opacity set to \a alpha.
inline Color with_alpha(float alpha) const;
/// Returns true if \a lhs has the same values for the individual color channels as \a rhs;
/// false otherwise.
friend bool operator==(const Color &lhs, const Color &rhs) = default;
@ -163,8 +190,7 @@ public:
#if !defined(DOXYGEN)
// FIXME: we need this to create GradientStop
operator const cbindgen_private::types::Color &() const
{
operator const cbindgen_private::types::Color &() const {
return inner;
}
#endif
@ -189,6 +215,34 @@ inline Color Color::darker(float factor) const
return result;
}
inline Color Color::translucent(float factor) const
{
Color result;
cbindgen_private::types::slint_color_translucent(&inner, factor, &result.inner);
return result;
}
inline Color Color::opaque(float factor) const
{
Color result;
cbindgen_private::types::slint_color_opaque(&inner, factor, &result.inner);
return result;
}
inline Color Color::mixed(const Color &other, float factor) const
{
Color result;
cbindgen_private::types::slint_color_mixed(&inner, &other.inner, factor, &result.inner);
return result;
}
inline Color Color::with_alpha(float alpha) const
{
Color result;
cbindgen_private::types::slint_color_with_alpha(&inner, alpha, &result.inner);
return result;
}
/// Constructs a new RgbaColor<uint8_t> from the color \a color.
template<>
inline RgbaColor<uint8_t>::RgbaColor(const Color &color)