• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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_HWUI_RECT_H
18 #define ANDROID_HWUI_RECT_H
19 
20 #include <cmath>
21 #include <SkRect.h>
22 
23 #include <utils/Log.h>
24 
25 #include "Vertex.h"
26 
27 namespace android {
28 namespace uirenderer {
29 
30 #define RECT_STRING "%5.2f %5.2f %5.2f %5.2f"
31 #define RECT_ARGS(r) \
32     (r).left, (r).top, (r).right, (r).bottom
33 #define SK_RECT_ARGS(r) \
34     (r).left(), (r).top(), (r).right(), (r).bottom()
35 
36 ///////////////////////////////////////////////////////////////////////////////
37 // Structs
38 ///////////////////////////////////////////////////////////////////////////////
39 
40 class Rect {
41 public:
42     float left;
43     float top;
44     float right;
45     float bottom;
46 
47     // Used by Region
48     typedef float value_type;
49 
50     // we don't provide copy-ctor and operator= on purpose
51     // because we want the compiler generated versions
52 
Rect()53     inline Rect():
54             left(0),
55             top(0),
56             right(0),
57             bottom(0) {
58     }
59 
Rect(float left,float top,float right,float bottom)60     inline Rect(float left, float top, float right, float bottom):
61             left(left),
62             top(top),
63             right(right),
64             bottom(bottom) {
65     }
66 
Rect(float width,float height)67     inline Rect(float width, float height):
68             left(0.0f),
69             top(0.0f),
70             right(width),
71             bottom(height) {
72     }
73 
Rect(const SkRect & rect)74     inline Rect(const SkRect& rect):
75             left(rect.fLeft),
76             top(rect.fTop),
77             right(rect.fRight),
78             bottom(rect.fBottom) {
79     }
80 
81     friend int operator==(const Rect& a, const Rect& b) {
82         return !memcmp(&a, &b, sizeof(a));
83     }
84 
85     friend int operator!=(const Rect& a, const Rect& b) {
86         return memcmp(&a, &b, sizeof(a));
87     }
88 
clear()89     inline void clear() {
90         left = top = right = bottom = 0.0f;
91     }
92 
isEmpty()93     inline bool isEmpty() const {
94         // this is written in such way this it'll handle NANs to return
95         // true (empty)
96         return !((left < right) && (top < bottom));
97     }
98 
setEmpty()99     inline void setEmpty() {
100         left = top = right = bottom = 0.0f;
101     }
102 
set(float left,float top,float right,float bottom)103     inline void set(float left, float top, float right, float bottom) {
104         this->left = left;
105         this->right = right;
106         this->top = top;
107         this->bottom = bottom;
108     }
109 
set(const Rect & r)110     inline void set(const Rect& r) {
111         set(r.left, r.top, r.right, r.bottom);
112     }
113 
getWidth()114     inline float getWidth() const {
115         return right - left;
116     }
117 
getHeight()118     inline float getHeight() const {
119         return bottom - top;
120     }
121 
intersects(float l,float t,float r,float b)122     bool intersects(float l, float t, float r, float b) const {
123         return !intersectWith(l, t, r, b).isEmpty();
124     }
125 
intersects(const Rect & r)126     bool intersects(const Rect& r) const {
127         return intersects(r.left, r.top, r.right, r.bottom);
128     }
129 
intersect(float l,float t,float r,float b)130     bool intersect(float l, float t, float r, float b) {
131         Rect tmp(l, t, r, b);
132         intersectWith(tmp);
133         if (!tmp.isEmpty()) {
134             set(tmp);
135             return true;
136         }
137         return false;
138     }
139 
intersect(const Rect & r)140     bool intersect(const Rect& r) {
141         return intersect(r.left, r.top, r.right, r.bottom);
142     }
143 
contains(float l,float t,float r,float b)144     inline bool contains(float l, float t, float r, float b) const {
145         return l >= left && t >= top && r <= right && b <= bottom;
146     }
147 
contains(const Rect & r)148     inline bool contains(const Rect& r) const {
149         return contains(r.left, r.top, r.right, r.bottom);
150     }
151 
unionWith(const Rect & r)152     bool unionWith(const Rect& r) {
153         if (r.left < r.right && r.top < r.bottom) {
154             if (left < right && top < bottom) {
155                 if (left > r.left) left = r.left;
156                 if (top > r.top) top = r.top;
157                 if (right < r.right) right = r.right;
158                 if (bottom < r.bottom) bottom = r.bottom;
159                 return true;
160             } else {
161                 left = r.left;
162                 top = r.top;
163                 right = r.right;
164                 bottom = r.bottom;
165                 return true;
166             }
167         }
168         return false;
169     }
170 
translate(float dx,float dy)171     void translate(float dx, float dy) {
172         left += dx;
173         right += dx;
174         top += dy;
175         bottom += dy;
176     }
177 
inset(float delta)178     void inset(float delta) {
179         outset(-delta);
180     }
181 
outset(float delta)182     void outset(float delta) {
183         left -= delta;
184         top -= delta;
185         right += delta;
186         bottom += delta;
187     }
188 
outset(float xdelta,float ydelta)189     void outset(float xdelta, float ydelta) {
190         left -= xdelta;
191         top -= ydelta;
192         right += xdelta;
193         bottom += ydelta;
194     }
195 
196     /**
197      * Similar to snapToPixelBoundaries, but estimates bounds conservatively to handle GL rounding
198      * errors.
199      *
200      * This function should be used whenever estimating the damage rect of geometry already mapped
201      * into layer space.
202      */
snapGeometryToPixelBoundaries(bool snapOut)203     void snapGeometryToPixelBoundaries(bool snapOut) {
204         if (snapOut) {
205             /* For AA geometry with a ramp perimeter, don't snap by rounding - AA geometry will have
206              * a 0.5 pixel perimeter not accounted for in its bounds. Instead, snap by
207              * conservatively rounding out the bounds with floor/ceil.
208              *
209              * In order to avoid changing integer bounds with floor/ceil due to rounding errors
210              * inset the bounds first by the fudge factor. Very small fraction-of-a-pixel errors
211              * from this inset will only incur similarly small errors in output, due to transparency
212              * in extreme outside of the geometry.
213              */
214             left = floorf(left + Vertex::GeometryFudgeFactor());
215             top = floorf(top + Vertex::GeometryFudgeFactor());
216             right = ceilf(right - Vertex::GeometryFudgeFactor());
217             bottom = ceilf(bottom - Vertex::GeometryFudgeFactor());
218         } else {
219             /* For other geometry, we do the regular rounding in order to snap, but also outset the
220              * bounds by a fudge factor. This ensures that ambiguous geometry (e.g. a non-AA Rect
221              * with top left at (0.5, 0.5)) will err on the side of a larger damage rect.
222              */
223             left = floorf(left + 0.5f - Vertex::GeometryFudgeFactor());
224             top = floorf(top + 0.5f - Vertex::GeometryFudgeFactor());
225             right = floorf(right + 0.5f + Vertex::GeometryFudgeFactor());
226             bottom = floorf(bottom + 0.5f + Vertex::GeometryFudgeFactor());
227         }
228     }
229 
snapToPixelBoundaries()230     void snapToPixelBoundaries() {
231         left = floorf(left + 0.5f);
232         top = floorf(top + 0.5f);
233         right = floorf(right + 0.5f);
234         bottom = floorf(bottom + 0.5f);
235     }
236 
roundOut()237     void roundOut() {
238         left = floorf(left);
239         top = floorf(top);
240         right = ceilf(right);
241         bottom = ceilf(bottom);
242     }
243 
expandToCoverVertex(float x,float y)244     void expandToCoverVertex(float x, float y) {
245         left = fminf(left, x);
246         top = fminf(top, y);
247         right = fmaxf(right, x);
248         bottom = fmaxf(bottom, y);
249     }
250 
251     void dump(const char* label = NULL) const {
252         ALOGD("%s[l=%f t=%f r=%f b=%f]", label ? label : "Rect", left, top, right, bottom);
253     }
254 
255 private:
intersectWith(Rect & tmp)256     void intersectWith(Rect& tmp) const {
257         tmp.left = fmaxf(left, tmp.left);
258         tmp.top = fmaxf(top, tmp.top);
259         tmp.right = fminf(right, tmp.right);
260         tmp.bottom = fminf(bottom, tmp.bottom);
261     }
262 
intersectWith(float l,float t,float r,float b)263     Rect intersectWith(float l, float t, float r, float b) const {
264         Rect tmp;
265         tmp.left = fmaxf(left, l);
266         tmp.top = fmaxf(top, t);
267         tmp.right = fminf(right, r);
268         tmp.bottom = fminf(bottom, b);
269         return tmp;
270     }
271 
272 }; // class Rect
273 
274 }; // namespace uirenderer
275 }; // namespace android
276 
277 #endif // ANDROID_HWUI_RECT_H
278