Get world scale more faster
[platform/core/uifw/dali-core.git] / dali / public-api / math / rect.h
1 #ifndef DALI_RECT_H
2 #define DALI_RECT_H
3
4 /*
5  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // EXTERNAL INCLUDES
22 #include <math.h>
23 #include <ostream>
24
25 // INTERNAL INCLUDES
26 #include <dali/public-api/math/math-utils.h>
27
28 namespace Dali
29 {
30 /**
31  * @addtogroup dali_core_math
32  * @{
33  */
34
35 /**
36  * @brief Template class to create and operate on rectangles.
37  * @SINCE_1_0.0
38  */
39 template<typename T = float>
40 struct Rect
41 {
42   // Methods
43
44   /**
45    * @brief Constructor.
46    * @SINCE_1_0.0
47    */
48   Rect()
49   : x(0),
50     y(0),
51     width(0),
52     height(0)
53   {
54   }
55
56   /**
57    * @brief Constructor.
58    *
59    * @SINCE_1_0.0
60    * @param[in] x      X coordinate (or left)
61    * @param[in] y      Y coordinate (or right)
62    * @param[in] width  Width (or bottom)
63    * @param[in] height Height (or top)
64    */
65   Rect(T x, T y, T width, T height)
66   : x(x),
67     y(y),
68     width(width),
69     height(height)
70   {
71   }
72
73   /**
74    * @brief Conversion constructor from Vector4.
75    *
76    * @SINCE_1_9.14
77    * @param[in] vec4 Vector4 to convert from
78    */
79   Rect(const Vector4& vec4)
80   : x(vec4.x),
81     y(vec4.y),
82     width(vec4.z),
83     height(vec4.w)
84   {
85   }
86
87   /**
88    * @brief Default copy constructor.
89    *
90    * @SINCE_1_9.27
91    * @param[in] rhs The original object
92    */
93   Rect(const Rect<T>& rhs) = default;
94
95   /**
96    * @brief Default copy assignment operator.
97    *
98    * @SINCE_1_9.27
99    * @param[in] rhs The original object
100    * @return Reference to this
101    */
102   Rect<T>& operator=(const Rect<T>& rhs) = default;
103
104   /**
105    * @brief Default move constructor.
106    *
107    * @SINCE_1_9.27
108    * @param[in] rhs The original object
109    */
110   Rect<T>(Rect<T>&& rhs) noexcept = default;
111
112   /**
113    * @brief Default move assignment operator.
114    *
115    * @SINCE_1_9.27
116    * @param[in] rhs The original object
117    * @return Reference to this
118    */
119   Rect<T>& operator=(Rect<T>&& rhs) noexcept = default;
120
121   /**
122    * @brief Assignment operator.
123    *
124    * @SINCE_1_9.14
125    * @param[in] vec4 The Vector4 to assign
126    * @return Reference to this
127    */
128   Rect<T>& operator=(const Vector4& vec4)
129   {
130     x      = vec4.x;
131     y      = vec4.y;
132     width  = vec4.z;
133     height = vec4.w;
134
135     return *this;
136   }
137
138   /**
139    * @brief Assignment from individual values.
140    *
141    * @SINCE_1_0.0
142    * @param[in] newX      X coordinate
143    * @param[in] newY      Y coordinate
144    * @param[in] newWidth  Width
145    * @param[in] newHeight Height
146    */
147   void Set(T newX, T newY, T newWidth, T newHeight)
148   {
149     x      = newX;
150     y      = newY;
151     width  = newWidth;
152     height = newHeight;
153   }
154
155   /**
156    * @brief Determines whether or not this Rectangle is empty.
157    *
158    * @SINCE_1_0.0
159    * @return True if width or height are zero
160    */
161   bool IsEmpty() const
162   {
163     return width == 0 ||
164            height == 0;
165   }
166
167   /**
168    * @brief Determines whether or not this Rectangle is valid.
169    *
170    * @SINCE_1_9.18
171    * @return True if width and height are not negative
172    */
173   bool IsValid() const
174   {
175     return !(width < 0 || height < 0);
176   }
177
178   /**
179    * @brief Gets the left of the rectangle.
180    *
181    * @SINCE_1_0.0
182    * @return The left edge of the rectangle
183    */
184   T Left() const
185   {
186     return x;
187   }
188   /**
189    * @brief Gets the right of the rectangle.
190    *
191    * @SINCE_1_0.0
192    * @return The right edge of the rectangle
193    */
194   T Right() const
195   {
196     return x + width;
197   }
198
199   /**
200    * @brief Gets the top of the rectangle.
201    *
202    * @SINCE_1_0.0
203    * @return The top of the rectangle
204    */
205   T Top() const
206   {
207     return y;
208   }
209
210   /**
211    * @brief Gets the bottom of the rectangle.
212    *
213    * @SINCE_1_0.0
214    * @return The bottom of the rectangle
215    */
216   T Bottom() const
217   {
218     return y + height;
219   }
220
221   /**
222    * @brief Gets the area of the rectangle.
223    *
224    * @SINCE_1_0.0
225    * @return The area of the rectangle
226    */
227   T Area() const
228   {
229     return width * height;
230   }
231
232   /**
233    * @brief Determines whether or not this rectangle and the specified rectangle intersect.
234    *
235    * @SINCE_1_0.0
236    * @param[in] other The other rectangle to test against this rectangle
237    * @return True if the rectangles intersect
238    */
239   bool Intersects(const Rect<T>& other) const
240   {
241     return (other.x + other.width) > x && other.x < (x + width) &&
242            (other.y + other.height) > y && other.y < (y + height);
243   }
244
245   /**
246    * @brief Intersects this rectangle and the specified rectangle.
247    * The result of the intersection is stored in this rectangle.
248    *
249    * @SINCE_1_9.18
250    * @param[in] rect The other rectangle to intersect with
251    * @return True if the rectangles intersect
252    */
253   bool Intersect(const Rect<T>& rect)
254   {
255     const int left   = std::max(rect.x, x);
256     const int top    = std::max(rect.y, y);
257     const int right  = std::min(rect.x + rect.width, x + width);
258     const int bottom = std::min(rect.y + rect.height, y + height);
259
260     const int width  = right - left;
261     const int height = bottom - top;
262     if(!(width < 0 || height < 0))
263     {
264       x            = left;
265       y            = top;
266       this->width  = width;
267       this->height = height;
268       return true;
269     }
270
271     return false;
272   }
273
274   /**
275    * @brief Merges this rectangle and the specified rectangle.
276    * The result of the merge is stored in this rectangle.
277    *
278    * @SINCE_1_9.18
279    * @param[in] rect The other rectangle to merge with
280    */
281   void Merge(const Rect<T>& rect)
282   {
283     const int left   = std::min(rect.x, x);
284     const int top    = std::min(rect.y, y);
285     const int right  = std::max(rect.x + rect.width, x + width);
286     const int bottom = std::max(rect.y + rect.height, y + height);
287     x                = left;
288     y                = top;
289     width            = right - left;
290     height           = bottom - top;
291   }
292
293   /**
294    * @brief Inset the rectangle by (dx,dy). If dx is positive, then the sides are moved inwards.
295    * If dx is negative, then the sides are moved outwards.
296    * The result of the inset is stored in this rectangle.
297    * @SINCE_1_9.18
298    */
299   void Inset(T dx, T dy)
300   {
301     const int left   = x - dx;
302     const int top    = y - dy;
303     const int right  = x + width + dx;
304     const int bottom = y + height + dy;
305     x                = left;
306     y                = top;
307     width            = right - left;
308     height           = bottom - top;
309   }
310
311   /**
312    * @brief Determines whether or not this Rectangle contains the specified rectangle.
313    *
314    * @SINCE_1_0.0
315    * @param[in] other The other rectangle to test against this rectangle
316    * @return True if the specified rectangle is contained
317    */
318   bool Contains(const Rect<T>& other) const
319   {
320     return other.x >= x && (other.x + other.width) <= (x + width) &&
321            other.y >= y && (other.y + other.height) <= (y + height);
322   }
323
324 public: // Data
325   union
326   {
327     T x;    ///< X position of the rectangle
328     T left; ///< The left value
329   };
330
331   union
332   {
333     T y;     ///< Y position of the rectangle
334     T right; ///< The right value
335   };
336
337   union
338   {
339     T width;  ///< width of the rectangle
340     T bottom; ///< The bottom value
341   };
342
343   union
344   {
345     T height; ///< height of the rectangle
346     T top;    ///< The top value
347   };
348 };
349
350 /**
351  * @brief Equality operator.
352  *
353  * @SINCE_1_0.0
354  * @param[in] lhs First operand
355  * @param[in] rhs Second operand
356  * @return True if boxes are exactly same
357  */
358 template<typename T>
359 inline bool operator==(const Rect<T>& lhs, const Rect<T>& rhs)
360 {
361   return (lhs.x == rhs.x) &&
362          (lhs.y == rhs.y) &&
363          (lhs.width == rhs.width) &&
364          (lhs.height == rhs.height);
365 }
366
367 /**
368  * @brief Inequality operator.
369  *
370  * @SINCE_1_0.0
371  * @param[in] lhs The first rectangle
372  * @param[in] rhs The second rectangle
373  * @return True if rectangles are not identical
374  */
375 template<typename T>
376 inline bool operator!=(const Rect<T>& lhs, const Rect<T>& rhs)
377 {
378   return !(lhs == rhs);
379 }
380
381 /**
382  * @brief Equality operator specialization for float.
383  *
384  * @SINCE_1_0.0
385  * @param[in] lhs The first rectangle
386  * @param[in] rhs The second rectangle
387  * @return True if rectangles are exactly same
388  */
389 template<>
390 inline bool operator==(const Rect<float>& lhs, const Rect<float>& rhs)
391 {
392   return (fabsf(lhs.x - rhs.x) < GetRangedEpsilon(lhs.x, rhs.x)) &&
393          (fabsf(lhs.y - rhs.y) < GetRangedEpsilon(lhs.y, rhs.y)) &&
394          (fabsf(lhs.width - rhs.width) < GetRangedEpsilon(lhs.width, rhs.width)) &&
395          (fabsf(lhs.height - rhs.height) < GetRangedEpsilon(lhs.height, rhs.height));
396 }
397
398 /**
399  * @brief IsEmpty specialization for float.
400  *
401  * @SINCE_1_0.0
402  * @return True if the rectangle has zero size
403  */
404 template<>
405 inline bool Rect<float>::IsEmpty() const
406 {
407   return (fabsf(width) <= GetRangedEpsilon(width, width) ||
408           fabsf(height) <= GetRangedEpsilon(height, height));
409 }
410
411 /**
412  * @brief Converts the value of the rectangle into a string and insert in to an output stream.
413  *
414  * @SINCE_1_0.0
415  * @param[in] stream The output stream operator
416  * @param[in] rectangle the rectangle to output
417  * @return The output stream operator
418  */
419 template<typename T>
420 inline std::ostream& operator<<(std::ostream& stream, const Rect<T>& rectangle)
421 {
422   return stream << "[" << rectangle.x << ", " << rectangle.y << ", " << rectangle.width << ", " << rectangle.height << "]";
423 }
424
425 /**
426  * @}
427  */
428 } // namespace Dali
429
430 #endif // DALI_RECT_H