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

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