blob: 50199db756400df41f2e82ae3eb9f34b733e5d1e [file] [log] [blame]
Romain Guybb9524b2010-06-22 18:56:38 -07001/*
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
Romain Guy5b3b3522010-10-27 18:57:51 -070017#ifndef ANDROID_HWUI_RECT_H
18#define ANDROID_HWUI_RECT_H
19
20#include <cmath>
Chris Craikdf72b632015-06-30 17:56:13 -070021#include <algorithm>
ztenghuiaf6f7ed2014-03-18 17:25:49 -070022#include <SkRect.h>
Romain Guybb9524b2010-06-22 18:56:38 -070023
Romain Guy5cbbce52010-06-27 22:59:20 -070024#include <utils/Log.h>
25
Chris Craik32f05e32013-09-17 16:20:29 -070026#include "Vertex.h"
27
Romain Guybb9524b2010-06-22 18:56:38 -070028namespace android {
Romain Guy9d5316e2010-06-24 19:30:36 -070029namespace uirenderer {
Romain Guybb9524b2010-06-22 18:56:38 -070030
Chris Craik62d307c2014-07-29 10:35:13 -070031#define RECT_STRING "%5.2f %5.2f %5.2f %5.2f"
Chris Craik28ce94a2013-05-31 11:38:03 -070032#define RECT_ARGS(r) \
33 (r).left, (r).top, (r).right, (r).bottom
Chris Craik3f0854292014-04-15 16:18:08 -070034#define SK_RECT_ARGS(r) \
35 (r).left(), (r).top(), (r).right(), (r).bottom()
Chris Craik28ce94a2013-05-31 11:38:03 -070036
Romain Guybb9524b2010-06-22 18:56:38 -070037///////////////////////////////////////////////////////////////////////////////
38// Structs
39///////////////////////////////////////////////////////////////////////////////
40
Mathias Agopian83b186a2011-09-19 16:00:46 -070041class Rect {
Mathias Agopian83b186a2011-09-19 16:00:46 -070042public:
Romain Guy7ae7ac42010-06-25 13:46:18 -070043 float left;
44 float top;
45 float right;
46 float bottom;
Romain Guybb9524b2010-06-22 18:56:38 -070047
Romain Guy5b3b3522010-10-27 18:57:51 -070048 // Used by Region
49 typedef float value_type;
50
Mathias Agopian83b186a2011-09-19 16:00:46 -070051 // we don't provide copy-ctor and operator= on purpose
52 // because we want the compiler generated versions
53
Romain Guy5b3b3522010-10-27 18:57:51 -070054 inline Rect():
Romain Guy7ae7ac42010-06-25 13:46:18 -070055 left(0),
56 top(0),
57 right(0),
58 bottom(0) {
59 }
Romain Guy9d5316e2010-06-24 19:30:36 -070060
Romain Guy5b3b3522010-10-27 18:57:51 -070061 inline Rect(float left, float top, float right, float bottom):
Romain Guy7ae7ac42010-06-25 13:46:18 -070062 left(left),
63 top(top),
64 right(right),
65 bottom(bottom) {
66 }
Romain Guybb9524b2010-06-22 18:56:38 -070067
Romain Guy5b3b3522010-10-27 18:57:51 -070068 inline Rect(float width, float height):
69 left(0.0f),
70 top(0.0f),
71 right(width),
72 bottom(height) {
73 }
74
ztenghuiaf6f7ed2014-03-18 17:25:49 -070075 inline Rect(const SkRect& rect):
76 left(rect.fLeft),
77 top(rect.fTop),
78 right(rect.fRight),
79 bottom(rect.fBottom) {
80 }
81
Romain Guy7ae7ac42010-06-25 13:46:18 -070082 friend int operator==(const Rect& a, const Rect& b) {
83 return !memcmp(&a, &b, sizeof(a));
84 }
Romain Guybb9524b2010-06-22 18:56:38 -070085
Romain Guy7ae7ac42010-06-25 13:46:18 -070086 friend int operator!=(const Rect& a, const Rect& b) {
87 return memcmp(&a, &b, sizeof(a));
88 }
Romain Guybb9524b2010-06-22 18:56:38 -070089
Romain Guy5b3b3522010-10-27 18:57:51 -070090 inline void clear() {
91 left = top = right = bottom = 0.0f;
92 }
93
94 inline bool isEmpty() const {
Mathias Agopian83b186a2011-09-19 16:00:46 -070095 // this is written in such way this it'll handle NANs to return
96 // true (empty)
97 return !((left < right) && (top < bottom));
Romain Guy7ae7ac42010-06-25 13:46:18 -070098 }
Romain Guybb9524b2010-06-22 18:56:38 -070099
Romain Guy5b3b3522010-10-27 18:57:51 -0700100 inline void setEmpty() {
101 left = top = right = bottom = 0.0f;
Romain Guy7ae7ac42010-06-25 13:46:18 -0700102 }
Romain Guybb9524b2010-06-22 18:56:38 -0700103
Romain Guy5b3b3522010-10-27 18:57:51 -0700104 inline void set(float left, float top, float right, float bottom) {
Romain Guy7ae7ac42010-06-25 13:46:18 -0700105 this->left = left;
106 this->right = right;
107 this->top = top;
108 this->bottom = bottom;
109 }
Romain Guybb9524b2010-06-22 18:56:38 -0700110
Romain Guy5b3b3522010-10-27 18:57:51 -0700111 inline void set(const Rect& r) {
Romain Guy7ae7ac42010-06-25 13:46:18 -0700112 set(r.left, r.top, r.right, r.bottom);
113 }
Romain Guybb9524b2010-06-22 18:56:38 -0700114
Rob Tsuk487a92c2015-01-06 13:22:54 -0800115 inline void set(const SkIRect& r) {
116 set(r.left(), r.top(), r.right(), r.bottom());
117 }
118
Romain Guy8aef54f2010-09-01 15:13:49 -0700119 inline float getWidth() const {
Romain Guy7ae7ac42010-06-25 13:46:18 -0700120 return right - left;
121 }
Romain Guybb9524b2010-06-22 18:56:38 -0700122
Romain Guy8aef54f2010-09-01 15:13:49 -0700123 inline float getHeight() const {
Romain Guy7ae7ac42010-06-25 13:46:18 -0700124 return bottom - top;
125 }
Romain Guybb9524b2010-06-22 18:56:38 -0700126
Mathias Agopian83b186a2011-09-19 16:00:46 -0700127 bool intersects(float l, float t, float r, float b) const {
Chris Craikac02eb92015-10-05 12:23:46 -0700128 float tempLeft = std::max(left, l);
129 float tempTop = std::max(top, t);
130 float tempRight = std::min(right, r);
131 float tempBottom = std::min(bottom, b);
132
133 return ((tempLeft < tempRight) && (tempTop < tempBottom)); // !isEmpty
Romain Guy7ae7ac42010-06-25 13:46:18 -0700134 }
Romain Guybb9524b2010-06-22 18:56:38 -0700135
Romain Guy7ae7ac42010-06-25 13:46:18 -0700136 bool intersects(const Rect& r) const {
137 return intersects(r.left, r.top, r.right, r.bottom);
138 }
Romain Guybb9524b2010-06-22 18:56:38 -0700139
Chris Craikac02eb92015-10-05 12:23:46 -0700140 /**
141 * This method is named 'doIntersect' instead of 'intersect' so as not to be confused with
142 * SkRect::intersect / android.graphics.Rect#intersect behavior, which do not modify the object
143 * if the intersection of the rects would be empty.
144 */
145 void doIntersect(float l, float t, float r, float b) {
146 left = std::max(left, l);
147 top = std::max(top, t);
148 right = std::min(right, r);
149 bottom = std::min(bottom, b);
Romain Guy7ae7ac42010-06-25 13:46:18 -0700150 }
Romain Guybb9524b2010-06-22 18:56:38 -0700151
Chris Craikac02eb92015-10-05 12:23:46 -0700152 void doIntersect(const Rect& r) {
153 doIntersect(r.left, r.top, r.right, r.bottom);
Romain Guy7ae7ac42010-06-25 13:46:18 -0700154 }
Romain Guybb9524b2010-06-22 18:56:38 -0700155
Romain Guy2db5e992013-05-21 15:29:59 -0700156 inline bool contains(float l, float t, float r, float b) const {
Romain Guyec31f832011-12-13 18:39:19 -0800157 return l >= left && t >= top && r <= right && b <= bottom;
158 }
159
Romain Guy2db5e992013-05-21 15:29:59 -0700160 inline bool contains(const Rect& r) const {
Romain Guyec31f832011-12-13 18:39:19 -0800161 return contains(r.left, r.top, r.right, r.bottom);
162 }
163
Romain Guy079ba2c2010-07-16 14:12:24 -0700164 bool unionWith(const Rect& r) {
165 if (r.left < r.right && r.top < r.bottom) {
166 if (left < right && top < bottom) {
167 if (left > r.left) left = r.left;
168 if (top > r.top) top = r.top;
169 if (right < r.right) right = r.right;
170 if (bottom < r.bottom) bottom = r.bottom;
171 return true;
172 } else {
173 left = r.left;
174 top = r.top;
175 right = r.right;
176 bottom = r.bottom;
177 return true;
178 }
179 }
180 return false;
181 }
182
Romain Guy5b3b3522010-10-27 18:57:51 -0700183 void translate(float dx, float dy) {
184 left += dx;
185 right += dx;
186 top += dy;
187 bottom += dy;
188 }
189
Chris Craike4aa95e2014-05-08 13:57:05 -0700190 void inset(float delta) {
191 outset(-delta);
192 }
193
Chris Craikc3566d02013-02-04 16:16:33 -0800194 void outset(float delta) {
195 left -= delta;
196 top -= delta;
197 right += delta;
198 bottom += delta;
199 }
200
Chris Craik05f3d6e2014-06-02 16:27:04 -0700201 void outset(float xdelta, float ydelta) {
202 left -= xdelta;
203 top -= ydelta;
204 right += xdelta;
205 bottom += ydelta;
206 }
207
Chris Craik5e49b302013-07-30 19:05:20 -0700208 /**
Chris Craik32f05e32013-09-17 16:20:29 -0700209 * Similar to snapToPixelBoundaries, but estimates bounds conservatively to handle GL rounding
210 * errors.
Chris Craik5e49b302013-07-30 19:05:20 -0700211 *
Chris Craik32f05e32013-09-17 16:20:29 -0700212 * This function should be used whenever estimating the damage rect of geometry already mapped
213 * into layer space.
Chris Craik5e49b302013-07-30 19:05:20 -0700214 */
Chris Craik32f05e32013-09-17 16:20:29 -0700215 void snapGeometryToPixelBoundaries(bool snapOut) {
216 if (snapOut) {
217 /* For AA geometry with a ramp perimeter, don't snap by rounding - AA geometry will have
218 * a 0.5 pixel perimeter not accounted for in its bounds. Instead, snap by
219 * conservatively rounding out the bounds with floor/ceil.
220 *
221 * In order to avoid changing integer bounds with floor/ceil due to rounding errors
222 * inset the bounds first by the fudge factor. Very small fraction-of-a-pixel errors
223 * from this inset will only incur similarly small errors in output, due to transparency
224 * in extreme outside of the geometry.
225 */
Chris Craik564acf72014-01-02 16:46:18 -0800226 left = floorf(left + Vertex::GeometryFudgeFactor());
227 top = floorf(top + Vertex::GeometryFudgeFactor());
228 right = ceilf(right - Vertex::GeometryFudgeFactor());
229 bottom = ceilf(bottom - Vertex::GeometryFudgeFactor());
Chris Craik32f05e32013-09-17 16:20:29 -0700230 } else {
231 /* For other geometry, we do the regular rounding in order to snap, but also outset the
232 * bounds by a fudge factor. This ensures that ambiguous geometry (e.g. a non-AA Rect
233 * with top left at (0.5, 0.5)) will err on the side of a larger damage rect.
234 */
Chris Craik564acf72014-01-02 16:46:18 -0800235 left = floorf(left + 0.5f - Vertex::GeometryFudgeFactor());
236 top = floorf(top + 0.5f - Vertex::GeometryFudgeFactor());
237 right = floorf(right + 0.5f + Vertex::GeometryFudgeFactor());
238 bottom = floorf(bottom + 0.5f + Vertex::GeometryFudgeFactor());
Chris Craik32f05e32013-09-17 16:20:29 -0700239 }
Chris Craik5e49b302013-07-30 19:05:20 -0700240 }
241
Romain Guybf434112010-09-16 14:40:17 -0700242 void snapToPixelBoundaries() {
Romain Guyae88e5e2010-10-22 17:49:18 -0700243 left = floorf(left + 0.5f);
244 top = floorf(top + 0.5f);
245 right = floorf(right + 0.5f);
246 bottom = floorf(bottom + 0.5f);
Romain Guybf434112010-09-16 14:40:17 -0700247 }
248
Chris Craikf0a59072013-11-19 18:00:46 -0800249 void roundOut() {
250 left = floorf(left);
251 top = floorf(top);
252 right = ceilf(right);
253 bottom = ceilf(bottom);
254 }
255
Chris Craikc93e45c2014-07-16 10:15:56 -0700256 void expandToCoverVertex(float x, float y) {
Chris Craikdf72b632015-06-30 17:56:13 -0700257 left = std::min(left, x);
258 top = std::min(top, y);
259 right = std::max(right, x);
260 bottom = std::max(bottom, y);
Chris Craikc93e45c2014-07-16 10:15:56 -0700261 }
262
Chris Craik8820fd12015-03-03 14:20:47 -0800263 void expandToCoverRect(float otherLeft, float otherTop, float otherRight, float otherBottom) {
Chris Craikdf72b632015-06-30 17:56:13 -0700264 left = std::min(left, otherLeft);
265 top = std::min(top, otherTop);
266 right = std::max(right, otherRight);
267 bottom = std::max(bottom, otherBottom);
Chris Craik8820fd12015-03-03 14:20:47 -0800268 }
269
Rob Tsuk487a92c2015-01-06 13:22:54 -0800270 SkRect toSkRect() const {
271 return SkRect::MakeLTRB(left, top, right, bottom);
272 }
273
274 SkIRect toSkIRect() const {
275 return SkIRect::MakeLTRB(left, top, right, bottom);
276 }
277
Chris Craike84a2082014-12-22 14:28:49 -0800278 void dump(const char* label = nullptr) const {
Chris Craike4aa95e2014-05-08 13:57:05 -0700279 ALOGD("%s[l=%f t=%f r=%f b=%f]", label ? label : "Rect", left, top, right, bottom);
Romain Guy7ae7ac42010-06-25 13:46:18 -0700280 }
Mathias Agopian83b186a2011-09-19 16:00:46 -0700281}; // class Rect
Romain Guybb9524b2010-06-22 18:56:38 -0700282
Romain Guy9d5316e2010-06-24 19:30:36 -0700283}; // namespace uirenderer
Romain Guybb9524b2010-06-22 18:56:38 -0700284}; // namespace android
285
Romain Guy5b3b3522010-10-27 18:57:51 -0700286#endif // ANDROID_HWUI_RECT_H