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_P_H
8#define BLEND2D_BLGRADIENT_P_H
9
10#include "./blapi-internal_p.h"
11#include "./blgradient.h"
12
13//! \cond INTERNAL
14//! \addtogroup blend2d_internal
15//! \{
16
17// ============================================================================
18// [BLGradient - LUT]
19// ============================================================================
20
21//! Lookup table that contains interpolated pixels of the gradient in either
22//! PRGB32 or PRGB64 format (no other format is ever used).
23struct BLGradientLUT {
24 //! Reference count.
25 volatile size_t refCount;
26 //! Table size - must be power of 2!
27 size_t size;
28
29 template<typename T = void>
30 BL_INLINE T* data() noexcept { return reinterpret_cast<T*>(this + 1); }
31
32 template<typename T = void>
33 const BL_INLINE T* data() const noexcept { return reinterpret_cast<const T*>(this + 1); }
34
35 BL_INLINE BLGradientLUT* incRef() noexcept {
36 blAtomicFetchAdd(&refCount);
37 return this;
38 }
39
40 BL_INLINE bool decRefAndTest() noexcept {
41 return blAtomicFetchSub(&refCount) == 1;
42 }
43
44 BL_INLINE void release() noexcept {
45 if (decRefAndTest())
46 destroy(this);
47 }
48
49 static BL_INLINE BLGradientLUT* alloc(size_t size, uint32_t pixelSize) noexcept {
50 BLGradientLUT* self = static_cast<BLGradientLUT*>(
51 malloc(sizeof(BLGradientLUT) + size * pixelSize));
52
53 if (BL_UNLIKELY(!self))
54 return nullptr;
55
56 self->refCount = 1;
57 self->size = size;
58
59 return self;
60 }
61
62 static BL_INLINE void destroy(BLGradientLUT* self) noexcept {
63 free(self);
64 }
65};
66
67// ============================================================================
68// [BLGradient - Info]
69// ============================================================================
70
71//! Additional information maintained by `BLGradient` that is cached and is
72//! useful when deciding how to render the gradient and how big the LUT should
73//! be.
74struct BLGradientInfo {
75 union {
76 uint32_t packed;
77
78 struct {
79 //! True if the gradient is a solid color.
80 uint8_t solid;
81 //! Gradient format (either 32-bit or 64-bit).
82 uint8_t format;
83 //! Optimal LUT size.
84 uint16_t lutSize;
85 };
86 };
87
88 BL_INLINE bool empty() const noexcept { return this->packed == 0; }
89 BL_INLINE void reset() noexcept { this->packed = 0; }
90};
91
92// ============================================================================
93// [BLGradient - Internal]
94// ============================================================================
95
96//! Internal implementation that extends `BLGradientImpl` and adds LUT cache to it.
97struct BLInternalGradientImpl : public BLGradientImpl {
98 //! Gradient lookup table (32-bit).
99 BLGradientLUT* volatile lut32;
100 volatile BLGradientInfo info32;
101};
102
103template<>
104struct BLInternalCastImpl<BLGradientImpl> { typedef BLInternalGradientImpl Type; };
105
106BL_HIDDEN BLResult blGradientImplDelete(BLGradientImpl* impl) noexcept;
107
108BL_HIDDEN BLGradientInfo blGradientImplEnsureInfo32(BLGradientImpl* impl_) noexcept;
109BL_HIDDEN BLGradientLUT* blGradientImplEnsureLut32(BLGradientImpl* impl_) noexcept;
110
111// ============================================================================
112// [BLGradient - Ops]
113// ============================================================================
114
115struct BLGradientOps {
116 void (BL_CDECL* interpolate32)(uint32_t* dst, uint32_t dstSize, const BLGradientStop* stops, size_t stopCount) BL_NOEXCEPT;
117};
118BL_HIDDEN extern BLGradientOps blGradientOps;
119
120#ifdef BL_BUILD_OPT_SSE2
121BL_HIDDEN void BL_CDECL blGradientInterpolate32_SSE2(uint32_t* dPtr, uint32_t dSize, const BLGradientStop* sPtr, size_t sSize) noexcept;
122#endif
123
124#ifdef BL_BUILD_OPT_AVX2
125BL_HIDDEN void BL_CDECL blGradientInterpolate32_AVX2(uint32_t* dPtr, uint32_t dWidth, const BLGradientStop* sPtr, size_t sSize) noexcept;
126#endif
127
128//! \}
129//! \endcond
130
131#endif // BLEND2D_BLGRADIENT_P_H
132