blob: 4c4cd3da3be467eae87142f41cb48c184ff00bd2 [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 {
Romain Guya1d3c912011-12-13 14:55:06 -0800128 return !intersectWith(l, t, r, b).isEmpty();
Romain Guy7ae7ac42010-06-25 13:46:18 -0700129 }
Romain Guybb9524b2010-06-22 18:56:38 -0700130
Romain Guy7ae7ac42010-06-25 13:46:18 -0700131 bool intersects(const Rect& r) const {
132 return intersects(r.left, r.top, r.right, r.bottom);
133 }
Romain Guybb9524b2010-06-22 18:56:38 -0700134
Mathias Agopian83b186a2011-09-19 16:00:46 -0700135 bool intersect(float l, float t, float r, float b) {
Romain Guy8f85e802011-12-14 19:23:32 -0800136 Rect tmp(l, t, r, b);
137 intersectWith(tmp);
Mathias Agopian83b186a2011-09-19 16:00:46 -0700138 if (!tmp.isEmpty()) {
139 set(tmp);
Romain Guy7ae7ac42010-06-25 13:46:18 -0700140 return true;
141 }
142 return false;
143 }
Romain Guybb9524b2010-06-22 18:56:38 -0700144
Romain Guy7ae7ac42010-06-25 13:46:18 -0700145 bool intersect(const Rect& r) {
146 return intersect(r.left, r.top, r.right, r.bottom);
147 }
Romain Guybb9524b2010-06-22 18:56:38 -0700148
Romain Guy2db5e992013-05-21 15:29:59 -0700149 inline bool contains(float l, float t, float r, float b) const {
Romain Guyec31f832011-12-13 18:39:19 -0800150 return l >= left && t >= top && r <= right && b <= bottom;
151 }
152
Romain Guy2db5e992013-05-21 15:29:59 -0700153 inline bool contains(const Rect& r) const {
Romain Guyec31f832011-12-13 18:39:19 -0800154 return contains(r.left, r.top, r.right, r.bottom);
155 }
156
Romain Guy079ba2c2010-07-16 14:12:24 -0700157 bool unionWith(const Rect& r) {
158 if (r.left < r.right && r.top < r.bottom) {
159 if (left < right && top < bottom) {
160 if (left > r.left) left = r.left;
161 if (top > r.top) top = r.top;
162 if (right < r.right) right = r.right;
163 if (bottom < r.bottom) bottom = r.bottom;
164 return true;
165 } else {
166 left = r.left;
167 top = r.top;
168 right = r.right;
169 bottom = r.bottom;
170 return true;
171 }
172 }
173 return false;
174 }
175
Romain Guy5b3b3522010-10-27 18:57:51 -0700176 void translate(float dx, float dy) {
177 left += dx;
178 right += dx;
179 top += dy;
180 bottom += dy;
181 }
182
Chris Craike4aa95e2014-05-08 13:57:05 -0700183 void inset(float delta) {
184 outset(-delta);
185 }
186
Chris Craikc3566d02013-02-04 16:16:33 -0800187 void outset(float delta) {
188 left -= delta;
189 top -= delta;
190 right += delta;
191 bottom += delta;
192 }
193
Chris Craik05f3d6e2014-06-02 16:27:04 -0700194 void outset(float xdelta, float ydelta) {
195 left -= xdelta;
196 top -= ydelta;
197 right += xdelta;
198 bottom += ydelta;
199 }
200
Chris Craik5e49b302013-07-30 19:05:20 -0700201 /**
Chris Craik32f05e32013-09-17 16:20:29 -0700202 * Similar to snapToPixelBoundaries, but estimates bounds conservatively to handle GL rounding
203 * errors.
Chris Craik5e49b302013-07-30 19:05:20 -0700204 *
Chris Craik32f05e32013-09-17 16:20:29 -0700205 * This function should be used whenever estimating the damage rect of geometry already mapped
206 * into layer space.
Chris Craik5e49b302013-07-30 19:05:20 -0700207 */
Chris Craik32f05e32013-09-17 16:20:29 -0700208 void snapGeometryToPixelBoundaries(bool snapOut) {
209 if (snapOut) {
210 /* For AA geometry with a ramp perimeter, don't snap by rounding - AA geometry will have
211 * a 0.5 pixel perimeter not accounted for in its bounds. Instead, snap by
212 * conservatively rounding out the bounds with floor/ceil.
213 *
214 * In order to avoid changing integer bounds with floor/ceil due to rounding errors
215 * inset the bounds first by the fudge factor. Very small fraction-of-a-pixel errors
216 * from this inset will only incur similarly small errors in output, due to transparency
217 * in extreme outside of the geometry.
218 */
Chris Craik564acf72014-01-02 16:46:18 -0800219 left = floorf(left + Vertex::GeometryFudgeFactor());
220 top = floorf(top + Vertex::GeometryFudgeFactor());
221 right = ceilf(right - Vertex::GeometryFudgeFactor());
222 bottom = ceilf(bottom - Vertex::GeometryFudgeFactor());
Chris Craik32f05e32013-09-17 16:20:29 -0700223 } else {
224 /* For other geometry, we do the regular rounding in order to snap, but also outset the
225 * bounds by a fudge factor. This ensures that ambiguous geometry (e.g. a non-AA Rect
226 * with top left at (0.5, 0.5)) will err on the side of a larger damage rect.
227 */
Chris Craik564acf72014-01-02 16:46:18 -0800228 left = floorf(left + 0.5f - Vertex::GeometryFudgeFactor());
229 top = floorf(top + 0.5f - Vertex::GeometryFudgeFactor());
230 right = floorf(right + 0.5f + Vertex::GeometryFudgeFactor());
231 bottom = floorf(bottom + 0.5f + Vertex::GeometryFudgeFactor());
Chris Craik32f05e32013-09-17 16:20:29 -0700232 }
Chris Craik5e49b302013-07-30 19:05:20 -0700233 }
234
Romain Guybf434112010-09-16 14:40:17 -0700235 void snapToPixelBoundaries() {
Romain Guyae88e5e2010-10-22 17:49:18 -0700236 left = floorf(left + 0.5f);
237 top = floorf(top + 0.5f);
238 right = floorf(right + 0.5f);
239 bottom = floorf(bottom + 0.5f);
Romain Guybf434112010-09-16 14:40:17 -0700240 }
241
Chris Craikf0a59072013-11-19 18:00:46 -0800242 void roundOut() {
243 left = floorf(left);
244 top = floorf(top);
245 right = ceilf(right);
246 bottom = ceilf(bottom);
247 }
248
Chris Craikc93e45c2014-07-16 10:15:56 -0700249 void expandToCoverVertex(float x, float y) {
Chris Craikdf72b632015-06-30 17:56:13 -0700250 left = std::min(left, x);
251 top = std::min(top, y);
252 right = std::max(right, x);
253 bottom = std::max(bottom, y);
Chris Craikc93e45c2014-07-16 10:15:56 -0700254 }
255
Chris Craik8820fd12015-03-03 14:20:47 -0800256 void expandToCoverRect(float otherLeft, float otherTop, float otherRight, float otherBottom) {
Chris Craikdf72b632015-06-30 17:56:13 -0700257 left = std::min(left, otherLeft);
258 top = std::min(top, otherTop);
259 right = std::max(right, otherRight);
260 bottom = std::max(bottom, otherBottom);
Chris Craik8820fd12015-03-03 14:20:47 -0800261 }
262
Rob Tsuk487a92c2015-01-06 13:22:54 -0800263 SkRect toSkRect() const {
264 return SkRect::MakeLTRB(left, top, right, bottom);
265 }
266
267 SkIRect toSkIRect() const {
268 return SkIRect::MakeLTRB(left, top, right, bottom);
269 }
270
Chris Craike84a2082014-12-22 14:28:49 -0800271 void dump(const char* label = nullptr) const {
Chris Craike4aa95e2014-05-08 13:57:05 -0700272 ALOGD("%s[l=%f t=%f r=%f b=%f]", label ? label : "Rect", left, top, right, bottom);
Romain Guy7ae7ac42010-06-25 13:46:18 -0700273 }
Romain Guybb9524b2010-06-22 18:56:38 -0700274
Romain Guya1d3c912011-12-13 14:55:06 -0800275private:
Romain Guy8f85e802011-12-14 19:23:32 -0800276 void intersectWith(Rect& tmp) const {
Chris Craikdf72b632015-06-30 17:56:13 -0700277 tmp.left = std::max(left, tmp.left);
278 tmp.top = std::max(top, tmp.top);
279 tmp.right = std::min(right, tmp.right);
280 tmp.bottom = std::min(bottom, tmp.bottom);
Romain Guy8f85e802011-12-14 19:23:32 -0800281 }
282
Romain Guya1d3c912011-12-13 14:55:06 -0800283 Rect intersectWith(float l, float t, float r, float b) const {
284 Rect tmp;
Chris Craikdf72b632015-06-30 17:56:13 -0700285 tmp.left = std::max(left, l);
286 tmp.top = std::max(top, t);
287 tmp.right = std::min(right, r);
288 tmp.bottom = std::min(bottom, b);
Romain Guya1d3c912011-12-13 14:55:06 -0800289 return tmp;
290 }
291
Mathias Agopian83b186a2011-09-19 16:00:46 -0700292}; // class Rect
Romain Guybb9524b2010-06-22 18:56:38 -0700293
Romain Guy9d5316e2010-06-24 19:30:36 -0700294}; // namespace uirenderer
Romain Guybb9524b2010-06-22 18:56:38 -0700295}; // namespace android
296
Romain Guy5b3b3522010-10-27 18:57:51 -0700297#endif // ANDROID_HWUI_RECT_H