1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ANDROID_UI_RECT
18 #define ANDROID_UI_RECT
19 
20 #include <ostream>
21 
22 #include <utils/Flattenable.h>
23 #include <utils/Log.h>
24 #include <utils/TypeHelpers.h>
25 #include <log/log.h>
26 
27 #include <ui/FloatRect.h>
28 #include <ui/Point.h>
29 #include <ui/Size.h>
30 
31 #include <android/rect.h>
32 
33 namespace android {
34 
35 class Rect : public ARect, public LightFlattenablePod<Rect>
36 {
37 public:
38     typedef ARect::value_type value_type;
39 
40     static const Rect INVALID_RECT;
41     static const Rect EMPTY_RECT;
42 
43     // we don't provide copy-ctor and operator= on purpose
44     // because we want the compiler generated versions
45 
Rect()46     inline Rect() : Rect(INVALID_RECT) {}
47 
48     template <typename T>
Rect(T w,T h)49     inline Rect(T w, T h) {
50         if (w > INT32_MAX) {
51             w = INT32_MAX;
52         }
53         if (h > INT32_MAX) {
54             h = INT32_MAX;
55         }
56         left = top = 0;
57         right = static_cast<int32_t>(w);
58         bottom = static_cast<int32_t>(h);
59     }
60 
Rect(int32_t l,int32_t t,int32_t r,int32_t b)61     inline Rect(int32_t l, int32_t t, int32_t r, int32_t b) {
62         left = l;
63         top = t;
64         right = r;
65         bottom = b;
66     }
67 
Rect(const Point & lt,const Point & rb)68     inline Rect(const Point& lt, const Point& rb) {
69         left = lt.x;
70         top = lt.y;
71         right = rb.x;
72         bottom = rb.y;
73     }
74 
Rect(const FloatRect & floatRect)75     inline explicit Rect(const FloatRect& floatRect) {
76         // Ideally we would use std::round, but we don't want to add an STL
77         // dependency here, so we use an approximation
78         left = static_cast<int32_t>(floatRect.left + 0.5f);
79         top = static_cast<int32_t>(floatRect.top + 0.5f);
80         right = static_cast<int32_t>(floatRect.right + 0.5f);
81         bottom = static_cast<int32_t>(floatRect.bottom + 0.5f);
82     }
83 
Rect(const ui::Size & size)84     inline explicit Rect(const ui::Size& size) {
85         left = 0;
86         top = 0;
87         right = size.width;
88         bottom = size.height;
89     }
90 
91     void makeInvalid();
92 
clear()93     inline void clear() {
94         left = top = right = bottom = 0;
95     }
96 
97     // a valid rectangle has a non negative width and height
isValid()98     inline bool isValid() const {
99         return (getWidth() >= 0) && (getHeight() >= 0);
100     }
101 
102     // an empty rect has a zero width or height, or is invalid
isEmpty()103     inline bool isEmpty() const {
104         return (getWidth() <= 0) || (getHeight() <= 0);
105     }
106 
107     // rectangle's width
108     __attribute__((no_sanitize("signed-integer-overflow")))
getWidth()109     inline int32_t getWidth() const {
110         return right - left;
111     }
112 
113     // rectangle's height
114     __attribute__((no_sanitize("signed-integer-overflow")))
getHeight()115     inline int32_t getHeight() const {
116         return bottom - top;
117     }
118 
getSize()119     ui::Size getSize() const { return ui::Size(getWidth(), getHeight()); }
120 
121     __attribute__((no_sanitize("signed-integer-overflow")))
getBounds()122     inline Rect getBounds() const {
123         return Rect(right - left, bottom - top);
124     }
125 
setLeftTop(const Point & lt)126     void setLeftTop(const Point& lt) {
127         left = lt.x;
128         top = lt.y;
129     }
130 
setRightBottom(const Point & rb)131     void setRightBottom(const Point& rb) {
132         right = rb.x;
133         bottom = rb.y;
134     }
135 
136     // the following 4 functions return the 4 corners of the rect as Point
leftTop()137     Point leftTop() const {
138         return Point(left, top);
139     }
rightBottom()140     Point rightBottom() const {
141         return Point(right, bottom);
142     }
rightTop()143     Point rightTop() const {
144         return Point(right, top);
145     }
leftBottom()146     Point leftBottom() const {
147         return Point(left, bottom);
148     }
149 
150     // comparisons
151     inline bool operator == (const Rect& rhs) const {
152         return (left == rhs.left) && (top == rhs.top) &&
153                (right == rhs.right) && (bottom == rhs.bottom);
154     }
155 
156     inline bool operator != (const Rect& rhs) const {
157         return !operator == (rhs);
158     }
159 
160     // operator < defines an order which allows to use rectangles in sorted
161     // vectors.
162     bool operator < (const Rect& rhs) const;
163 
164     const Rect operator + (const Point& rhs) const;
165     const Rect operator - (const Point& rhs) const;
166 
167     Rect& operator += (const Point& rhs) {
168         return offsetBy(rhs.x, rhs.y);
169     }
170     Rect& operator -= (const Point& rhs) {
171         return offsetBy(-rhs.x, -rhs.y);
172     }
173 
offsetToOrigin()174     Rect& offsetToOrigin() {
175         right -= left;
176         bottom -= top;
177         left = top = 0;
178         return *this;
179     }
offsetTo(const Point & p)180     Rect& offsetTo(const Point& p) {
181         return offsetTo(p.x, p.y);
182     }
offsetBy(const Point & dp)183     Rect& offsetBy(const Point& dp) {
184         return offsetBy(dp.x, dp.y);
185     }
186 
187     Rect& offsetTo(int32_t x, int32_t y);
188     Rect& offsetBy(int32_t x, int32_t y);
189 
190     /**
191      * Insets the rectangle on all sides specified by the insets.
192      */
193     Rect& inset(int32_t _left, int32_t _top, int32_t _right, int32_t _bottom);
194 
195     bool intersect(const Rect& with, Rect* result) const;
196 
197     // Create a new Rect by transforming this one using a graphics HAL
198     // transform.  This rectangle is defined in a coordinate space starting at
199     // the origin and extending to (width, height).  If the transform includes
200     // a ROT90 then the output rectangle is defined in a space extending to
201     // (height, width).  Otherwise the output rectangle is in the same space as
202     // the input.
203     Rect transform(uint32_t xform, int32_t width, int32_t height) const;
204 
205     // this calculates (Region(*this) - exclude).bounds() efficiently
206     Rect reduce(const Rect& exclude) const;
207 
208     // for backward compatibility
width()209     inline int32_t width() const { return getWidth(); }
height()210     inline int32_t height() const { return getHeight(); }
set(const Rect & rhs)211     inline void set(const Rect& rhs) { operator = (rhs); }
212 
toFloatRect()213     FloatRect toFloatRect() const {
214         return {static_cast<float>(left), static_cast<float>(top),
215                 static_cast<float>(right), static_cast<float>(bottom)};
216     }
217 };
218 
219 // Defining PrintTo helps with Google Tests.
PrintTo(const Rect & rect,::std::ostream * os)220 static inline void PrintTo(const Rect& rect, ::std::ostream* os) {
221     *os << "Rect(" << rect.left << ", " << rect.top << ", " << rect.right << ", " << rect.bottom
222         << ")";
223 }
224 
225 ANDROID_BASIC_TYPES_TRAITS(Rect)
226 
227 }; // namespace android
228 
229 #endif // ANDROID_UI_RECT
230