Rect.h revision f0a590781b2c3e34132b2011d3956135add73ae0
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 26namespace android { 27namespace 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 37class Rect { 38public: 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 50 inline Rect(): 51 left(0), 52 top(0), 53 right(0), 54 bottom(0) { 55 } 56 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 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 79 inline void clear() { 80 left = top = right = bottom = 0.0f; 81 } 82 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 89 inline void setEmpty() { 90 left = top = right = bottom = 0.0f; 91 } 92 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 100 inline void set(const Rect& r) { 101 set(r.left, r.top, r.right, r.bottom); 102 } 103 104 inline float getWidth() const { 105 return right - left; 106 } 107 108 inline float getHeight() const { 109 return bottom - top; 110 } 111 112 bool intersects(float l, float t, float r, float b) const { 113 return !intersectWith(l, t, r, b).isEmpty(); 114 } 115 116 bool intersects(const Rect& r) const { 117 return intersects(r.left, r.top, r.right, r.bottom); 118 } 119 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 130 bool intersect(const Rect& r) { 131 return intersect(r.left, r.top, r.right, r.bottom); 132 } 133 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 138 inline bool contains(const Rect& r) const { 139 return contains(r.left, r.top, r.right, r.bottom); 140 } 141 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 161 void translate(float dx, float dy) { 162 left += dx; 163 right += dx; 164 top += dy; 165 bottom += dy; 166 } 167 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 */ 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 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 216 void roundOut() { 217 left = floorf(left); 218 top = floorf(top); 219 right = ceilf(right); 220 bottom = ceilf(bottom); 221 } 222 223 void dump() const { 224 ALOGD("Rect[l=%f t=%f r=%f b=%f]", left, top, right, bottom); 225 } 226 227private: 228 void intersectWith(Rect& tmp) const { 229 tmp.left = fmaxf(left, tmp.left); 230 tmp.top = fmaxf(top, tmp.top); 231 tmp.right = fminf(right, tmp.right); 232 tmp.bottom = fminf(bottom, tmp.bottom); 233 } 234 235 Rect intersectWith(float l, float t, float r, float b) const { 236 Rect tmp; 237 tmp.left = fmaxf(left, l); 238 tmp.top = fmaxf(top, t); 239 tmp.right = fminf(right, r); 240 tmp.bottom = fminf(bottom, b); 241 return tmp; 242 } 243 244}; // class Rect 245 246}; // namespace uirenderer 247}; // namespace android 248 249#endif // ANDROID_HWUI_RECT_H 250