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 <log/log.h>
23 #include <utils/Flattenable.h>
24 #include <utils/Log.h>
25 #include <utils/TypeHelpers.h>
26 
27 #include <math/HashCombine.h>
28 #include <ui/FloatRect.h>
29 #include <ui/Point.h>
30 #include <ui/Size.h>
31 
32 #include <android/rect.h>
33 
34 namespace android {
35 
36 class Rect : public ARect, public LightFlattenablePod<Rect>
37 {
38 public:
39     typedef ARect::value_type value_type;
40 
41     static const Rect INVALID_RECT;
42     static const Rect EMPTY_RECT;
43 
44     // we don't provide copy-ctor and operator= on purpose
45     // because we want the compiler generated versions
46 
Rect()47     inline Rect() : Rect(INVALID_RECT) {}
48 
49     template <typename T>
Rect(T w,T h)50     inline Rect(T w, T h) {
51         if (w > INT32_MAX) {
52             w = INT32_MAX;
53         }
54         if (h > INT32_MAX) {
55             h = INT32_MAX;
56         }
57         left = top = 0;
58         right = static_cast<int32_t>(w);
59         bottom = static_cast<int32_t>(h);
60     }
61 
Rect(int32_t l,int32_t t,int32_t r,int32_t b)62     inline Rect(int32_t l, int32_t t, int32_t r, int32_t b) {
63         left = l;
64         top = t;
65         right = r;
66         bottom = b;
67     }
68 
Rect(const Point & lt,const Point & rb)69     inline Rect(const Point& lt, const Point& rb) {
70         left = lt.x;
71         top = lt.y;
72         right = rb.x;
73         bottom = rb.y;
74     }
75 
Rect(const FloatRect & floatRect)76     inline explicit Rect(const FloatRect& floatRect) {
77         left = static_cast<int32_t>(std::round(floatRect.left));
78         top = static_cast<int32_t>(std::round(floatRect.top));
79         right = static_cast<int32_t>(std::round(floatRect.right));
80         bottom = static_cast<int32_t>(std::round(floatRect.bottom));
81     }
82 
Rect(const ui::Size & size)83     inline explicit Rect(const ui::Size& size) {
84         left = 0;
85         top = 0;
86         right = size.width;
87         bottom = size.height;
88     }
89 
90     void makeInvalid();
91 
clear()92     inline void clear() {
93         left = top = right = bottom = 0;
94     }
95 
96     // a valid rectangle has a non negative width and height
isValid()97     inline bool isValid() const {
98         return (getWidth() >= 0) && (getHeight() >= 0);
99     }
100 
101     // an empty rect has a zero width or height, or is invalid
isEmpty()102     inline bool isEmpty() const {
103         return (getWidth() <= 0) || (getHeight() <= 0);
104     }
105 
106     // rectangle's width
107     __attribute__((no_sanitize("signed-integer-overflow")))
getWidth()108     inline int32_t getWidth() const {
109         return right - left;
110     }
111 
112     // rectangle's height
113     __attribute__((no_sanitize("signed-integer-overflow")))
getHeight()114     inline int32_t getHeight() const {
115         return bottom - top;
116     }
117 
getSize()118     ui::Size getSize() const { return ui::Size(getWidth(), getHeight()); }
119 
120     __attribute__((no_sanitize("signed-integer-overflow")))
getBounds()121     inline Rect getBounds() const {
122         return Rect(right - left, bottom - top);
123     }
124 
setLeftTop(const Point & lt)125     void setLeftTop(const Point& lt) {
126         left = lt.x;
127         top = lt.y;
128     }
129 
setRightBottom(const Point & rb)130     void setRightBottom(const Point& rb) {
131         right = rb.x;
132         bottom = rb.y;
133     }
134 
135     // the following 4 functions return the 4 corners of the rect as Point
leftTop()136     Point leftTop() const {
137         return Point(left, top);
138     }
rightBottom()139     Point rightBottom() const {
140         return Point(right, bottom);
141     }
rightTop()142     Point rightTop() const {
143         return Point(right, top);
144     }
leftBottom()145     Point leftBottom() const {
146         return Point(left, bottom);
147     }
148 
149     // comparisons
150     inline bool operator == (const Rect& rhs) const {
151         return (left == rhs.left) && (top == rhs.top) &&
152                (right == rhs.right) && (bottom == rhs.bottom);
153     }
154 
155     inline bool operator != (const Rect& rhs) const {
156         return !operator == (rhs);
157     }
158 
159     // operator < defines an order which allows to use rectangles in sorted
160     // vectors.
161     bool operator < (const Rect& rhs) const;
162 
163     const Rect operator + (const Point& rhs) const;
164     const Rect operator - (const Point& rhs) const;
165 
166     Rect& operator += (const Point& rhs) {
167         return offsetBy(rhs.x, rhs.y);
168     }
169     Rect& operator -= (const Point& rhs) {
170         return offsetBy(-rhs.x, -rhs.y);
171     }
172 
offsetToOrigin()173     Rect& offsetToOrigin() {
174         right -= left;
175         bottom -= top;
176         left = top = 0;
177         return *this;
178     }
offsetTo(const Point & p)179     Rect& offsetTo(const Point& p) {
180         return offsetTo(p.x, p.y);
181     }
offsetBy(const Point & dp)182     Rect& offsetBy(const Point& dp) {
183         return offsetBy(dp.x, dp.y);
184     }
185 
186     Rect& offsetTo(int32_t x, int32_t y);
187     Rect& offsetBy(int32_t x, int32_t y);
188 
189     /**
190      * Insets the rectangle on all sides specified by the insets.
191      */
192     Rect& inset(int32_t _left, int32_t _top, int32_t _right, int32_t _bottom);
193 
194     bool intersect(const Rect& with, Rect* result) const;
195 
196     // Create a new Rect by transforming this one using a graphics HAL
197     // transform.  This rectangle is defined in a coordinate space starting at
198     // the origin and extending to (width, height).  If the transform includes
199     // a ROT90 then the output rectangle is defined in a space extending to
200     // (height, width).  Otherwise the output rectangle is in the same space as
201     // the input.
202     Rect transform(uint32_t xform, int32_t width, int32_t height) const;
203 
scale(float scaleX,float scaleY)204     Rect scale(float scaleX, float scaleY) const {
205         return Rect(FloatRect(left * scaleX, top * scaleY, right * scaleX, bottom * scaleY));
206     }
207 
scaleSelf(float scaleX,float scaleY)208     Rect& scaleSelf(float scaleX, float scaleY) {
209         set(scale(scaleX, scaleY));
210         return *this;
211     }
212 
213     // this calculates (Region(*this) - exclude).bounds() efficiently
214     Rect reduce(const Rect& exclude) const;
215 
216     // for backward compatibility
width()217     inline int32_t width() const { return getWidth(); }
height()218     inline int32_t height() const { return getHeight(); }
set(const Rect & rhs)219     inline void set(const Rect& rhs) { operator = (rhs); }
220 
toFloatRect()221     FloatRect toFloatRect() const {
222         return {static_cast<float>(left), static_cast<float>(top),
223                 static_cast<float>(right), static_cast<float>(bottom)};
224     }
225 };
226 
227 std::string to_string(const android::Rect& rect);
228 
229 // Defining PrintTo helps with Google Tests.
230 void PrintTo(const Rect& rect, ::std::ostream* os);
231 
232 ANDROID_BASIC_TYPES_TRAITS(Rect)
233 
234 } // namespace android
235 
236 namespace std {
237 template <>
238 struct hash<android::Rect> {
239     size_t operator()(const android::Rect& rect) const {
240         return android::hashCombine(rect.left, rect.top, rect.right, rect.bottom);
241     }
242 };
243 } // namespace std
244 
245 #endif // ANDROID_UI_RECT
246