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#include <string_view>
6#include "slint_color.h"
7#include "slint_brush_internal.h"
8#include "slint_string.h"
9
10namespace slint {
11
12namespace private_api {
13
14using cbindgen_private::types::GradientStop;
15
16/// \private
17/// LinearGradientBrush represents a gradient for a brush that is a linear sequence of color stops,
18/// that are aligned at a specific angle.
19class LinearGradientBrush
20{
21public:
22 /// Constructs an empty linear gradient with no color stops.
23 LinearGradientBrush() = default;
24 /// Constructs a new linear gradient with the specified \a angle. The color stops will be
25 /// constructed from the stops array pointed to be \a firstStop, with the length \a stopCount.
26 LinearGradientBrush(float angle, const GradientStop *firstStop, int stopCount)
27 : inner(make_linear_gradient(angle, firstStop, stopCount))
28 {
29 }
30
31 /// Returns the linear gradient's angle in degrees.
32 float angle() const
33 {
34 // The gradient's first stop is a fake stop to store the angle
35 return inner[0].position;
36 }
37
38 /// Returns the number of gradient stops.
39 int stopCount() const { return int(inner.size()) - 1; }
40
41 /// Returns a pointer to the first gradient stop; undefined if the gradient has not stops.
42 const GradientStop *stopsBegin() const { return inner.begin() + 1; }
43 /// Returns a pointer past the last gradient stop. The returned pointer cannot be dereferenced,
44 /// it can only be used for comparison.
45 const GradientStop *stopsEnd() const { return inner.end(); }
46
47private:
48 cbindgen_private::types::LinearGradientBrush inner;
49
50 friend class slint::Brush;
51
52 static SharedVector<private_api::GradientStop>
53 make_linear_gradient(float angle, const GradientStop *firstStop, int stopCount)
54 {
55 SharedVector<private_api::GradientStop> gradient;
56 gradient.push_back(value: { .color: Color::from_argb_encoded(argb_encoded: 0).inner, .position: angle });
57 for (int i = 0; i < stopCount; ++i, ++firstStop)
58 gradient.push_back(value: *firstStop);
59 return gradient;
60 }
61};
62
63/// \private
64/// RadialGradientBrush represents a circular gradient centered in the middle
65class RadialGradientBrush
66{
67public:
68 /// Constructs an empty linear gradient with no color stops.
69 RadialGradientBrush() = default;
70 /// Constructs a new circular radial gradient . The color stops will be
71 /// constructed from the stops array pointed to be \a firstStop, with the length \a stopCount.
72 RadialGradientBrush(const GradientStop *firstStop, int stopCount)
73 : inner(make_circle_gradient(firstStop, stopCount))
74 {
75 }
76
77 /// Returns the number of gradient stops.
78 int stopCount() const { return int(inner.size()); }
79
80 /// Returns a pointer to the first gradient stop; undefined if the gradient has not stops.
81 const GradientStop *stopsBegin() const { return inner.begin(); }
82 /// Returns a pointer past the last gradient stop. The returned pointer cannot be dereferenced,
83 /// it can only be used for comparison.
84 const GradientStop *stopsEnd() const { return inner.end(); }
85
86private:
87 cbindgen_private::types::RadialGradientBrush inner;
88
89 friend class slint::Brush;
90
91 static SharedVector<private_api::GradientStop>
92 make_circle_gradient(const GradientStop *firstStop, int stopCount)
93 {
94 SharedVector<private_api::GradientStop> gradient;
95 for (int i = 0; i < stopCount; ++i, ++firstStop)
96 gradient.push_back(value: *firstStop);
97 return gradient;
98 }
99};
100
101}
102
103/// Brush is used to declare how to fill or outline shapes, such as rectangles, paths or text. A
104/// brush is either a solid color or a linear gradient.
105class Brush
106{
107public:
108 /// Constructs a new brush that is a transparent color.
109 Brush() : Brush(Color {}) { }
110 /// Constructs a new brush that is of color \a color.
111 Brush(const Color &color) : data(Inner::SolidColor(0: color.inner)) { }
112 /// \private
113 /// Constructs a new brush that is the gradient \a gradient.
114 Brush(const private_api::LinearGradientBrush &gradient)
115 : data(Inner::LinearGradient(0: gradient.inner))
116 {
117 }
118
119 /// \private
120 /// Constructs a new brush that is the gradient \a gradient.
121 Brush(const private_api::RadialGradientBrush &gradient)
122 : data(Inner::RadialGradient(0: gradient.inner))
123 {
124 }
125
126 /// Returns the color of the brush. If the brush is a gradient, this function returns the color
127 /// of the first stop.
128 inline Color color() const;
129
130 /// Returns a new version of this brush that has the brightness increased
131 /// by the specified factor. This is done by calling Color::brighter on
132 /// all the colors of this brush.
133 [[nodiscard]] inline Brush brighter(float factor) const;
134 /// Returns a new version of this color that has the brightness decreased
135 /// by the specified factor. This is done by calling Color::darker on
136 /// all the colors of this brush.
137 [[nodiscard]] inline Brush darker(float factor) const;
138
139 /// Returns a new version of this brush with the opacity decreased by \a factor.
140 ///
141 /// This is done by calling Color::transparentize on all the colors of this brush.
142 [[nodiscard]] inline Brush transparentize(float factor) const;
143
144 /// Returns a new version of this brush with the related color's opacities
145 /// set to \a alpha.
146 [[nodiscard]] inline Brush with_alpha(float alpha) const;
147
148 /// Returns true if \a a is equal to \a b. If \a a holds a color, then \a b must also hold a
149 /// color that is identical to \a a's color. If it holds a gradient, then the gradients must be
150 /// identical. Returns false if the brushes differ in what they hold or their respective color
151 /// or gradient are not equal.
152 friend bool operator==(const Brush &a, const Brush &b) { return a.data == b.data; }
153 /// Returns false if \a is not equal to \a b; true otherwise.
154 friend bool operator!=(const Brush &a, const Brush &b) { return a.data != b.data; }
155
156private:
157 using Tag = cbindgen_private::types::Brush::Tag;
158 using Inner = cbindgen_private::types::Brush;
159 Inner data;
160 friend struct private_api::Property<Brush>;
161};
162
163Color Brush::color() const
164{
165 Color result;
166 switch (data.tag) {
167 case Tag::SolidColor:
168 result.inner = data.solid_color._0;
169 break;
170 case Tag::LinearGradient:
171 if (data.linear_gradient._0.size() > 1) {
172 result.inner = data.linear_gradient._0[1].color;
173 }
174 break;
175 case Tag::RadialGradient:
176 if (data.radial_gradient._0.size() > 0) {
177 result.inner = data.radial_gradient._0[0].color;
178 }
179 break;
180 }
181 return result;
182}
183
184inline Brush Brush::brighter(float factor) const
185{
186 Brush result = *this;
187 switch (data.tag) {
188 case Tag::SolidColor:
189 cbindgen_private::types::slint_color_brighter(col: &data.solid_color._0, factor,
190 out: &result.data.solid_color._0);
191 break;
192 case Tag::LinearGradient:
193 for (std::size_t i = 1; i < data.linear_gradient._0.size(); ++i) {
194 cbindgen_private::types::slint_color_brighter(col: &data.linear_gradient._0[i].color, factor,
195 out: &result.data.linear_gradient._0[i].color);
196 }
197 break;
198 case Tag::RadialGradient:
199 for (std::size_t i = 0; i < data.linear_gradient._0.size(); ++i) {
200 cbindgen_private::types::slint_color_brighter(col: &data.radial_gradient._0[i].color, factor,
201 out: &result.data.radial_gradient._0[i].color);
202 }
203 break;
204 }
205 return result;
206}
207
208inline Brush Brush::darker(float factor) const
209{
210 Brush result = *this;
211 switch (data.tag) {
212 case Tag::SolidColor:
213 cbindgen_private::types::slint_color_darker(col: &data.solid_color._0, factor,
214 out: &result.data.solid_color._0);
215 break;
216 case Tag::LinearGradient:
217 for (std::size_t i = 1; i < data.linear_gradient._0.size(); ++i) {
218 cbindgen_private::types::slint_color_darker(col: &data.linear_gradient._0[i].color, factor,
219 out: &result.data.linear_gradient._0[i].color);
220 }
221 break;
222 case Tag::RadialGradient:
223 for (std::size_t i = 0; i < data.linear_gradient._0.size(); ++i) {
224 cbindgen_private::types::slint_color_darker(col: &data.radial_gradient._0[i].color, factor,
225 out: &result.data.radial_gradient._0[i].color);
226 }
227 break;
228 }
229 return result;
230}
231
232inline Brush Brush::transparentize(float factor) const
233{
234 Brush result = *this;
235 switch (data.tag) {
236 case Tag::SolidColor:
237 cbindgen_private::types::slint_color_transparentize(col: &data.solid_color._0, factor,
238 out: &result.data.solid_color._0);
239 break;
240 case Tag::LinearGradient:
241 for (std::size_t i = 1; i < data.linear_gradient._0.size(); ++i) {
242 cbindgen_private::types::slint_color_transparentize(
243 col: &data.linear_gradient._0[i].color, factor,
244 out: &result.data.linear_gradient._0[i].color);
245 }
246 break;
247 case Tag::RadialGradient:
248 for (std::size_t i = 0; i < data.linear_gradient._0.size(); ++i) {
249 cbindgen_private::types::slint_color_transparentize(
250 col: &data.radial_gradient._0[i].color, factor,
251 out: &result.data.radial_gradient._0[i].color);
252 }
253 break;
254 }
255 return result;
256}
257
258inline Brush Brush::with_alpha(float alpha) const
259{
260 Brush result = *this;
261 switch (data.tag) {
262 case Tag::SolidColor:
263 cbindgen_private::types::slint_color_with_alpha(col: &data.solid_color._0, alpha,
264 out: &result.data.solid_color._0);
265 break;
266 case Tag::LinearGradient:
267 for (std::size_t i = 1; i < data.linear_gradient._0.size(); ++i) {
268 cbindgen_private::types::slint_color_with_alpha(
269 col: &data.linear_gradient._0[i].color, alpha,
270 out: &result.data.linear_gradient._0[i].color);
271 }
272 break;
273 case Tag::RadialGradient:
274 for (std::size_t i = 0; i < data.linear_gradient._0.size(); ++i) {
275 cbindgen_private::types::slint_color_with_alpha(
276 col: &data.radial_gradient._0[i].color, alpha,
277 out: &result.data.radial_gradient._0[i].color);
278 }
279 break;
280 }
281 return result;
282}
283
284namespace private_api {
285
286template<>
287inline void Property<slint::Brush>::set_animated_value(
288 const slint::Brush &new_value,
289 const cbindgen_private::PropertyAnimation &animation_data) const
290{
291 cbindgen_private::slint_property_set_animated_value_brush(&inner, &value, &new_value,
292 &animation_data);
293}
294
295} // namespace private_api
296
297} // namespace slint
298

Provided by KDAB

Privacy Policy

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