1/*
2 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16/**
17 * @addtogroup UI_Utils
18 * @{
19 *
20 * @brief Defines basic UI utils.
21 *
22 * @since 1.0
23 * @version 1.0
24 */
25
26/**
27 * @file rect.h
28 *
29 * @brief Defines a rectangle, including the position data of the four boundaries of the rectangle, and provides
30 *        functions for rectangle inclusion, intersection, and aggregation.
31 * @since 1.0
32 * @version 1.0
33 */
34
35#ifndef GRAPHIC_LITE_RECT_H
36#define GRAPHIC_LITE_RECT_H
37
38#include "gfx_utils/graphic_math.h"
39#include "gfx_utils/graphic_types.h"
40#include "gfx_utils/heap_base.h"
41
42namespace OHOS {
43/**
44 * @brief Defines a rectangle, including the position data of the four boundaries of the rectangle, and provides
45 *        functions for rectangle inclusion, intersection, and aggregation.
46 * @since 1.0
47 * @version 1.0
48 */
49template <typename T> class CommonRect : public HeapBase {
50public:
51    /**
52     * @brief A constructor used to create a <b>CommonRect</b> instance.
53     * @since 1.0
54     * @version 1.0
55     */
56    CommonRect() : left_(0), top_(0), right_(0), bottom_(0) {}
57
58    /**
59     * @brief A destructor used to delete the <b>CommonRect</b> instance.
60     * @since 1.0
61     * @version 1.0
62     */
63    ~CommonRect() {}
64
65    /**
66     * @brief A constructor used to create a <b>CommonRect</b> instance based on the coordinates of the four boundaries.
67     * @param left Indicates the coordinate of the left boundary.
68     * @param top Indicates the coordinate of the top boundary.
69     * @param right Indicates the coordinate of the right boundary.
70     * @param bottom Indicates the coordinate of the bottom boundary.
71     * @since 1.0
72     * @version 1.0
73     */
74    CommonRect(T left, T top, T right, T bottom) : left_(left), top_(top), right_(right), bottom_(bottom) {}
75
76    /**
77     * @brief A constructor used to create a <b>CommonRect</b> instance by copying another rectangle.
78     *
79     * @param other Indicates the rectangle to copy.
80     * @since 1.0
81     * @version 1.0
82     */
83    CommonRect(const CommonRect<T>& other) = default;
84
85    /**
86     * @brief A constructor used to create a <b>CommonRect</b> instance by copying another rectangle.
87     *
88     * @param other Indicates the rectangle to copy.
89     * @since 1.0
90     * @version 1.0
91     */
92    CommonRect(CommonRect<T>&& other) = default;
93
94    /**
95     * @brief Sets the coordinates of the four boundaries of a rectangle.
96     *
97     * @param left Indicates the coordinate of the left boundary.
98     * @param top Indicates the coordinate of the top boundary.
99     * @param right Indicates the coordinate of the right boundary.
100     * @param bottom Indicates the coordinate of the bottom boundary.
101     * @since 1.0
102     * @version 1.0
103     */
104    void SetRect(T left, T top, T right, T bottom)
105    {
106        left_ = left;
107        right_ = right;
108        top_ = top;
109        bottom_ = bottom;
110    }
111
112    /**
113     * @brief Obtains the rectangle width.
114     * @return Returns the rectangle width.
115     * @since 1.0
116     * @version 1.0
117     */
118    T GetWidth() const
119    {
120        return right_ - left_ + 1;
121    }
122
123    /**
124     * @brief Obtains the rectangle height.
125     * @return Returns the rectangle height.
126     * @since 1.0
127     * @version 1.0
128     */
129    T GetHeight() const
130    {
131        return bottom_ - top_ + 1;
132    }
133
134    /**
135     * @brief Obtains the left boundary coordinate of the rectangle.
136     * @return Returns the left boundary coordinate.
137     * @since 1.0
138     * @version 1.0
139     */
140    T GetX() const
141    {
142        return left_;
143    }
144
145    /**
146     * @brief Obtains the top boundary coordinate of the rectangle.
147     * @return Returns the top boundary coordinate.
148     * @since 1.0
149     * @version 1.0
150     */
151    T GetY() const
152    {
153        return top_;
154    }
155
156    /**
157     * @brief Obtains the left boundary coordinate of the rectangle.
158     * @return Returns the left boundary coordinate.
159     * @since 1.0
160     * @version 1.0
161     */
162    T GetLeft() const
163    {
164        return left_;
165    }
166
167    /**
168     * @brief Obtains the top boundary coordinate of the rectangle.
169     * @return Returns the top boundary coordinate.
170     * @since 1.0
171     * @version 1.0
172     */
173    T GetTop() const
174    {
175        return top_;
176    }
177
178    /**
179     * @brief Obtains the right boundary coordinate of the rectangle.
180     * @return Returns the right boundary coordinate.
181     * @since 1.0
182     * @version 1.0
183     */
184    T GetRight() const
185    {
186        return right_;
187    }
188
189    /**
190     * @brief Obtains the bottom boundary coordinate of the rectangle.
191     * @return Returns the bottom boundary coordinate.
192     * @since 1.0
193     * @version 1.0
194     */
195    T GetBottom() const
196    {
197        return bottom_;
198    }
199
200    /**
201     * @brief Changes the left boundary coordinate of the rectangle without changing the rectangle width.
202     * @param x Indicates the coordinate of the left boundary.
203     * @since 1.0
204     * @version 1.0
205     */
206    void SetX(T x)
207    {
208        right_ += x - left_;
209        left_ = x;
210    }
211
212    /**
213     * @brief Changes the top boundary coordinate of the rectangle without changing the rectangle height.
214     * @param y Indicates the coordinate of the top boundary.
215     * @since 1.0
216     * @version 1.0
217     */
218    void SetY(T y)
219    {
220        bottom_ += y - top_;
221        top_ = y;
222    }
223
224    /**
225     * @brief Changes the coordinates of the left and top boundaries of the rectangle without changing the rectangle
226     *        width and height.
227     * @param x Indicates the coordinate of the left boundary.
228     * @param y Indicates the coordinate of the top boundary.
229     * @since 1.0
230     * @version 1.0
231     */
232    void SetPosition(T x, T y)
233    {
234        right_ += x - left_;
235        bottom_ += y - top_;
236        left_ = x;
237        top_ = y;
238    }
239
240    /**
241     * @brief Changes the width of the rectangle without changing the coordinate of the left boundary.
242     * @param width Indicates the width of the rectangle.
243     * @since 1.0
244     * @version 1.0
245     */
246    void SetWidth(T width)
247    {
248        right_ = left_ + width - 1;
249    }
250
251    /**
252     * @brief Changes the height of the rectangle without changing the coordinate of the top boundary.
253     * @param height Indicates the height of the rectangle.
254     * @since 1.0
255     * @version 1.0
256     */
257    void SetHeight(T height)
258    {
259        bottom_ = top_ + height - 1;
260    }
261
262    /**
263     * @brief Sets the coordinate of the left boundary of a rectangle.
264     * @param left Indicates the coordinate of the left boundary.
265     * @since 1.0
266     * @version 1.0
267     */
268    void SetLeft(T left)
269    {
270        left_ = left;
271    }
272
273    /**
274     * @brief Sets the coordinate of the top boundary of a rectangle.
275     * @param top Indicates the coordinate of the top boundary.
276     * @since 1.0
277     * @version 1.0
278     */
279    void SetTop(T top)
280    {
281        top_ = top;
282    }
283
284    /**
285     * @brief Sets the coordinate of the right boundary of a rectangle.
286     * @param right Indicates the coordinate of the right boundary.
287     * @since 1.0
288     * @version 1.0
289     */
290    void SetRight(T right)
291    {
292        right_ = right;
293    }
294
295    /**
296     * @brief Sets the coordinate of the bottom boundary of a rectangle.
297     * @param bottom Indicates the coordinate of the bottom boundary.
298     * @since 1.0
299     * @version 1.0
300     */
301    void SetBottom(T bottom)
302    {
303        bottom_ = bottom;
304    }
305
306    /**
307     * @brief Sets the width and height of a rectangle.
308     * @param width Indicates the width of the rectangle.
309     * @param height Indicates the height of the rectangle.
310     * @since 1.0
311     * @version 1.0
312     */
313    void Resize(T width, T height)
314    {
315        right_ = left_ + width - 1;
316        bottom_ = top_ + height - 1;
317    }
318
319    /**
320     * @brief Obtains the area of a rectangle.
321     * @return Returns the area of the rectangle.
322     * @since 1.0
323     * @version 1.0
324     */
325    uint32_t GetSize() const
326    {
327        return static_cast<uint32_t>(right_ - left_ + 1) * (bottom_ - top_ + 1);
328    }
329
330    /**
331     * @brief Checks whether two rectangles intersect.
332     * @param rect1 Indicates the first rectangle to check.
333     * @param rect2 Indicates the second rectangle to check.
334     * @return Returns <b>true</b> if the two rectangles intersect; returns <b>false</b> otherwise.
335     * @since 1.0
336     * @version 1.0
337     */
338    bool Intersect(const CommonRect<T>& rect1, const CommonRect<T>& rect2)
339    {
340        /* Get the smaller area from 'rect1' and 'rect2' */
341        left_ = MATH_MAX(rect1.left_, rect2.left_);
342        top_ = MATH_MAX(rect1.top_, rect2.top_);
343        right_ = MATH_MIN(rect1.right_, rect2.right_);
344        bottom_ = MATH_MIN(rect1.bottom_, rect2.bottom_);
345        if ((left_ > right_) || (top_ > bottom_)) {
346            return false;
347        }
348
349        return true;
350    }
351
352    /**
353     * @brief Obtains the minimum rectangle that contains another two rectangles.
354     * @param rect1 Indicates the first rectangle to contain.
355     * @param rect2 Indicates the second rectangle to contain.
356     * @since 1.0
357     * @version 1.0
358     */
359    void Join(const CommonRect<T>& rect1, const CommonRect<T>& rect2)
360    {
361        left_ = MATH_MIN(rect1.left_, rect2.left_);
362        top_ = MATH_MIN(rect1.top_, rect2.top_);
363        right_ = MATH_MAX(rect1.right_, rect2.right_);
364        bottom_ = MATH_MAX(rect1.bottom_, rect2.bottom_);
365    }
366
367    /**
368     * @brief Checks whether the rectangle contains a coordinate point.
369     * @param point Indicates the coordinate point.
370     * @return Returns <b>true</b> if the input coordinate point is contained; returns <b>false</b> otherwise.
371     * @since 1.0
372     * @version 1.0
373     */
374    bool IsContains(const Vector2<T>& point) const
375    {
376        bool isContains = false;
377
378        if ((point.x_ >= this->left_) && (point.x_ <= this->right_) && (point.y_ >= this->top_) &&
379            (point.y_ <= this->bottom_)) {
380            isContains = true;
381        }
382
383        return isContains;
384    }
385
386    /**
387     * @brief Checks whether the rectangle contains a coordinate point.
388     * @param point Indicates the coordinate point.
389     * @return Returns <b>true</b> if the input coordinate point is contained; returns <b>false</b> otherwise.
390     * @since 1.0
391     * @version 1.0
392     */
393    bool IsContains(const Point& point) const
394    {
395        bool isContains = false;
396
397        if ((point.x >= this->left_) && (point.x <= this->right_) && (point.y >= this->top_) &&
398            (point.y <= this->bottom_)) {
399            isContains = true;
400        }
401
402        return isContains;
403    }
404
405    /**
406     * @brief Checks whether the rectangle is adjacent to another rectangle horizontally or vertically.
407     * @param other Indicates the rectangle to be used for check.
408     * @return Returns <b>true</b> if the rectangle is adjacent to the input rectangle; returns <b>false</b> otherwise.
409     * @since 1.0
410     * @version 1.0
411     */
412    bool IsExtends(const CommonRect<T>& other) const
413    {
414        if (left_ == other.left_ && right_ == other.right_) {
415            return (top_ == other.bottom_ + 1) || (bottom_ == other.top_ - 1);
416        }
417
418        if (top_ == other.top_ && bottom_ == other.bottom_) {
419            return (left_ == other.right_ + 1) || (right_ == other.left_ - 1);
420        }
421
422        return false;
423    }
424
425    /**
426     * @brief Checks whether the rectangle intersects with another rectangle.
427     * @param other Indicates the rectangle to be used for check.
428     * @return Returns <b>true</b> if the two rectangles intersect; returns <b>false</b> otherwise.
429     * @since 1.0
430     * @version 1.0
431     */
432    bool IsIntersect(const CommonRect<T>& other) const
433    {
434        if ((this->left_ <= other.right_) && (this->right_ >= other.left_) && (this->top_ <= other.bottom_) &&
435            (this->bottom_ >= other.top_)) {
436            return true;
437        } else {
438            return false;
439        }
440    }
441
442    /**
443     * @brief Checks whether the rectangle contains another rectangle.
444     *
445     * @param other Indicates the rectangle to be used for check.
446     * @return Returns <b>true</b> if the input rectangle is contained; returns <b>false</b> otherwise.
447     * @since 1.0
448     * @version 1.0
449     */
450    bool IsContains(const CommonRect<T>& other) const
451    {
452        bool isContains = false;
453
454        if (other.left_ >= this->left_ && other.top_ >= this->top_ && other.right_ <= this->right_ &&
455            other.bottom_ <= this->bottom_) {
456            isContains = true;
457        }
458
459        return isContains;
460    }
461
462    void Inflate(T delta);
463    void operator=(const CommonRect<T>& other)
464    {
465        left_ = other.left_;
466        right_ = other.right_;
467        top_ = other.top_;
468        bottom_ = other.bottom_;
469    }
470    void operator=(const CommonRect<T>&& other)
471    {
472        left_ = other.left_;
473        right_ = other.right_;
474        top_ = other.top_;
475        bottom_ = other.bottom_;
476    }
477    bool operator==(const CommonRect<T>& other) const
478    {
479        if (left_ == other.left_ && right_ == other.right_ && top_ == other.top_ && bottom_ == other.bottom_) {
480            return true;
481        } else {
482            return false;
483        }
484    }
485
486    void Normalize()
487    {
488        T t;
489        if (left_ > right_) {
490            t = left_;
491            left_ = right_;
492            right_ = t;
493        }
494        if (top_ > bottom_) {
495            t = top_;
496            top_ = bottom_;
497            bottom_ = t;
498        }
499    }
500
501protected:
502    T left_;
503    T top_;
504    T right_;
505    T bottom_;
506};
507using Rect = CommonRect<int16_t>;
508using Rect32 = CommonRect<int32_t>;
509} // namespace OHOS
510#endif // GRAPHIC_LITE_RECT_H
511