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