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.
22BL_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].
38struct 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].
70struct 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.
82class BLRegion : public BLRegionCore {
83public:
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, &region, 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