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