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_BLREGION_H |
8 | #define BLEND2D_BLREGION_H |
9 | |
10 | #include "./blarray.h" |
11 | #include "./blgeometry.h" |
12 | #include "./blvariant.h" |
13 | |
14 | //! \addtogroup blend2d_api_geometry |
15 | //! \{ |
16 | |
17 | // ============================================================================ |
18 | // [Constants] |
19 | // ============================================================================ |
20 | |
21 | //! Region type. |
22 | BL_DEFINE_ENUM(BLRegionType) { |
23 | //! Region is empty (has no rectangles). |
24 | BL_REGION_TYPE_EMPTY = 0, |
25 | //! Region has one rectangle (rectangular). |
26 | BL_REGION_TYPE_RECT = 1, |
27 | //! Region has more YX sorted rectangles. |
28 | BL_REGION_TYPE_COMPLEX = 2, |
29 | //! Count of region types. |
30 | BL_REGION_TYPE_COUNT = 3 |
31 | }; |
32 | |
33 | // ============================================================================ |
34 | // [BLRegion - Core] |
35 | // ============================================================================ |
36 | |
37 | //! 2D region [C Interface - Impl]. |
38 | struct BLRegionImpl { |
39 | //! Union of either raw `data` & `size` members or their `view`. |
40 | union { |
41 | struct { |
42 | //! Region data (Y/X sorted rectangles). |
43 | BLBoxI* data; |
44 | //! Region size (count of rectangles in the region). |
45 | size_t size; |
46 | }; |
47 | //! Region data and size as `BLRegionView`. |
48 | BLRegionView view; |
49 | }; |
50 | |
51 | //! Region capacity (rectangles). |
52 | size_t capacity; |
53 | |
54 | //! Reference count. |
55 | volatile size_t refCount; |
56 | //! Impl type. |
57 | uint8_t implType; |
58 | //! Impl traits. |
59 | uint8_t implTraits; |
60 | //! Memory pool data. |
61 | uint16_t memPoolData; |
62 | |
63 | //! Reserved, must be zero. |
64 | uint8_t reserved[4]; |
65 | //! Bounding box, empty regions have [0, 0, 0, 0]. |
66 | BLBoxI boundingBox; |
67 | }; |
68 | |
69 | //! 2D region [C Interface - Core]. |
70 | struct BLRegionCore { |
71 | BLRegionImpl* impl; |
72 | }; |
73 | |
74 | // ============================================================================ |
75 | // [BLRegion - C++] |
76 | // ============================================================================ |
77 | |
78 | #ifdef __cplusplus |
79 | //! 2D region [C++ API]. |
80 | //! |
81 | //! Region is a set of rectangles sorted and coalesced by their Y/X coordinates. |
82 | class BLRegion : public BLRegionCore { |
83 | public: |
84 | //! \cond INTERNAL |
85 | static constexpr const uint32_t kImplType = BL_IMPL_TYPE_REGION; |
86 | //! \endcond |
87 | |
88 | //! \name Construction & Destruction |
89 | //! \{ |
90 | |
91 | BL_INLINE BLRegion() noexcept { this->impl = none().impl; } |
92 | BL_INLINE BLRegion(BLRegion&& other) noexcept { blVariantInitMove(this, &other); } |
93 | BL_INLINE BLRegion(const BLRegion& other) noexcept { blVariantInitWeak(this, &other); } |
94 | BL_INLINE explicit BLRegion(BLRegionImpl* impl) noexcept { this->impl = impl; } |
95 | |
96 | BL_INLINE ~BLRegion() noexcept { blRegionReset(this); } |
97 | |
98 | //! \} |
99 | |
100 | //! \name Overloaded Operators |
101 | //! \{ |
102 | |
103 | BL_INLINE explicit operator bool() const noexcept { return impl->size != 0; } |
104 | |
105 | BL_INLINE BLRegion& operator=(BLRegion&& other) noexcept { blRegionAssignMove(this, &other); return *this; } |
106 | BL_INLINE BLRegion& operator=(const BLRegion& other) noexcept { blRegionAssignWeak(this, &other); return *this; } |
107 | |
108 | BL_INLINE bool operator==(const BLRegion& other) const noexcept { return equals(other); } |
109 | BL_INLINE bool operator!=(const BLRegion& other) const noexcept { return !equals(other); } |
110 | |
111 | //! \} |
112 | |
113 | //! \name Common Functionality |
114 | //! \{ |
115 | |
116 | BL_INLINE BLResult reset() noexcept { return blRegionReset(this); } |
117 | BL_INLINE void swap(BLRegion& other) noexcept { std::swap(this->impl, other.impl); } |
118 | |
119 | BL_INLINE BLResult assign(BLRegion&& other) noexcept { return blRegionAssignMove(this, &other); } |
120 | BL_INLINE BLResult assign(const BLRegion& other) noexcept { return blRegionAssignWeak(this, &other); } |
121 | BL_INLINE BLResult assignDeep(const BLRegion& other) noexcept { return blRegionAssignDeep(this, &other); } |
122 | |
123 | BL_INLINE BLResult assign(const BLBoxI& box) noexcept { return blRegionAssignBoxI(this, &box); } |
124 | BL_INLINE BLResult assign(const BLBoxI* data, size_t n) noexcept { return blRegionAssignBoxIArray(this, data, n); } |
125 | BL_INLINE BLResult assign(const BLRectI& rect) noexcept { return blRegionAssignRectI(this, &rect); } |
126 | BL_INLINE BLResult assign(const BLRectI* data, size_t n) noexcept { return blRegionAssignRectIArray(this, data, n); } |
127 | |
128 | //! Tests whether the region is a built-in null instance. |
129 | BL_INLINE bool isNone() const noexcept { return (impl->implTraits & BL_IMPL_TRAIT_NULL) != 0; } |
130 | //! Tests whether the region is empty. |
131 | BL_INLINE bool empty() const noexcept { return impl->size == 0; } |
132 | |
133 | //! Tests whether this region and `other` are equal. |
134 | BL_INLINE bool equals(const BLRegion& other) const noexcept { return blRegionEquals(this, &other); } |
135 | |
136 | //! \} |
137 | |
138 | //! \name Region Content |
139 | //! \{ |
140 | |
141 | //! Returns the type of the region, see `BLRegionType`. |
142 | //! |
143 | //! This inline method has also a C API equivalent `blRegionGetType()`. |
144 | BL_INLINE uint32_t type() const noexcept { return uint32_t(blMin<size_t>(impl->size, BL_REGION_TYPE_COMPLEX)); } |
145 | |
146 | //! Tests whether the region is one rectangle. |
147 | BL_INLINE bool isRect() const noexcept { return impl->size == 1; } |
148 | //! Tests whether the region is complex. |
149 | BL_INLINE bool isComplex() const noexcept { return impl->size > 1; } |
150 | |
151 | //! Returns the region size. |
152 | BL_INLINE size_t size() const noexcept { return impl->size; } |
153 | //! Returns the region capacity. |
154 | BL_INLINE size_t capacity() const noexcept { return impl->capacity; } |
155 | //! Returns a const pointer to the region data. |
156 | BL_INLINE const BLBoxI* data() const noexcept { return impl->data; } |
157 | //! Returns the region's bounding box. |
158 | BL_INLINE const BLBoxI& boundingBox() const noexcept { return impl->boundingBox; } |
159 | |
160 | //! Returns the region data as `BLRegionView`. |
161 | BL_INLINE const BLRegionView& view() const noexcept { return impl->view; } |
162 | |
163 | //! \} |
164 | |
165 | //! \name Region Operations |
166 | //! \{ |
167 | |
168 | BL_INLINE BLResult clear() noexcept { return blRegionClear(this); } |
169 | |
170 | //! Reserves at least `n` boxes in this region. |
171 | BL_INLINE BLResult reserve(size_t n) noexcept { return blRegionReserve(this, n); } |
172 | //! Shrinks the region data so it consumes only memory it requires. |
173 | BL_INLINE BLResult shrink() noexcept { return blRegionShrink(this); } |
174 | |
175 | BL_INLINE BLResult combine(const BLRegion& region, uint32_t op) noexcept { return blRegionCombine(this, this, ®ion, op); } |
176 | BL_INLINE BLResult combine(const BLBoxI& box, uint32_t op) noexcept { return blRegionCombineRB(this, this, &box, op); } |
177 | |
178 | //! Translates the region by the given point `pt`. |
179 | //! |
180 | //! Possible overflow will be handled by clipping to a maximum region boundary, |
181 | //! so the final region could be smaller than the region before translation. |
182 | BL_INLINE BLResult translate(const BLPointI& pt) noexcept { return blRegionTranslate(this, this, &pt); } |
183 | //! Translates the region by the given point `pt` and clip it to the given `clipBox`. |
184 | BL_INLINE BLResult translateAndClip(const BLPointI& pt, const BLBoxI& clipBox) noexcept { return blRegionTranslateAndClip(this, this, &pt, &clipBox); } |
185 | //! Translates the region with `r` and clip it to the given `clipBox`. |
186 | BL_INLINE BLResult intersectAndClip(const BLRegion& r, const BLBoxI& clipBox) noexcept { return blRegionIntersectAndClip(this, this, &r, &clipBox); } |
187 | |
188 | //! \} |
189 | |
190 | //! \name Hit Testing |
191 | //! \{ |
192 | |
193 | //! Tests if a given point `pt` is in region, returns `BLHitTest`. |
194 | BL_INLINE uint32_t hitTest(const BLPointI& pt) const noexcept { return blRegionHitTest(this, &pt); } |
195 | //! Tests if a given `box` is in region, returns `BLHitTest`. |
196 | BL_INLINE uint32_t hitTest(const BLBoxI& box) const noexcept { return blRegionHitTestBoxI(this, &box); } |
197 | |
198 | //! \} |
199 | |
200 | static BL_INLINE const BLRegion& none() noexcept { return reinterpret_cast<const BLRegion*>(blNone)[kImplType]; } |
201 | |
202 | static BL_INLINE BLResult combine(BLRegion& dst, const BLRegion& a, const BLRegion& b, uint32_t op) noexcept { return blRegionCombine(&dst, &a, &b, op); } |
203 | static BL_INLINE BLResult combine(BLRegion& dst, const BLRegion& a, const BLBoxI& b, uint32_t op) noexcept { return blRegionCombineRB(&dst, &a, &b, op); } |
204 | static BL_INLINE BLResult combine(BLRegion& dst, const BLBoxI& a, const BLRegion& b, uint32_t op) noexcept { return blRegionCombineBR(&dst, &a, &b, op); } |
205 | static BL_INLINE BLResult combine(BLRegion& dst, const BLBoxI& a, const BLBoxI& b, uint32_t op) noexcept { return blRegionCombineBB(&dst, &a, &b, op); } |
206 | |
207 | static BL_INLINE BLResult translate(BLRegion& dst, const BLRegion& r, const BLPointI& pt) noexcept { return blRegionTranslate(&dst, &r, &pt); } |
208 | static BL_INLINE BLResult translateAndClip(BLRegion& dst, const BLRegion& r, const BLPointI& pt, const BLBoxI& clipBox) noexcept { return blRegionTranslateAndClip(&dst, &r, &pt, &clipBox); } |
209 | static BL_INLINE BLResult intersectAndClip(BLRegion& dst, const BLRegion& a, const BLRegion& b, const BLBoxI& clipBox) noexcept { return blRegionIntersectAndClip(&dst, &a, &b, &clipBox); } |
210 | }; |
211 | #endif |
212 | |
213 | //! \} |
214 | |
215 | #endif // BLEND2D_BLREGION_H |
216 | |