1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
3
4#pragma once
5
6#include "slint_color_internal.h"
7#include "slint_properties.h"
8
9#include <stdint.h>
10
11namespace slint {
12
13namespace private_api {
14class LinearGradientBrush;
15}
16
17class Color;
18
19/// RgbaColor stores the red, green, blue and alpha components of a color
20/// with the precision of the template parameter T. For example if T is float,
21/// the values are normalized between 0 and 1. If T is uint8_t, they values range
22/// is 0 to 255.
23template<typename T>
24struct RgbaColor
25{
26 /// The alpha component.
27 T alpha;
28 /// The red component.
29 T red;
30 /// The green component.
31 T green;
32 /// The blue component.
33 T blue;
34
35 /// Creates a new RgbaColor instance from a given color. This template function is
36 /// specialized and thus implemented for T == uint8_t and T == float.
37 RgbaColor(const Color &col);
38};
39
40/// HsvaColor stores the hue, saturation, value, and alpha components of a color in the HSV color
41/// space.
42struct HsvaColor
43{
44 /// The hue component in degrees between 0 and 360.
45 float hue;
46 /// The saturation component, between 0 and 1.
47 float saturation;
48 /// The value component, between 0 and 1.
49 float value;
50 /// The alpha component, between 0 and 1.
51 float alpha;
52};
53
54/// Color represents a color in the Slint run-time, represented using 8-bit channels for
55/// red, green, blue and the alpha (opacity).
56class Color
57{
58public:
59 /// Default constructs a new color that is entirely transparent.
60 Color() { inner.red = inner.green = inner.blue = inner.alpha = 0; }
61 /// Constructs a new color from the given RgbaColor<uint8_t> \a col.
62 Color(const RgbaColor<uint8_t> &col)
63 {
64 inner.red = col.red;
65 inner.green = col.green;
66 inner.blue = col.blue;
67 inner.alpha = col.alpha;
68 }
69 /// Constructs a new color from the given RgbaColor<float> \a col.
70 Color(const RgbaColor<float> &col)
71 {
72 inner.red = uint8_t(col.red * 255);
73 inner.green = uint8_t(col.green * 255);
74 inner.blue = uint8_t(col.blue * 255);
75 inner.alpha = uint8_t(col.alpha * 255);
76 }
77
78 /// Construct a color from an integer encoded as `0xAARRGGBB`
79 [[nodiscard]] static Color from_argb_encoded(uint32_t argb_encoded)
80 {
81 Color col;
82 col.inner.red = (argb_encoded >> 16) & 0xff;
83 col.inner.green = (argb_encoded >> 8) & 0xff;
84 col.inner.blue = argb_encoded & 0xff;
85 col.inner.alpha = (argb_encoded >> 24) & 0xff;
86 return col;
87 }
88
89 /// Returns `(alpha, red, green, blue)` encoded as uint32_t.
90 uint32_t as_argb_encoded() const
91 {
92 return (uint32_t(inner.red) << 16) | (uint32_t(inner.green) << 8) | uint32_t(inner.blue)
93 | (uint32_t(inner.alpha) << 24);
94 }
95
96 /// Construct a color from the alpha, red, green and blue color channel parameters.
97 [[nodiscard]] static Color from_argb_uint8(uint8_t alpha, uint8_t red, uint8_t green,
98 uint8_t blue)
99 {
100 Color col;
101 col.inner.alpha = alpha;
102 col.inner.red = red;
103 col.inner.green = green;
104 col.inner.blue = blue;
105 return col;
106 }
107
108 /// Construct a color from the red, green and blue color channel parameters. The alpha
109 /// channel will have the value 255.
110 [[nodiscard]] static Color from_rgb_uint8(uint8_t red, uint8_t green, uint8_t blue)
111 {
112 return from_argb_uint8(alpha: 255, red, green, blue);
113 }
114
115 /// Construct a color from the alpha, red, green and blue color channel parameters.
116 [[nodiscard]] static Color from_argb_float(float alpha, float red, float green, float blue)
117 {
118 Color col;
119 col.inner.alpha = uint8_t(alpha * 255);
120 col.inner.red = uint8_t(red * 255);
121 col.inner.green = uint8_t(green * 255);
122 col.inner.blue = uint8_t(blue * 255);
123 return col;
124 }
125
126 /// Construct a color from the red, green and blue color channel parameters. The alpha
127 /// channel will have the value 255.
128 [[nodiscard]] static Color from_rgb_float(float red, float green, float blue)
129 {
130 return Color::from_argb_float(alpha: 1.0, red, green, blue);
131 }
132
133 /// Converts this color to an RgbaColor struct for easy destructuring.
134 [[nodiscard]] inline RgbaColor<uint8_t> to_argb_uint() const;
135
136 /// Converts this color to an RgbaColor struct for easy destructuring.
137 [[nodiscard]] inline RgbaColor<float> to_argb_float() const;
138
139 /// Construct a color from the HSV color space components.
140 /// The hue is expected to be in the range between 0 and 360, and the other parameters between 0
141 /// and 1.
142 [[nodiscard]] static Color from_hsva(float h, float s, float v, float a)
143 {
144 Color ret;
145 ret.inner = cbindgen_private::types::slint_color_from_hsva(h, s, v, a);
146 return ret;
147 }
148
149 /// Convert this color to the HSV color space.
150 /// @returns a new HsvaColor.
151 [[nodiscard]] HsvaColor to_hsva() const
152 {
153 HsvaColor hsv {};
154 cbindgen_private::types::slint_color_to_hsva(&inner, &hsv.hue, &hsv.saturation, &hsv.value,
155 &hsv.alpha);
156 return hsv;
157 }
158
159 /// Returns the red channel of the color as u8 in the range 0..255.
160 [[nodiscard]] uint8_t red() const { return inner.red; }
161
162 /// Returns the green channel of the color as u8 in the range 0..255.
163 [[nodiscard]] uint8_t green() const { return inner.green; }
164
165 /// Returns the blue channel of the color as u8 in the range 0..255.
166 [[nodiscard]] uint8_t blue() const { return inner.blue; }
167
168 /// Returns the alpha channel of the color as u8 in the range 0..255.
169 [[nodiscard]] uint8_t alpha() const { return inner.alpha; }
170
171 /// Returns a new version of this color that has the brightness increased
172 /// by the specified factor. This is done by converting the color to the HSV
173 /// color space and multiplying the brightness (value) with (1 + factor).
174 /// The result is converted back to RGB and the alpha channel is unchanged.
175 /// So for example `brighter(0.2)` will increase the brightness by 20%, and
176 /// calling `brighter(-0.5)` will return a color that's 50% darker.
177 [[nodiscard]] inline Color brighter(float factor) const;
178 /// Returns a new version of this color that has the brightness decreased
179 /// by the specified factor. This is done by converting the color to the HSV
180 /// color space and dividing the brightness (value) by (1 + factor). The
181 /// result is converted back to RGB and the alpha channel is unchanged.
182 /// So for example `darker(0.3)` will decrease the brightness by 30%.
183 [[nodiscard]] inline Color darker(float factor) const;
184
185 /// Returns a new version of this color with the opacity decreased by \a factor.
186 ///
187 /// The transparency is obtained by multiplying the alpha channel by `(1 - factor)`.
188 [[nodiscard]] inline Color transparentize(float factor) const;
189
190 /// Returns a new color that is a mix of \a this color and \a other. The specified \a factor is
191 /// clamped to be between `0.0` and `1.0` and then applied to \a this color, while `1.0 -
192 /// factor` is applied to \a other.
193 [[nodiscard]] inline Color mix(const Color &other, float factor) const;
194
195 /// Returns a new version of this color with the opacity set to \a alpha.
196 [[nodiscard]] inline Color with_alpha(float alpha) const;
197
198 /// Returns true if \a lhs has the same values for the individual color channels as \a rhs;
199 /// false otherwise.
200 friend bool operator==(const Color &lhs, const Color &rhs) = default;
201
202 /// Writes the \a color to the specified \a stream and returns a reference to the
203 /// stream.
204 friend std::ostream &operator<<(std::ostream &stream, const Color &color)
205 {
206 // Cast to uint32_t to avoid the components being interpreted as char.
207 return stream << "argb(" << uint32_t(color.inner.alpha) << ", " << uint32_t(color.inner.red)
208 << ", " << uint32_t(color.inner.green) << ", " << uint32_t(color.inner.blue)
209 << ")";
210 }
211
212#if !defined(DOXYGEN)
213 // FIXME: we need this to create GradientStop
214 operator const cbindgen_private::types::Color &() const { return inner; }
215#endif
216
217private:
218 cbindgen_private::types::Color inner;
219 friend class private_api::LinearGradientBrush;
220 friend class Brush;
221};
222
223inline Color Color::brighter(float factor) const
224{
225 Color result;
226 cbindgen_private::types::slint_color_brighter(col: &inner, factor, out: &result.inner);
227 return result;
228}
229
230inline Color Color::darker(float factor) const
231{
232 Color result;
233 cbindgen_private::types::slint_color_darker(col: &inner, factor, out: &result.inner);
234 return result;
235}
236
237inline Color Color::transparentize(float factor) const
238{
239 Color result;
240 cbindgen_private::types::slint_color_transparentize(col: &inner, factor, out: &result.inner);
241 return result;
242}
243
244inline Color Color::mix(const Color &other, float factor) const
245{
246 Color result;
247 cbindgen_private::types::slint_color_mix(col1: &inner, col2: &other.inner, factor, out: &result.inner);
248 return result;
249}
250
251inline Color Color::with_alpha(float alpha) const
252{
253 Color result;
254 cbindgen_private::types::slint_color_with_alpha(col: &inner, alpha, out: &result.inner);
255 return result;
256}
257
258/// Constructs a new RgbaColor<uint8_t> from the color \a color.
259template<>
260inline RgbaColor<uint8_t>::RgbaColor(const Color &color)
261{
262 red = color.red();
263 green = color.green();
264 blue = color.blue();
265 alpha = color.alpha();
266}
267
268/// Constructs a new RgbaColor<float> from the color \a color.
269template<>
270inline RgbaColor<float>::RgbaColor(const Color &color)
271{
272 red = float(color.red()) / 255.f;
273 green = float(color.green()) / 255.f;
274 blue = float(color.blue()) / 255.f;
275 alpha = float(color.alpha()) / 255.f;
276}
277
278RgbaColor<uint8_t> Color::to_argb_uint() const
279{
280 return RgbaColor<uint8_t>(*this);
281}
282
283RgbaColor<float> Color::to_argb_float() const
284{
285 return RgbaColor<float>(*this);
286}
287
288namespace private_api {
289
290template<>
291inline void
292Property<Color>::set_animated_value(const Color &new_value,
293 const cbindgen_private::PropertyAnimation &animation_data) const
294{
295 cbindgen_private::slint_property_set_animated_value_color(handle: &inner, from: value, to: new_value,
296 animation_data: &animation_data);
297}
298
299} // namespace private_api
300
301} // namespace slint
302

source code of slint/api/cpp/include/slint_color.h