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