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