Line data Source code
1 : /**
2 : Copyright (c) 2010-2012 cocos2d-x.org
3 : Copyright (c) 2013-2014 Chukong Technologies
4 : Copyright (c) 2017-2022 Roman Katuntsev <sbkarr@stappler.org>
5 : Copyright (c) 2023-2024 Stappler LLC <admin@stappler.dev>
6 :
7 : Permission is hereby granted, free of charge, to any person obtaining a copy
8 : of this software and associated documentation files (the "Software"), to deal
9 : in the Software without restriction, including without limitation the rights
10 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 : copies of the Software, and to permit persons to whom the Software is
12 : furnished to do so, subject to the following conditions:
13 :
14 : The above copyright notice and this permission notice shall be included in
15 : all copies or substantial portions of the Software.
16 :
17 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 : THE SOFTWARE.
24 : **/
25 :
26 : #ifndef CORE_GEOM_SPGEOMETRY_H_
27 : #define CORE_GEOM_SPGEOMETRY_H_
28 :
29 : #include "SPVec2.h"
30 : #include "SPVec3.h"
31 :
32 : namespace STAPPLER_VERSIONIZED stappler::geom {
33 :
34 : struct Metric {
35 : enum Units : uint8_t {
36 : Percent,
37 : Px,
38 : Em,
39 : Rem,
40 : Auto,
41 : Dpi,
42 : Dppx,
43 : Contain, // only for background-size
44 : Cover, // only for background-size
45 : Vw,
46 : Vh,
47 : VMin,
48 : VMax
49 : };
50 :
51 : inline bool isAuto() const { return metric == Units::Auto; }
52 :
53 : inline bool isFixed() const {
54 : switch (metric) {
55 : case Units::Px:
56 : case Units::Em:
57 : case Units::Rem:
58 : case Units::Vw:
59 : case Units::Vh:
60 : case Units::VMin:
61 : case Units::VMax:
62 : return true;
63 : break;
64 : default:
65 : break;
66 : }
67 : return false;
68 : }
69 :
70 : float value = 0.0f;
71 : Units metric = Units::Auto;
72 :
73 : Metric(float v, Units m) : value(v), metric(m) { }
74 :
75 : Metric() = default;
76 :
77 : bool readStyleValue(StringView r, bool resolutionMetric, bool allowEmptyMetric);
78 :
79 : inline bool operator == (const Metric &other) const = default;
80 : inline bool operator != (const Metric &other) const = default;
81 : };
82 :
83 : struct Size2 {
84 : static const Size2 ZERO;
85 :
86 : float width = 0.0f;
87 : float height = 0.0f;
88 :
89 146463 : constexpr Size2() = default;
90 3113213 : constexpr Size2(float w, float h) : width(w), height(h) { }
91 :
92 : template <typename Functor>
93 : constexpr Size2(const Size2 &v, const Functor &f) : width(f(v.width)), height(f(v.height)) { }
94 :
95 : constexpr Size2(const Size2 &other) = default;
96 : constexpr explicit Size2(const Vec2 &point) : width(point.x), height(point.y) { }
97 :
98 4274 : constexpr operator Vec2() const { return Vec2(width, height); }
99 :
100 : constexpr Size2& operator= (const Size2 &other) = default;
101 : constexpr Size2& operator= (const Vec2 &point) {
102 : this->width = point.x; this->height = point.y;
103 : return *this;
104 : }
105 :
106 138 : constexpr Size2 operator+(const Size2 &right) const {
107 138 : return Size2(this->width + right.width, this->height + right.height);
108 : }
109 10 : constexpr Size2 operator-(const Size2 &right) const {
110 10 : return Size2(this->width - right.width, this->height - right.height);
111 : }
112 252 : constexpr Size2 operator*(float a) const {
113 252 : return Size2(this->width * a, this->height * a);
114 : }
115 4348 : constexpr Size2 operator/(float a) const {
116 4348 : return Size2(this->width / a, this->height / a);
117 : }
118 :
119 : constexpr void setSize(float w, float h) { }
120 :
121 : constexpr bool fuzzyEquals(const Size2 &target, float var = NumericLimits<float>::epsilon()) const {
122 : return (std::fabs(this->width - target.width) < var)
123 : && (std::fabs(this->height - target.height) < var);
124 : }
125 :
126 : SP_THREE_WAY_COMPARISON_FRIEND_CONSTEXPR(Size2)
127 : };
128 :
129 :
130 : struct Size3 {
131 : static const Size3 ZERO;
132 :
133 : float width = 0.0f;
134 : float height = 0.0f;
135 : float depth = 0.0f;
136 :
137 : constexpr Size3() = default;
138 25 : constexpr Size3(float w, float h, float d) : width(w), height(h), depth(d) { }
139 :
140 : template <typename Functor>
141 : constexpr Size3(const Size3 &v, const Functor &f) : width(f(v.width)), height(f(v.height)), depth(f(v.depth)) { }
142 :
143 : constexpr Size3(const Size3& other) = default;
144 : constexpr explicit Size3(const Vec3& point) : width(point.x), height(point.y), depth(point.z) { }
145 :
146 : constexpr operator Vec3() const { return Vec3(width, height, depth); }
147 :
148 : constexpr Size3& operator= (const Size3& other) = default;
149 : constexpr Size3& operator= (const Vec3& point) {
150 : width = point.x;
151 : height = point.y;
152 : depth = point.z;
153 : return *this;
154 : }
155 :
156 : constexpr Size3 operator+(const Size3& right) const {
157 : Size3 ret(*this);
158 : ret.width += right.width;
159 : ret.height += right.height;
160 : ret.depth += right.depth;
161 : return ret;
162 : }
163 : constexpr Size3 operator-(const Size3& right) const {
164 : Size3 ret(*this);
165 : ret.width -= right.width;
166 : ret.height -= right.height;
167 : ret.depth -= right.depth;
168 : return ret;
169 : }
170 : constexpr Size3 operator*(float a) const {
171 : Size3 ret(*this);
172 : ret.width *= a;
173 : ret.height *= a;
174 : ret.depth *= a;
175 : return ret;
176 : }
177 : constexpr Size3 operator/(float a) const {
178 : Size3 ret(*this);
179 : ret.width /= a;
180 : ret.height /= a;
181 : ret.depth /= a;
182 : return ret;
183 : }
184 :
185 : constexpr bool fuzzyEquals(const Size3 &target, float var = NumericLimits<float>::epsilon()) const {
186 : return (std::fabs(this->width - target.width) < var)
187 : && (std::fabs(this->height - target.height) < var)
188 : && (std::fabs(this->depth - target.depth) < var);
189 : }
190 :
191 : SP_THREE_WAY_COMPARISON_FRIEND_CONSTEXPR(Size3)
192 : };
193 :
194 :
195 : struct Extent2 {
196 : static const Extent2 ZERO;
197 :
198 : uint32_t width = 0;
199 : uint32_t height = 0;
200 :
201 2731 : constexpr Extent2() = default;
202 30960 : constexpr Extent2(uint32_t w, uint32_t h) : width(w), height(h) { }
203 :
204 : constexpr Extent2(const Extent2 &other) = default;
205 : constexpr Extent2& operator= (const Extent2 &other) = default;
206 :
207 : constexpr explicit Extent2(const Size2 &size) : width(size.width), height(size.height) { }
208 : constexpr explicit Extent2(const Vec2 &point) : width(point.x), height(point.y) { }
209 :
210 : constexpr Extent2& operator= (const Size2 &size) { width = size.width; height = size.width; return *this; }
211 : constexpr Extent2& operator= (const Vec2 &other) { width = other.x; height = other.y; return *this; }
212 :
213 : SP_THREE_WAY_COMPARISON_TYPE_CONSTEXPR(Extent2)
214 :
215 : constexpr operator Size2 () const { return Size2(width, height); }
216 : };
217 :
218 :
219 : struct Extent3 {
220 : static const Extent3 ZERO;
221 :
222 87992 : uint32_t width = 0;
223 87992 : uint32_t height = 0;
224 87992 : uint32_t depth = 0;
225 :
226 199861 : constexpr Extent3() = default;
227 1075823 : constexpr Extent3(uint32_t w, uint32_t h, uint32_t d) : width(w), height(h), depth(d) { }
228 7322 : constexpr Extent3(Extent2 e, uint32_t d) : width(e.width), height(e.height), depth(d) { }
229 :
230 : constexpr Extent3(const Extent3& other) = default;
231 : constexpr Extent3& operator= (const Extent3& other) = default;
232 :
233 : constexpr Extent3(const Extent2& other) : width(other.width), height(other.height), depth(1) { }
234 9822 : constexpr Extent3& operator= (const Extent2& other) { width = other.width; height = other.height; depth = 1; return *this; }
235 :
236 : constexpr explicit Extent3(const Size3 &size) : width(size.width), height(size.height), depth(size.depth) { }
237 : constexpr explicit Extent3(const Vec3 &point) : width(point.x), height(point.y), depth(point.z) { }
238 :
239 : constexpr Extent3& operator= (const Size3 &size) { width = size.width; height = size.width; depth = size.depth; return *this; }
240 : constexpr Extent3& operator= (const Vec3 &other) { width = other.x; height = other.y; depth = other.z; return *this; }
241 :
242 : #if SP_HAVE_THREE_WAY_COMPARISON
243 87992 : SP_THREE_WAY_COMPARISON_TYPE(Extent3)
244 : #else
245 : constexpr bool operator==(const Extent3 &other) const {
246 : return width == other.width
247 : && height == other.height
248 : && depth == other.depth
249 : ;
250 : }
251 : constexpr bool operator!=(const Extent3 &other) const {
252 : return width != other.width
253 : || height != other.height
254 : || depth != other.depth
255 : ;
256 : }
257 : constexpr bool operator<(const Extent3 &other) const {
258 : if (width < other.width) { return true; } else if (width > other.width) { return false; }
259 : if (height < other.height) { return true; } else if (height > other.height) { return false; }
260 : if (depth < other.depth) { return true; } else if (depth > other.depth) { return false; }
261 : return false;
262 : }
263 : constexpr bool operator>(const Extent3 &other) const {
264 : if (width < other.width) { return false; } else if (width > other.width) { return true; }
265 : if (height < other.height) { return false; } else if (height > other.height) { return true; }
266 : if (depth < other.depth) { return false; } else if (depth > other.depth) { return true; }
267 : return false;
268 : }
269 : constexpr bool operator<=(const Extent3 &other) const {
270 : if (width < other.width) { return true; } else if (width > other.width) { return false; }
271 : if (height < other.height) { return true; } else if (height > other.height) { return false; }
272 : if (depth < other.depth) { return true; } else if (depth > other.depth) { return false; }
273 : return true;
274 : }
275 : constexpr bool operator>=(const Extent3 &other) const {
276 : if (width < other.width) { return false; } else if (width > other.width) { return true; }
277 : if (height < other.height) { return false; } else if (height > other.height) { return true; }
278 : if (depth < other.depth) { return false; } else if (depth > other.depth) { return true; }
279 : return true;
280 : }
281 : #endif
282 :
283 : constexpr operator Size3 () const { return Size3(width, height, depth); }
284 : };
285 :
286 :
287 : struct Rect {
288 : static const Rect ZERO;
289 :
290 : Vec2 origin;
291 : Size2 size;
292 :
293 548856 : constexpr Rect() = default;
294 778482 : constexpr Rect(float x, float y, float width, float height) : origin(x, y), size(width, height) { }
295 508 : constexpr Rect(const Vec2 &o, const Size2 &s) : origin(o), size(s) { }
296 :
297 : template <typename Functor>
298 : constexpr Rect(const Rect &v, const Functor &f) : origin(Vec2(v.origin, f)), size(Size2(v.size, f)) { }
299 :
300 : constexpr Rect(const Rect& other) = default;
301 :
302 : constexpr Rect& operator= (const Rect& other) = default;
303 :
304 175 : constexpr float getMaxX() const { return origin.x + size.width; }
305 6114 : constexpr float getMidX() const { return origin.x + size.width / 2.0f; }
306 175 : constexpr float getMinX() const { return origin.x; }
307 150 : constexpr float getMaxY() const { return origin.y + size.height; }
308 6114 : constexpr float getMidY() const { return origin.y + size.height / 2.0f; }
309 150 : constexpr float getMinY() const { return origin.y; }
310 :
311 131 : constexpr bool equals(const Rect& rect) const {
312 131 : return (origin == rect.origin) && (size == rect.size);
313 : }
314 :
315 : bool containsPoint(const Vec2& point, float padding = 0.0f) const;
316 : bool intersectsRect(const Rect& rect) const;
317 : bool intersectsCircle(const Vec2& center, float radius) const;
318 :
319 : /** Get the min rect which can contain this and rect. */
320 : Rect unionWithRect(const Rect & rect) const;
321 :
322 : /** Compute the min rect which can contain this and rect, assign it to this. */
323 : void merge(const Rect& rect);
324 :
325 : SP_THREE_WAY_COMPARISON_FRIEND_CONSTEXPR(Rect)
326 : };
327 :
328 : struct UVec2 {
329 : uint32_t x;
330 : uint32_t y;
331 :
332 : SP_THREE_WAY_COMPARISON_TYPE_CONSTEXPR(UVec2)
333 : };
334 :
335 : struct UVec3 {
336 : uint32_t x;
337 : uint32_t y;
338 : uint32_t z;
339 :
340 : SP_THREE_WAY_COMPARISON_TYPE_CONSTEXPR(UVec3)
341 : };
342 :
343 : struct UVec4 {
344 : uint32_t x;
345 : uint32_t y;
346 : uint32_t z;
347 : uint32_t w;
348 :
349 : SP_THREE_WAY_COMPARISON_TYPE_CONSTEXPR(UVec4)
350 : };
351 :
352 : struct URect {
353 : uint32_t x = 0;
354 : uint32_t y = 0;
355 : uint32_t width = 0;
356 : uint32_t height = 0;
357 :
358 616747 : URect() = default;
359 2 : URect(const UVec2 &origin, const Extent2 &size)
360 2 : : x(origin.x), y(origin.y), width(size.width), height(size.height) { }
361 1272199 : URect(uint32_t x, uint32_t y, uint32_t w, uint32_t h)
362 1272199 : : x(x), y(y), width(w), height(h) { }
363 :
364 208814 : constexpr UVec2 origin() const { return UVec2{x, y}; }
365 :
366 300 : constexpr float getMaxX() const { return x + width; }
367 : constexpr float getMidX() const { return x + width / 2.0f; }
368 325 : constexpr float getMinX() const { return x; }
369 75 : constexpr float getMaxY() const { return y + height; }
370 : constexpr float getMidY() const { return y + height / 2.0f; }
371 75 : constexpr float getMinY() const { return y; }
372 :
373 : bool containsPoint(const UVec2 &point) const;
374 : bool intersectsRect(const URect &rect) const;
375 :
376 : SP_THREE_WAY_COMPARISON_TYPE_CONSTEXPR(URect)
377 : };
378 :
379 : #ifndef __LCC__
380 :
381 : constexpr Size2 Size2::ZERO(0.0f, 0.0f);
382 : constexpr Size3 Size3::ZERO = Size3(0.0f, 0.0f, 0.0f);
383 : constexpr Extent2 Extent2::ZERO = Extent2(0, 0);
384 : constexpr Extent3 Extent3::ZERO = Extent3(0, 0, 0);
385 : constexpr Rect Rect::ZERO = Rect(0.0f, 0.0f, 0.0f, 0.0f);
386 :
387 : #endif
388 :
389 : Rect TransformRect(const Rect& rect, const Mat4& transform);
390 :
391 : inline std::ostream & operator<<(std::ostream & stream, const Rect & obj) {
392 : stream << "Rect(x:" << obj.origin.x << " y:" << obj.origin.y
393 : << " width:" << obj.size.width << " height:" << obj.size.height << ");";
394 : return stream;
395 : }
396 :
397 : inline std::ostream & operator<<(std::ostream & stream, const URect & obj) {
398 : stream << "URect(x:" << obj.x << " y:" << obj.y
399 : << " width:" << obj.width << " height:" << obj.height << ");";
400 : return stream;
401 : }
402 :
403 21 : inline std::ostream & operator<<(std::ostream & stream, const Size2 & obj) {
404 21 : stream << "Size2(width:" << obj.width << " height:" << obj.height << ");";
405 21 : return stream;
406 : }
407 :
408 : inline std::ostream & operator<<(std::ostream & stream, const Size3 & obj) {
409 : stream << "Size3(width:" << obj.width << " height:" << obj.height << " depth:" << obj.depth << ");";
410 : return stream;
411 : }
412 :
413 : inline std::ostream & operator<<(std::ostream & stream, const Extent2 & obj) {
414 : stream << "Extent2(width:" << obj.width << " height:" << obj.height << ");";
415 : return stream;
416 : }
417 :
418 101 : inline std::ostream & operator<<(std::ostream & stream, const Extent3 & obj) {
419 101 : stream << "Extent3(width:" << obj.width << " height:" << obj.height << " depth:" << obj.depth << ");";
420 101 : return stream;
421 : }
422 :
423 : }
424 :
425 : #endif /* CORE_GEOM_SPGEOMETRY_H_ */
|