1 | // // [Blend2D] |
2 | // 2D Vector Graphics Powered by a JIT Compiler. |
3 | // |
4 | // [License] |
5 | // Zlib - See LICENSE.md file in the package. |
6 | |
7 | #ifndef BLEND2D_BLGRADIENT_H |
8 | #define BLEND2D_BLGRADIENT_H |
9 | |
10 | #include "./blgeometry.h" |
11 | #include "./blmatrix.h" |
12 | #include "./blrgba.h" |
13 | #include "./blvariant.h" |
14 | |
15 | BL_DIAGNOSTIC_PUSH(BL_DIAGNOSTIC_NO_SHADOW) |
16 | |
17 | //! \addtogroup blend2d_api_styling |
18 | //! \{ |
19 | |
20 | // ============================================================================ |
21 | // [Constants] |
22 | // ============================================================================ |
23 | |
24 | //! Gradient type. |
25 | BL_DEFINE_ENUM(BLGradientType) { |
26 | //! Linear gradient type. |
27 | BL_GRADIENT_TYPE_LINEAR = 0, |
28 | //! Radial gradient type. |
29 | BL_GRADIENT_TYPE_RADIAL = 1, |
30 | //! Conical gradient type. |
31 | BL_GRADIENT_TYPE_CONICAL = 2, |
32 | |
33 | //! Count of gradient types. |
34 | BL_GRADIENT_TYPE_COUNT = 3 |
35 | }; |
36 | |
37 | //! Gradient data index. |
38 | BL_DEFINE_ENUM(BLGradientValue) { |
39 | //! x0 - start 'x' for Linear/Radial and center 'x' for Conical. |
40 | BL_GRADIENT_VALUE_COMMON_X0 = 0, |
41 | //! y0 - start 'y' for Linear/Radial and center 'y' for Conical. |
42 | BL_GRADIENT_VALUE_COMMON_Y0 = 1, |
43 | //! x1 - end 'x' for Linear/Radial. |
44 | BL_GRADIENT_VALUE_COMMON_X1 = 2, |
45 | //! y1 - end 'y' for Linear/Radial. |
46 | BL_GRADIENT_VALUE_COMMON_Y1 = 3, |
47 | //! Radial gradient r0 radius. |
48 | BL_GRADIENT_VALUE_RADIAL_R0 = 4, |
49 | //! Conical gradient angle. |
50 | BL_GRADIENT_VALUE_CONICAL_ANGLE = 2, |
51 | |
52 | //! Count of gradient values. |
53 | BL_GRADIENT_VALUE_COUNT = 6 |
54 | }; |
55 | |
56 | // ============================================================================ |
57 | // [BLGradientStop] |
58 | // ============================================================================ |
59 | |
60 | //! Defines an `offset` and `rgba` color that us used by `BLGradient` to define |
61 | //! a linear transition between colors. |
62 | struct BLGradientStop { |
63 | double offset; |
64 | BLRgba64 rgba; |
65 | |
66 | // -------------------------------------------------------------------------- |
67 | #ifdef __cplusplus |
68 | //! \name Construction & Destruction |
69 | //! \{ |
70 | |
71 | BL_INLINE BLGradientStop() noexcept = default; |
72 | BL_INLINE BLGradientStop(const BLGradientStop& other) noexcept = default; |
73 | |
74 | BL_INLINE BLGradientStop(double offset, const BLRgba32& rgba32) noexcept |
75 | : offset(offset), |
76 | rgba(rgba32) {} |
77 | |
78 | BL_INLINE BLGradientStop(double offset, const BLRgba64& rgba64) noexcept |
79 | : offset(offset), |
80 | rgba(rgba64) {} |
81 | |
82 | //! \} |
83 | |
84 | //! \name Overloaded Operators |
85 | //! \{ |
86 | |
87 | BL_INLINE bool operator==(const BLGradientStop& other) const noexcept { return equals(other); } |
88 | BL_INLINE bool operator!=(const BLGradientStop& other) const noexcept { return !equals(other); } |
89 | |
90 | //! \} |
91 | |
92 | //! \name Common Functionality |
93 | //! \{ |
94 | |
95 | BL_INLINE void reset() noexcept { |
96 | this->offset = 0.0; |
97 | this->rgba.reset(); |
98 | } |
99 | |
100 | BL_INLINE void reset(double offset, const BLRgba32& rgba32) noexcept { |
101 | this->offset = offset; |
102 | this->rgba.reset(rgba32); |
103 | } |
104 | |
105 | BL_INLINE void reset(double offset, const BLRgba64& rgba64) noexcept { |
106 | this->offset = offset; |
107 | this->rgba.reset(rgba64); |
108 | } |
109 | |
110 | BL_INLINE bool equals(const BLGradientStop& other) const noexcept { |
111 | return blEquals(this->offset, other.offset) & |
112 | blEquals(this->rgba , other.rgba ) ; |
113 | } |
114 | |
115 | //! \} |
116 | #endif |
117 | // -------------------------------------------------------------------------- |
118 | }; |
119 | |
120 | // ============================================================================ |
121 | // [BLLinearGradientValues] |
122 | // ============================================================================ |
123 | |
124 | //! Linear gradient values packed into a structure. |
125 | struct BLLinearGradientValues { |
126 | double x0; |
127 | double y0; |
128 | double x1; |
129 | double y1; |
130 | |
131 | // -------------------------------------------------------------------------- |
132 | #ifdef __cplusplus |
133 | //! \name Construction & Destruction |
134 | //! \{ |
135 | |
136 | BL_INLINE BLLinearGradientValues() noexcept = default; |
137 | BL_INLINE BLLinearGradientValues(const BLLinearGradientValues& other) noexcept = default; |
138 | |
139 | BL_INLINE BLLinearGradientValues(double x0, double y0, double x1, double y1) noexcept |
140 | : x0(x0), |
141 | y0(y0), |
142 | x1(x1), |
143 | y1(y1) {} |
144 | |
145 | //! \} |
146 | |
147 | //! \name Common Functionality |
148 | //! \{ |
149 | |
150 | BL_INLINE void reset() noexcept { memset(this, 0, sizeof(*this)); } |
151 | |
152 | //! \} |
153 | #endif |
154 | // -------------------------------------------------------------------------- |
155 | }; |
156 | |
157 | // ============================================================================ |
158 | // [BLRadialGradientValues] |
159 | // ============================================================================ |
160 | |
161 | //! Radial gradient values packed into a structure. |
162 | struct BLRadialGradientValues { |
163 | double x0; |
164 | double y0; |
165 | double x1; |
166 | double y1; |
167 | double r0; |
168 | |
169 | // -------------------------------------------------------------------------- |
170 | #ifdef __cplusplus |
171 | //! \name Construction & Destruction |
172 | //! \{ |
173 | |
174 | BL_INLINE BLRadialGradientValues() noexcept = default; |
175 | BL_INLINE BLRadialGradientValues(const BLRadialGradientValues& other) noexcept = default; |
176 | |
177 | BL_INLINE BLRadialGradientValues(double x0, double y0, double x1, double y1, double r0) noexcept |
178 | : x0(x0), |
179 | y0(y0), |
180 | x1(x1), |
181 | y1(y1), |
182 | r0(r0) {} |
183 | |
184 | //! \} |
185 | |
186 | //! \name Common Functionality |
187 | //! \{ |
188 | |
189 | BL_INLINE void reset() noexcept { memset(this, 0, sizeof(*this)); } |
190 | |
191 | //! \} |
192 | #endif |
193 | // -------------------------------------------------------------------------- |
194 | }; |
195 | |
196 | // ============================================================================ |
197 | // [BLConicalGradientValues] |
198 | // ============================================================================ |
199 | |
200 | //! Conical gradient values packed into a structure. |
201 | struct BLConicalGradientValues { |
202 | double x0; |
203 | double y0; |
204 | double angle; |
205 | |
206 | // -------------------------------------------------------------------------- |
207 | #ifdef __cplusplus |
208 | //! \name Construction & Destruction |
209 | //! \{ |
210 | |
211 | BL_INLINE BLConicalGradientValues() noexcept = default; |
212 | BL_INLINE BLConicalGradientValues(const BLConicalGradientValues& other) noexcept = default; |
213 | |
214 | BL_INLINE BLConicalGradientValues(double x0, double y0, double angle) noexcept |
215 | : x0(x0), |
216 | y0(y0), |
217 | angle(angle) {} |
218 | |
219 | //! \} |
220 | |
221 | //! \name Common Functionality |
222 | //! \{ |
223 | |
224 | BL_INLINE void reset() noexcept { memset(this, 0, sizeof(*this)); } |
225 | |
226 | //! \} |
227 | #endif |
228 | // -------------------------------------------------------------------------- |
229 | }; |
230 | |
231 | // ============================================================================ |
232 | // [BLGradient - Core] |
233 | // ============================================================================ |
234 | |
235 | //! Gradient [C Interface - Impl]. |
236 | struct BLGradientImpl { |
237 | //! Union of either raw `stops` & `size` members or their `view`. |
238 | union { |
239 | struct { |
240 | //! Gradient stop data. |
241 | BLGradientStop* stops; |
242 | //! Gradient stop count. |
243 | size_t size; |
244 | }; |
245 | #ifdef __cplusplus |
246 | //! Gradient stop view (C++ only). |
247 | BLArrayView<BLGradientStop> view; |
248 | #endif |
249 | }; |
250 | |
251 | //! Stop capacity. |
252 | size_t capacity; |
253 | |
254 | //! Reference count. |
255 | volatile size_t refCount; |
256 | //! Impl type. |
257 | uint8_t implType; |
258 | //! Impl traits. |
259 | uint8_t implTraits; |
260 | //! Memory pool data. |
261 | uint16_t memPoolData; |
262 | |
263 | //! Gradient type, see `BLGradientType`. |
264 | uint8_t gradientType; |
265 | //! Gradient extend mode, see `BLExtendMode`. |
266 | uint8_t extendMode; |
267 | //! Type of the transformation matrix. |
268 | uint8_t matrixType; |
269 | //! Reserved, must be zero. |
270 | uint8_t reserved[1]; |
271 | |
272 | //! Gradient transformation matrix. |
273 | BLMatrix2D matrix; |
274 | |
275 | union { |
276 | //! Gradient values (coordinates, radius, angle). |
277 | double values[BL_GRADIENT_VALUE_COUNT]; |
278 | //! Linear parameters. |
279 | BLLinearGradientValues linear; |
280 | //! Radial parameters. |
281 | BLRadialGradientValues radial; |
282 | //! Conical parameters. |
283 | BLConicalGradientValues conical; |
284 | }; |
285 | }; |
286 | |
287 | //! Gradient [C Interface - Core]. |
288 | struct BLGradientCore { |
289 | BLGradientImpl* impl; |
290 | }; |
291 | |
292 | // ============================================================================ |
293 | // [BLGradient - C++] |
294 | // ============================================================================ |
295 | |
296 | #ifdef __cplusplus |
297 | //! Gradient [C++ API]. |
298 | class BLGradient : public BLGradientCore { |
299 | public: |
300 | //! \cond INTERNAL |
301 | static constexpr const uint32_t kImplType = BL_IMPL_TYPE_GRADIENT; |
302 | //! \endcond |
303 | |
304 | //! \name Construction & Destruction |
305 | //! \{ |
306 | |
307 | BL_INLINE BLGradient() noexcept { this->impl = none().impl; } |
308 | BL_INLINE BLGradient(BLGradient&& other) noexcept { blVariantInitMove(this, &other); } |
309 | BL_INLINE BLGradient(const BLGradient& other) noexcept { blVariantInitWeak(this, &other); } |
310 | BL_INLINE explicit BLGradient(BLGradientImpl* impl) noexcept { this->impl = impl; } |
311 | |
312 | BL_INLINE explicit BLGradient(uint32_t type, const double* values = nullptr) noexcept { |
313 | blGradientInitAs(this, type, values, BL_EXTEND_MODE_PAD, nullptr, 0, nullptr); |
314 | } |
315 | |
316 | BL_INLINE explicit BLGradient(const BLLinearGradientValues& values, uint32_t extendMode = BL_EXTEND_MODE_PAD) noexcept { |
317 | blGradientInitAs(this, BL_GRADIENT_TYPE_LINEAR, &values, extendMode, nullptr, 0, nullptr); |
318 | } |
319 | |
320 | BL_INLINE explicit BLGradient(const BLRadialGradientValues& values, uint32_t extendMode = BL_EXTEND_MODE_PAD) noexcept { |
321 | blGradientInitAs(this, BL_GRADIENT_TYPE_RADIAL, &values, extendMode, nullptr, 0, nullptr); |
322 | } |
323 | |
324 | BL_INLINE explicit BLGradient(const BLConicalGradientValues& values, uint32_t extendMode = BL_EXTEND_MODE_PAD) noexcept { |
325 | blGradientInitAs(this, BL_GRADIENT_TYPE_CONICAL, &values, extendMode, nullptr, 0, nullptr); |
326 | } |
327 | |
328 | BL_INLINE BLGradient(const BLLinearGradientValues& values, uint32_t extendMode, const BLGradientStop* stops, size_t n) noexcept { |
329 | blGradientInitAs(this, BL_GRADIENT_TYPE_LINEAR, &values, extendMode, stops, n, nullptr); |
330 | } |
331 | |
332 | BL_INLINE BLGradient(const BLRadialGradientValues& values, uint32_t extendMode, const BLGradientStop* stops, size_t n) noexcept { |
333 | blGradientInitAs(this, BL_GRADIENT_TYPE_RADIAL, &values, extendMode, stops, n, nullptr); |
334 | } |
335 | |
336 | BL_INLINE BLGradient(const BLConicalGradientValues& values, uint32_t extendMode, const BLGradientStop* stops, size_t n) noexcept { |
337 | blGradientInitAs(this, BL_GRADIENT_TYPE_CONICAL, &values, extendMode, stops, n, nullptr); |
338 | } |
339 | |
340 | BL_INLINE BLGradient(const BLLinearGradientValues& values, uint32_t extendMode, const BLGradientStop* stops, size_t n, const BLMatrix2D& m) noexcept { |
341 | blGradientInitAs(this, BL_GRADIENT_TYPE_LINEAR, &values, extendMode, stops, n, &m); |
342 | } |
343 | |
344 | BL_INLINE BLGradient(const BLRadialGradientValues& values, uint32_t extendMode, const BLGradientStop* stops, size_t n, const BLMatrix2D& m) noexcept { |
345 | blGradientInitAs(this, BL_GRADIENT_TYPE_RADIAL, &values, extendMode, stops, n, &m); |
346 | } |
347 | |
348 | BL_INLINE BLGradient(const BLConicalGradientValues& values, uint32_t extendMode, const BLGradientStop* stops, size_t n, const BLMatrix2D& m) noexcept { |
349 | blGradientInitAs(this, BL_GRADIENT_TYPE_CONICAL, &values, extendMode, stops, n, &m); |
350 | } |
351 | |
352 | BL_INLINE ~BLGradient() noexcept { blGradientReset(this); } |
353 | |
354 | //! \} |
355 | |
356 | //! \name Overloaded Operators |
357 | //! \{ |
358 | |
359 | BL_INLINE BLGradient& operator=(BLGradient&& other) noexcept { blGradientAssignMove(this, &other); return *this; } |
360 | BL_INLINE BLGradient& operator=(const BLGradient& other) noexcept { blGradientAssignWeak(this, &other); return *this; } |
361 | |
362 | BL_INLINE bool operator==(const BLGradient& other) const noexcept { return blGradientEquals(this, &other); } |
363 | BL_INLINE bool operator!=(const BLGradient& other) const noexcept { return !blGradientEquals(this, &other); } |
364 | |
365 | //! \} |
366 | |
367 | //! \name Common Functionality |
368 | //! \{ |
369 | |
370 | BL_INLINE BLResult reset() noexcept { return blGradientReset(this); } |
371 | BL_INLINE void swap(BLGradient& other) noexcept { std::swap(this->impl, other.impl); } |
372 | |
373 | BL_INLINE BLResult assign(BLGradient&& other) noexcept { return blGradientAssignMove(this, &other); } |
374 | BL_INLINE BLResult assign(const BLGradient& other) noexcept { return blGradientAssignWeak(this, &other); } |
375 | |
376 | //! Tests whether the gradient is a built-in null instance. |
377 | BL_INLINE bool isNone() const noexcept { return (impl->implTraits & BL_IMPL_TRAIT_NULL) != 0; } |
378 | |
379 | BL_INLINE bool equals(const BLGradient& other) const noexcept { return blGradientEquals(this, &other); } |
380 | |
381 | //! \} |
382 | |
383 | //! \name Create Gradient |
384 | //! \{ |
385 | |
386 | BL_INLINE BLResult create(const BLLinearGradientValues& values, uint32_t extendMode = BL_EXTEND_MODE_PAD) noexcept { |
387 | return blGradientCreate(this, BL_GRADIENT_TYPE_LINEAR, &values, extendMode, nullptr, 0, nullptr); |
388 | } |
389 | |
390 | BL_INLINE BLResult create(const BLRadialGradientValues& values, uint32_t extendMode = BL_EXTEND_MODE_PAD) noexcept { |
391 | return blGradientCreate(this, BL_GRADIENT_TYPE_RADIAL, &values, extendMode, nullptr, 0, nullptr); |
392 | } |
393 | |
394 | BL_INLINE BLResult create(const BLConicalGradientValues& values, uint32_t extendMode = BL_EXTEND_MODE_PAD) noexcept { |
395 | return blGradientCreate(this, BL_GRADIENT_TYPE_CONICAL, &values, extendMode, nullptr, 0, nullptr); |
396 | } |
397 | |
398 | BL_INLINE BLResult create(const BLLinearGradientValues& values, uint32_t extendMode, const BLGradientStop* stops, size_t n) noexcept { |
399 | return blGradientCreate(this, BL_GRADIENT_TYPE_LINEAR, &values, extendMode, stops, n, nullptr); |
400 | } |
401 | |
402 | BL_INLINE BLResult create(const BLRadialGradientValues& values, uint32_t extendMode, const BLGradientStop* stops, size_t n) noexcept { |
403 | return blGradientCreate(this, BL_GRADIENT_TYPE_RADIAL, &values, extendMode, stops, n, nullptr); |
404 | } |
405 | |
406 | BL_INLINE BLResult create(const BLConicalGradientValues& values, uint32_t extendMode, const BLGradientStop* stops, size_t n) noexcept { |
407 | return blGradientCreate(this, BL_GRADIENT_TYPE_CONICAL, &values, extendMode, stops, n, nullptr); |
408 | } |
409 | |
410 | BL_INLINE BLResult create(const BLLinearGradientValues& values, uint32_t extendMode, const BLGradientStop* stops, size_t n, const BLMatrix2D& m) noexcept { |
411 | return blGradientCreate(this, BL_GRADIENT_TYPE_LINEAR, &values, extendMode, stops, n, &m); |
412 | } |
413 | |
414 | BL_INLINE BLResult create(const BLRadialGradientValues& values, uint32_t extendMode, const BLGradientStop* stops, size_t n, const BLMatrix2D& m) noexcept { |
415 | return blGradientCreate(this, BL_GRADIENT_TYPE_RADIAL, &values, extendMode, stops, n, &m); |
416 | } |
417 | |
418 | BL_INLINE BLResult create(const BLConicalGradientValues& values, uint32_t extendMode, const BLGradientStop* stops, size_t n, const BLMatrix2D& m) noexcept { |
419 | return blGradientCreate(this, BL_GRADIENT_TYPE_CONICAL, &values, extendMode, stops, n, &m); |
420 | } |
421 | |
422 | //! \} |
423 | |
424 | //! \name Gradient Options |
425 | //! \{ |
426 | |
427 | //! Returns the type of the gradient, see `BLGradientType`. |
428 | BL_INLINE uint32_t type() const noexcept { return impl->gradientType; } |
429 | //! Sets the gradient type, see `BLGradientType`. |
430 | BL_INLINE BLResult setType(uint32_t type) noexcept { return blGradientSetType(this, type); } |
431 | |
432 | //! Returns the gradient extend mode, see `BLExtendMode`. |
433 | BL_INLINE uint32_t extendMode() const noexcept { return impl->extendMode; } |
434 | //! Set the gradient extend mode, see `BLExtendMode`. |
435 | BL_INLINE BLResult setExtendMode(uint32_t extendMode) noexcept { return blGradientSetExtendMode(this, extendMode); } |
436 | //! Resets the gradient extend mode to `BL_EXTEND_MODE_PAD`. |
437 | BL_INLINE BLResult resetExtendMode() noexcept { return blGradientSetExtendMode(this, BL_EXTEND_MODE_PAD); } |
438 | |
439 | BL_INLINE double value(size_t index) const noexcept { |
440 | BL_ASSERT(index < BL_GRADIENT_VALUE_COUNT); |
441 | return impl->values[index]; |
442 | } |
443 | |
444 | BL_INLINE const BLLinearGradientValues& linear() const noexcept { return impl->linear; } |
445 | BL_INLINE const BLRadialGradientValues& radial() const noexcept { return impl->radial; } |
446 | BL_INLINE const BLConicalGradientValues& conical() const noexcept { return impl->conical; } |
447 | |
448 | BL_INLINE BLResult setValue(size_t index, double value) noexcept { return blGradientSetValue(this, index, value); } |
449 | BL_INLINE BLResult setValues(size_t index, const double* values, size_t n) noexcept { return blGradientSetValues(this, index, values, n); } |
450 | |
451 | BL_INLINE BLResult setValues(const BLLinearGradientValues& values) noexcept { return setValues(0, (const double*)&values, sizeof(BLLinearGradientValues) / sizeof(double)); } |
452 | BL_INLINE BLResult setValues(const BLRadialGradientValues& values) noexcept { return setValues(0, (const double*)&values, sizeof(BLRadialGradientValues) / sizeof(double)); } |
453 | BL_INLINE BLResult setValues(const BLConicalGradientValues& values) noexcept { return setValues(0, (const double*)&values, sizeof(BLConicalGradientValues) / sizeof(double)); } |
454 | |
455 | BL_INLINE double x0() const noexcept { return impl->values[BL_GRADIENT_VALUE_COMMON_X0]; } |
456 | BL_INLINE double y0() const noexcept { return impl->values[BL_GRADIENT_VALUE_COMMON_Y0]; } |
457 | BL_INLINE double x1() const noexcept { return impl->values[BL_GRADIENT_VALUE_COMMON_X1]; } |
458 | BL_INLINE double y1() const noexcept { return impl->values[BL_GRADIENT_VALUE_COMMON_Y1]; } |
459 | BL_INLINE double r0() const noexcept { return impl->values[BL_GRADIENT_VALUE_RADIAL_R0]; } |
460 | BL_INLINE double angle() const noexcept { return impl->values[BL_GRADIENT_VALUE_CONICAL_ANGLE]; } |
461 | |
462 | BL_INLINE BLResult setX0(double value) noexcept { return setValue(BL_GRADIENT_VALUE_COMMON_X0, value); } |
463 | BL_INLINE BLResult setY0(double value) noexcept { return setValue(BL_GRADIENT_VALUE_COMMON_Y0, value); } |
464 | BL_INLINE BLResult setX1(double value) noexcept { return setValue(BL_GRADIENT_VALUE_COMMON_X1, value); } |
465 | BL_INLINE BLResult setY1(double value) noexcept { return setValue(BL_GRADIENT_VALUE_COMMON_Y1, value); } |
466 | BL_INLINE BLResult setR0(double value) noexcept { return setValue(BL_GRADIENT_VALUE_RADIAL_R0, value); } |
467 | BL_INLINE BLResult setAngle(double value) noexcept { return setValue(BL_GRADIENT_VALUE_CONICAL_ANGLE, value); } |
468 | |
469 | //! \} |
470 | |
471 | //! \name Gradient Stops |
472 | //! \{ |
473 | |
474 | BL_INLINE bool empty() const noexcept { return impl->size == 0; } |
475 | BL_INLINE size_t size() const noexcept { return impl->size; } |
476 | BL_INLINE size_t capacity() const noexcept { return impl->capacity; } |
477 | |
478 | //! Reserve the capacity of gradient stops for at least `n` stops. |
479 | BL_INLINE BLResult reserve(size_t n) noexcept { return blGradientReserve(this, n); } |
480 | //! Shrink the capacity of gradient stops to fit the current usage. |
481 | BL_INLINE BLResult shrink() noexcept { return blGradientShrink(this); } |
482 | |
483 | BL_INLINE const BLGradientStop* stops() const noexcept { return impl->stops; } |
484 | |
485 | BL_INLINE const BLGradientStop& stopAt(size_t i) const noexcept { |
486 | BL_ASSERT(i < impl->size); |
487 | return impl->stops[i]; |
488 | } |
489 | |
490 | BL_INLINE BLResult resetStops() noexcept { return blGradientResetStops(this); } |
491 | BL_INLINE BLResult assignStops(const BLGradientStop* stops, size_t n) noexcept { return blGradientAssignStops(this, stops, n); } |
492 | BL_INLINE BLResult addStop(double offset, const BLRgba32& rgba32) noexcept { return blGradientAddStopRgba32(this, offset, rgba32.value); } |
493 | BL_INLINE BLResult addStop(double offset, const BLRgba64& rgba64) noexcept { return blGradientAddStopRgba64(this, offset, rgba64.value); } |
494 | BL_INLINE BLResult removeStop(size_t index) noexcept { return blGradientRemoveStop(this, index); } |
495 | BL_INLINE BLResult removeStopByOffset(double offset, bool all = true) noexcept { return blGradientRemoveStopByOffset(this, offset, all); } |
496 | BL_INLINE BLResult removeStops(const BLRange& range) noexcept { return blGradientRemoveStops(this, range.start, range.end); } |
497 | BL_INLINE BLResult removeStopsByOffset(double offsetMin, double offsetMax) noexcept { return blGradientRemoveStopsFromTo(this, offsetMin, offsetMax); } |
498 | BL_INLINE BLResult replaceStop(size_t index, double offset, const BLRgba32& rgba32) noexcept { return blGradientReplaceStopRgba32(this, index, offset, rgba32.value); } |
499 | BL_INLINE BLResult replaceStop(size_t index, double offset, const BLRgba64& rgba64) noexcept { return blGradientReplaceStopRgba64(this, index, offset, rgba64.value); } |
500 | BL_INLINE size_t indexOfStop(double offset) const noexcept { return blGradientIndexOfStop(this, offset) ;} |
501 | |
502 | //! \} |
503 | |
504 | //! \name Transformations |
505 | //! \{ |
506 | |
507 | BL_INLINE bool hasMatrix() const noexcept { return impl->matrixType != BL_MATRIX2D_TYPE_IDENTITY; } |
508 | BL_INLINE uint32_t matrixType() const noexcept { return impl->matrixType; } |
509 | BL_INLINE const BLMatrix2D& matrix() const noexcept { return impl->matrix; } |
510 | |
511 | //! Applies a matrix operation to the current transformation matrix (internal). |
512 | BL_INLINE BLResult _applyMatrixOp(uint32_t opType, const void* opData) noexcept { |
513 | return blGradientApplyMatrixOp(this, opType, opData); |
514 | } |
515 | |
516 | //! \cond INTERNAL |
517 | //! Applies a matrix operation to the current transformation matrix (internal). |
518 | template<typename... Args> |
519 | BL_INLINE BLResult _applyMatrixOpV(uint32_t opType, Args&&... args) noexcept { |
520 | double opData[] = { double(args)... }; |
521 | return blGradientApplyMatrixOp(this, opType, opData); |
522 | } |
523 | //! \endcond |
524 | |
525 | BL_INLINE BLResult setMatrix(const BLMatrix2D& m) noexcept { return _applyMatrixOp(BL_MATRIX2D_OP_ASSIGN, &m); } |
526 | BL_INLINE BLResult resetMatrix() noexcept { return _applyMatrixOp(BL_MATRIX2D_OP_RESET, nullptr); } |
527 | |
528 | BL_INLINE BLResult translate(double x, double y) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_TRANSLATE, x, y); } |
529 | BL_INLINE BLResult translate(const BLPointI& p) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_TRANSLATE, p.x, p.y); } |
530 | BL_INLINE BLResult translate(const BLPoint& p) noexcept { return _applyMatrixOp(BL_MATRIX2D_OP_TRANSLATE, &p); } |
531 | BL_INLINE BLResult scale(double xy) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_SCALE, xy, xy); } |
532 | BL_INLINE BLResult scale(double x, double y) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_SCALE, x, y); } |
533 | BL_INLINE BLResult scale(const BLPointI& p) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_SCALE, p.x, p.y); } |
534 | BL_INLINE BLResult scale(const BLPoint& p) noexcept { return _applyMatrixOp(BL_MATRIX2D_OP_SCALE, &p); } |
535 | BL_INLINE BLResult skew(double x, double y) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_SKEW, x, y); } |
536 | BL_INLINE BLResult skew(const BLPoint& p) noexcept { return _applyMatrixOp(BL_MATRIX2D_OP_SKEW, &p); } |
537 | BL_INLINE BLResult rotate(double angle) noexcept { return _applyMatrixOp(BL_MATRIX2D_OP_ROTATE, &angle); } |
538 | BL_INLINE BLResult rotate(double angle, double x, double y) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_ROTATE_PT, angle, x, y); } |
539 | BL_INLINE BLResult rotate(double angle, const BLPoint& p) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_ROTATE_PT, angle, p.x, p.y); } |
540 | BL_INLINE BLResult rotate(double angle, const BLPointI& p) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_ROTATE_PT, angle, p.x, p.y); } |
541 | BL_INLINE BLResult transform(const BLMatrix2D& m) noexcept { return _applyMatrixOp(BL_MATRIX2D_OP_TRANSFORM, &m); } |
542 | |
543 | BL_INLINE BLResult postTranslate(double x, double y) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_POST_TRANSLATE, x, y); } |
544 | BL_INLINE BLResult postTranslate(const BLPointI& p) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_POST_TRANSLATE, p.x, p.y); } |
545 | BL_INLINE BLResult postTranslate(const BLPoint& p) noexcept { return _applyMatrixOp(BL_MATRIX2D_OP_POST_TRANSLATE, &p); } |
546 | BL_INLINE BLResult postScale(double xy) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_POST_SCALE, xy, xy); } |
547 | BL_INLINE BLResult postScale(double x, double y) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_POST_SCALE, x, y); } |
548 | BL_INLINE BLResult postScale(const BLPointI& p) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_POST_SCALE, p.x, p.y); } |
549 | BL_INLINE BLResult postScale(const BLPoint& p) noexcept { return _applyMatrixOp(BL_MATRIX2D_OP_POST_SCALE, &p); } |
550 | BL_INLINE BLResult postSkew(double x, double y) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_POST_SKEW, x, y); } |
551 | BL_INLINE BLResult postSkew(const BLPoint& p) noexcept { return _applyMatrixOp(BL_MATRIX2D_OP_POST_SKEW, &p); } |
552 | BL_INLINE BLResult postRotate(double angle) noexcept { return _applyMatrixOp(BL_MATRIX2D_OP_POST_ROTATE, &angle); } |
553 | BL_INLINE BLResult postRotate(double angle, double x, double y) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_POST_ROTATE_PT, angle, x, y); } |
554 | BL_INLINE BLResult postRotate(double angle, const BLPoint& p) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_POST_ROTATE_PT, angle, p.x, p.y); } |
555 | BL_INLINE BLResult postRotate(double angle, const BLPointI& p) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_POST_ROTATE_PT, angle, p.x, p.y); } |
556 | BL_INLINE BLResult postTransform(const BLMatrix2D& m) noexcept { return _applyMatrixOp(BL_MATRIX2D_OP_POST_TRANSFORM, &m); } |
557 | |
558 | //! \} |
559 | |
560 | static BL_INLINE const BLGradient& none() noexcept { return reinterpret_cast<const BLGradient*>(blNone)[kImplType]; } |
561 | }; |
562 | #endif |
563 | |
564 | //! \} |
565 | |
566 | BL_DIAGNOSTIC_POP |
567 | |
568 | #endif // BLEND2D_BLGRADIENT_H |
569 | |