blob: 96d302f53d5853e59725d41e977d8cc3d878708b [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
2 Copyright 2010 Google Inc.
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
18#ifndef GrRect_DEFINED
19#define GrRect_DEFINED
20
21#include "GrPoint.h"
22
23struct GrIRect {
24 int32_t fLeft, fTop, fRight, fBottom;
bsalomon@google.comd302f142011-03-03 13:54:13 +000025
reed@google.comac10a2d2010-12-22 21:39:39 +000026 GrIRect() {}
27 GrIRect(int32_t left, int32_t top, int32_t right, int32_t bottom) {
28 fLeft = left;
29 fTop = top;
30 fRight = right;
31 fBottom = bottom;
32 }
33
34 int32_t x() const { return fLeft; }
35 int32_t y() const { return fTop; }
36 int32_t width() const { return fRight - fLeft; }
37 int32_t height() const { return fBottom - fTop; }
38
39 bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; }
40 bool isInverted() const { return fLeft > fRight || fTop > fBottom; }
41
42 void setEmpty() { fLeft = fTop = fRight = fBottom = 0; }
43
44 void setXYWH(int32_t x, int32_t y, int32_t w, int32_t h) {
45 fLeft = x;
46 fTop = y;
47 fRight = x + w;
48 fBottom = y + h;
49 }
bsalomon@google.comd302f142011-03-03 13:54:13 +000050
reed@google.comac10a2d2010-12-22 21:39:39 +000051 void setLTRB(int32_t l, int32_t t, int32_t r, int32_t b) {
52 fLeft = l;
53 fTop = t;
54 fRight = r;
55 fBottom = b;
56 }
bsalomon@google.comd302f142011-03-03 13:54:13 +000057
reed@google.comac10a2d2010-12-22 21:39:39 +000058 /**
59 * Make the largest representable rectangle
reed@google.comac10a2d2010-12-22 21:39:39 +000060 */
61 void setLargest() {
62 fLeft = fTop = GR_Int32Min;
63 fRight = fBottom = GR_Int32Max;
64 }
bsalomon@google.comd302f142011-03-03 13:54:13 +000065
reed@google.comac10a2d2010-12-22 21:39:39 +000066 bool quickReject(int l, int t, int r, int b) const {
67 return l >= fRight || fLeft >= r || t >= fBottom || fTop >= b;
68 }
69
70 void unionWith(const GrIRect& r) {
71 if (fLeft > r.fLeft) fLeft = r.fLeft;
72 if (fTop > r.fTop) fTop = r.fTop;
73 if (fRight < r.fRight) fRight = r.fRight;
74 if (fBottom < r.fBottom) fBottom = r.fBottom;
75 }
76
bsalomon@google.comd302f142011-03-03 13:54:13 +000077 /**
78 * Sets this rect to the intersection with a clip rect. If there is no
79 * intersection then this rect will be made empty.
80 */
81 void intersectWith(const GrIRect& clipRect) {
82 if (fRight < clipRect.fLeft ||
83 fLeft > clipRect.fRight ||
84 fBottom < clipRect.fTop ||
85 fTop > clipRect.fBottom) {
86 this->setEmpty();
87 } else {
88 fLeft = GrMax(fLeft, clipRect.fLeft);
89 fRight = GrMin(fRight, clipRect.fRight);
90 fTop = GrMax(fTop, clipRect.fTop);
91 fBottom = GrMin(fBottom, clipRect.fBottom);
92 }
93 }
94
reed@google.comac10a2d2010-12-22 21:39:39 +000095 friend bool operator==(const GrIRect& a, const GrIRect& b) {
96 return 0 == memcmp(&a, &b, sizeof(a));
97 }
bsalomon@google.comd302f142011-03-03 13:54:13 +000098
reed@google.comac10a2d2010-12-22 21:39:39 +000099 friend bool operator!=(const GrIRect& a, const GrIRect& b) {
100 return 0 != memcmp(&a, &b, sizeof(a));
101 }
102
103 bool equalsLTRB(int l, int t, int r, int b) const {
104 return fLeft == l && fTop == t &&
105 fRight == r && fBottom == b;
106 }
107 bool equalsXYWH(int x, int y, int w, int h) const {
108 return fLeft == x && fTop == y &&
109 this->width() == w && this->height() == h;
110 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000111
reed@google.comac10a2d2010-12-22 21:39:39 +0000112 bool contains(const GrIRect& r) const {
113 return fLeft <= r.fLeft &&
114 fRight >= r.fRight &&
115 fTop <= r.fTop &&
116 fBottom >= r.fBottom;
117 }
118};
119
120struct GrIRect16 {
121 int16_t fLeft, fTop, fRight, fBottom;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000122
reed@google.comac10a2d2010-12-22 21:39:39 +0000123 int width() const { return fRight - fLeft; }
124 int height() const { return fBottom - fTop; }
125 int area() const { return this->width() * this->height(); }
126 bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000127
reed@google.comac10a2d2010-12-22 21:39:39 +0000128 void set(const GrIRect& r) {
129 fLeft = GrToS16(r.fLeft);
130 fTop = GrToS16(r.fTop);
131 fRight = GrToS16(r.fRight);
132 fBottom = GrToS16(r.fBottom);
133 }
134};
135
bsalomon@google.comd302f142011-03-03 13:54:13 +0000136/**
reed@google.comac10a2d2010-12-22 21:39:39 +0000137 * 2D Rect struct
138 */
139struct GrRect {
140 GrScalar fLeft, fTop, fRight, fBottom;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000141
reed@google.comac10a2d2010-12-22 21:39:39 +0000142 /**
143 * Uninitialized rectangle.
144 */
145 GrRect() {}
146
147 /**
148 * Initialize a rectangle to a point.
149 * @param pt the point used to initialize the rectanglee.
150 */
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000151 explicit GrRect(const GrPoint& pt) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000152 setToPoint(pt);
153 }
154
155 GrRect(GrScalar left, GrScalar top, GrScalar right, GrScalar bottom) {
156 fLeft = left;
157 fTop = top;
158 fRight = right;
159 fBottom = bottom;
160 }
161
162 explicit GrRect(const GrIRect& src) {
163 fLeft = GrIntToScalar(src.fLeft);
164 fTop = GrIntToScalar(src.fTop);
165 fRight = GrIntToScalar(src.fRight);
166 fBottom = GrIntToScalar(src.fBottom);
167 }
168
169 GrScalar x() const { return fLeft; }
170 GrScalar y() const { return fTop; }
171 GrScalar width() const { return fRight - fLeft; }
172 GrScalar height() const { return fBottom - fTop; }
173
174 GrScalar left() const { return fLeft; }
175 GrScalar top() const { return fTop; }
176 GrScalar right() const { return fRight; }
177 GrScalar bottom() const { return fBottom; }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000178
reed@google.comac10a2d2010-12-22 21:39:39 +0000179 GrScalar diagonalLengthSqd() const {
180 GrScalar w = width();
181 GrScalar h = height();
182 return GrMul(w, w) + GrMul(h, h);
183 }
184
185 GrScalar diagonalLength() const {
186 // TODO: fixed point sqrt
187 return GrFloatToScalar(sqrtf(GrScalarToFloat(diagonalLengthSqd())));
188 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000189
reed@google.comac10a2d2010-12-22 21:39:39 +0000190 /**
191 * Returns true if the width or height is <= 0
192 */
193 bool isEmpty() const {
194 return fLeft >= fRight || fTop >= fBottom;
195 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000196
reed@google.comac10a2d2010-12-22 21:39:39 +0000197 void setEmpty() {
198 fLeft = fTop = fRight = fBottom = 0;
199 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000200
reed@google.comac10a2d2010-12-22 21:39:39 +0000201 /**
202 * returns true if the rectangle is inverted either in x or y
203 */
204 bool isInverted() const {
205 return (fLeft > fRight) || (fTop > fBottom);
206 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000207
208 bool contains(const GrPoint& point) const {
209 return point.fX >= fLeft && point.fX < fRight &&
210 point.fY >= fTop && point.fY < fBottom;
211 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000212
reed@google.comac10a2d2010-12-22 21:39:39 +0000213 /**
214 * Initialize a rectangle to a point.
215 * @param pt the point used to initialize the rectangle.
216 */
217 void setToPoint(const GrPoint& pt) {
218 fLeft = pt.fX;
219 fTop = pt.fY;
220 fRight = pt.fX;
221 fBottom = pt.fY;
222 }
223
224 void set(const GrIRect& r) {
225 fLeft = GrIntToScalar(r.fLeft);
226 fTop = GrIntToScalar(r.fTop);
227 fRight = GrIntToScalar(r.fRight);
228 fBottom = GrIntToScalar(r.fBottom);
229 }
230
231 void roundOut(GrIRect* r) const {
232 r->setLTRB(GrScalarFloorToInt(fLeft),
233 GrScalarFloorToInt(fTop),
234 GrScalarCeilToInt(fRight),
235 GrScalarCeilToInt(fBottom));
236 }
237
238 /**
239 * Set the rect to the union of the array of points. If the array is empty
240 * the rect will be empty [0,0,0,0]
241 */
242 void setBounds(const GrPoint pts[], int count);
243
244 /**
245 * Make the largest representable rectangle
bsalomon@google.comd302f142011-03-03 13:54:13 +0000246 * Set the rect to fLeft = fTop = GR_ScalarMin and
reed@google.comac10a2d2010-12-22 21:39:39 +0000247 * fRight = fBottom = GR_ScalarMax.
248 */
249 void setLargest() {
250 fLeft = fTop = GR_ScalarMin;
251 fRight = fBottom = GR_ScalarMax;
252 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000253
reed@google.comac10a2d2010-12-22 21:39:39 +0000254 /**
bsalomon@google.comd302f142011-03-03 13:54:13 +0000255 Set the rect to fLeft = fTop = GR_ScalarMax and
reed@google.comac10a2d2010-12-22 21:39:39 +0000256 fRight = fBottom = GR_ScalarMin.
257 Useful for initializing a bounding rectangle.
258 */
259 void setLargestInverted() {
260 fLeft = fTop = GR_ScalarMax;
261 fRight = fBottom = GR_ScalarMin;
262 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000263
264 void setLTRB(GrScalar left,
265 GrScalar top,
266 GrScalar right,
reed@google.comac10a2d2010-12-22 21:39:39 +0000267 GrScalar bottom) {
268 fLeft = left;
269 fTop = top;
270 fRight = right;
271 fBottom = bottom;
272 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000273
reed@google.comac10a2d2010-12-22 21:39:39 +0000274 void setXYWH(GrScalar x, GrScalar y, GrScalar width, GrScalar height) {
275 fLeft = x;
276 fTop = y;
277 fRight = x + width;
278 fBottom = y + height;
279 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000280
reed@google.comac10a2d2010-12-22 21:39:39 +0000281 /**
282 Expand the edges of the rectangle to include a point.
283 Useful for constructing a bounding rectangle.
284 @param pt the point used to grow the rectangle.
285 */
286 void growToInclude(const GrPoint& pt) {
287 fLeft = GrMin(pt.fX, fLeft);
288 fRight = GrMax(pt.fX, fRight);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000289
reed@google.comac10a2d2010-12-22 21:39:39 +0000290 fTop = GrMin(pt.fY, fTop);
291 fBottom = GrMax(pt.fY, fBottom);
292 }
293
294 /**
bsalomon@google.comd302f142011-03-03 13:54:13 +0000295 * Grows a rect to include another rect.
296 * @param rect the rect to include
297 */
298 void growToInclude(const GrRect& rect) {
299 GrAssert(!rect.isEmpty());
300 fLeft = GrMin(rect.fLeft, fLeft);
301 fRight = GrMax(rect.fRight, fRight);
302
303 fTop = GrMin(rect.fTop, fTop);
304 fBottom = GrMax(rect.fBottom, fBottom);
305 }
306
307 /**
308 * Sets this rect to the intersection with a clip rect. If there is no
309 * intersection then this rect will be made empty.
310 */
311 void intersectWith(const GrRect& clipRect) {
312 if (fRight < clipRect.fLeft ||
313 fLeft > clipRect.fRight ||
314 fBottom < clipRect.fTop ||
315 fTop > clipRect.fBottom) {
316 this->setEmpty();
317 } else {
318 fLeft = GrMax(fLeft, clipRect.fLeft);
319 fRight = GrMin(fRight, clipRect.fRight);
320 fTop = GrMax(fTop, clipRect.fTop);
321 fBottom = GrMin(fBottom, clipRect.fBottom);
322 }
323 }
324
325 /**
reed@google.comac10a2d2010-12-22 21:39:39 +0000326 * Assigns 4 sequential points in order to construct a counter-clockwise
327 * triangle fan, given the corners of this rect. Returns the address of
328 * the next point, treating pts as an array.
329 */
330 GrPoint* setRectFan(GrPoint pts[4]) const {
331 pts->setRectFan(fLeft, fTop, fRight, fBottom);
332 return pts + 4;
333 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000334
335 bool operator ==(const GrRect& r) const {
336 return fLeft == r.fLeft &&
337 fTop == r.fTop &&
338 fRight == r.fRight &&
339 fBottom == r.fBottom;
340 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000341};
342
343#endif
344