1 :
2 : /*
3 : * Copyright 2006 The Android Open Source Project
4 : *
5 : * Use of this source code is governed by a BSD-style license that can be
6 : * found in the LICENSE file.
7 : */
8 :
9 :
10 : #ifndef SkRect_DEFINED
11 : #define SkRect_DEFINED
12 :
13 : #include "SkPoint.h"
14 : #include "SkSize.h"
15 :
16 : /** \struct SkIRect
17 :
18 : SkIRect holds four 32 bit integer coordinates for a rectangle
19 : */
20 : struct SK_API SkIRect {
21 : int32_t fLeft, fTop, fRight, fBottom;
22 :
23 : static SkIRect MakeEmpty() {
24 : SkIRect r;
25 : r.setEmpty();
26 : return r;
27 : }
28 :
29 : static SkIRect MakeWH(int32_t w, int32_t h) {
30 : SkIRect r;
31 : r.set(0, 0, w, h);
32 : return r;
33 : }
34 :
35 : static SkIRect MakeSize(const SkISize& size) {
36 : SkIRect r;
37 : r.set(0, 0, size.width(), size.height());
38 : return r;
39 : }
40 :
41 : static SkIRect MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b) {
42 : SkIRect rect;
43 : rect.set(l, t, r, b);
44 : return rect;
45 : }
46 :
47 0 : static SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h) {
48 : SkIRect r;
49 0 : r.set(x, y, x + w, y + h);
50 : return r;
51 : }
52 :
53 : int left() const { return fLeft; }
54 : int top() const { return fTop; }
55 : int right() const { return fRight; }
56 : int bottom() const { return fBottom; }
57 :
58 : /** return the left edge of the rect */
59 : int x() const { return fLeft; }
60 : /** return the top edge of the rect */
61 : int y() const { return fTop; }
62 : /**
63 : * Returns the rectangle's width. This does not check for a valid rect
64 : * (i.e. left <= right) so the result may be negative.
65 : */
66 : int width() const { return fRight - fLeft; }
67 :
68 : /**
69 : * Returns the rectangle's height. This does not check for a valid rect
70 : * (i.e. top <= bottom) so the result may be negative.
71 : */
72 : int height() const { return fBottom - fTop; }
73 :
74 : /**
75 : * Return true if the rectangle's width or height are <= 0
76 : */
77 : bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; }
78 :
79 : friend bool operator==(const SkIRect& a, const SkIRect& b) {
80 : return !memcmp(&a, &b, sizeof(a));
81 : }
82 :
83 : friend bool operator!=(const SkIRect& a, const SkIRect& b) {
84 : return !(a == b);
85 : }
86 :
87 : bool is16Bit() const {
88 : return SkIsS16(fLeft) && SkIsS16(fTop) &&
89 : SkIsS16(fRight) && SkIsS16(fBottom);
90 : }
91 :
92 : /** Set the rectangle to (0,0,0,0)
93 : */
94 : void setEmpty() { memset(this, 0, sizeof(*this)); }
95 :
96 0 : void set(int32_t left, int32_t top, int32_t right, int32_t bottom) {
97 0 : fLeft = left;
98 0 : fTop = top;
99 0 : fRight = right;
100 0 : fBottom = bottom;
101 0 : }
102 : // alias for set(l, t, r, b)
103 : void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom) {
104 : this->set(left, top, right, bottom);
105 : }
106 :
107 : void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height) {
108 : fLeft = x;
109 : fTop = y;
110 : fRight = x + width;
111 : fBottom = y + height;
112 : }
113 :
114 : /**
115 : * Make the largest representable rectangle
116 : */
117 : void setLargest() {
118 : fLeft = fTop = SK_MinS32;
119 : fRight = fBottom = SK_MaxS32;
120 : }
121 :
122 : /**
123 : * Make the largest representable rectangle, but inverted (e.g. fLeft will
124 : * be max 32bit and right will be min 32bit).
125 : */
126 : void setLargestInverted() {
127 : fLeft = fTop = SK_MaxS32;
128 : fRight = fBottom = SK_MinS32;
129 : }
130 :
131 : /** Offset set the rectangle by adding dx to its left and right,
132 : and adding dy to its top and bottom.
133 : */
134 : void offset(int32_t dx, int32_t dy) {
135 : fLeft += dx;
136 : fTop += dy;
137 : fRight += dx;
138 : fBottom += dy;
139 : }
140 :
141 : void offset(const SkIPoint& delta) {
142 : this->offset(delta.fX, delta.fY);
143 : }
144 :
145 : /** Inset the rectangle by (dx,dy). If dx is positive, then the sides are moved inwards,
146 : making the rectangle narrower. If dx is negative, then the sides are moved outwards,
147 : making the rectangle wider. The same hods true for dy and the top and bottom.
148 : */
149 : void inset(int32_t dx, int32_t dy) {
150 : fLeft += dx;
151 : fTop += dy;
152 : fRight -= dx;
153 : fBottom -= dy;
154 : }
155 :
156 : bool quickReject(int l, int t, int r, int b) const {
157 : return l >= fRight || fLeft >= r || t >= fBottom || fTop >= b;
158 : }
159 :
160 : /** Returns true if (x,y) is inside the rectangle and the rectangle is not
161 : empty. The left and top are considered to be inside, while the right
162 : and bottom are not. Thus for the rectangle (0, 0, 5, 10), the
163 : points (0,0) and (0,9) are inside, while (-1,0) and (5,9) are not.
164 : */
165 : bool contains(int32_t x, int32_t y) const {
166 : return (unsigned)(x - fLeft) < (unsigned)(fRight - fLeft) &&
167 : (unsigned)(y - fTop) < (unsigned)(fBottom - fTop);
168 : }
169 :
170 : /** Returns true if the 4 specified sides of a rectangle are inside or equal to this rectangle.
171 : If either rectangle is empty, contains() returns false.
172 : */
173 : bool contains(int32_t left, int32_t top, int32_t right, int32_t bottom) const {
174 : return left < right && top < bottom && !this->isEmpty() && // check for empties
175 : fLeft <= left && fTop <= top &&
176 : fRight >= right && fBottom >= bottom;
177 : }
178 :
179 : /** Returns true if the specified rectangle r is inside or equal to this rectangle.
180 : */
181 : bool contains(const SkIRect& r) const {
182 : return !r.isEmpty() && !this->isEmpty() && // check for empties
183 : fLeft <= r.fLeft && fTop <= r.fTop &&
184 : fRight >= r.fRight && fBottom >= r.fBottom;
185 : }
186 :
187 : /** Return true if this rectangle contains the specified rectangle.
188 : For speed, this method does not check if either this or the specified
189 : rectangles are empty, and if either is, its return value is undefined.
190 : In the debugging build however, we assert that both this and the
191 : specified rectangles are non-empty.
192 : */
193 : bool containsNoEmptyCheck(int32_t left, int32_t top,
194 : int32_t right, int32_t bottom) const {
195 : SkASSERT(fLeft < fRight && fTop < fBottom);
196 : SkASSERT(left < right && top < bottom);
197 :
198 : return fLeft <= left && fTop <= top &&
199 : fRight >= right && fBottom >= bottom;
200 : }
201 :
202 : /** If r intersects this rectangle, return true and set this rectangle to that
203 : intersection, otherwise return false and do not change this rectangle.
204 : If either rectangle is empty, do nothing and return false.
205 : */
206 : bool intersect(const SkIRect& r) {
207 : SkASSERT(&r);
208 : return this->intersect(r.fLeft, r.fTop, r.fRight, r.fBottom);
209 : }
210 :
211 : /** If rectangles a and b intersect, return true and set this rectangle to
212 : that intersection, otherwise return false and do not change this
213 : rectangle. If either rectangle is empty, do nothing and return false.
214 : */
215 : bool intersect(const SkIRect& a, const SkIRect& b) {
216 : SkASSERT(&a && &b);
217 :
218 : if (!a.isEmpty() && !b.isEmpty() &&
219 : a.fLeft < b.fRight && b.fLeft < a.fRight &&
220 : a.fTop < b.fBottom && b.fTop < a.fBottom) {
221 : fLeft = SkMax32(a.fLeft, b.fLeft);
222 : fTop = SkMax32(a.fTop, b.fTop);
223 : fRight = SkMin32(a.fRight, b.fRight);
224 : fBottom = SkMin32(a.fBottom, b.fBottom);
225 : return true;
226 : }
227 : return false;
228 : }
229 :
230 : /** If rectangles a and b intersect, return true and set this rectangle to
231 : that intersection, otherwise return false and do not change this
232 : rectangle. For speed, no check to see if a or b are empty is performed.
233 : If either is, then the return result is undefined. In the debug build,
234 : we assert that both rectangles are non-empty.
235 : */
236 : bool intersectNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
237 : SkASSERT(&a && &b);
238 : SkASSERT(!a.isEmpty() && !b.isEmpty());
239 :
240 : if (a.fLeft < b.fRight && b.fLeft < a.fRight &&
241 : a.fTop < b.fBottom && b.fTop < a.fBottom) {
242 : fLeft = SkMax32(a.fLeft, b.fLeft);
243 : fTop = SkMax32(a.fTop, b.fTop);
244 : fRight = SkMin32(a.fRight, b.fRight);
245 : fBottom = SkMin32(a.fBottom, b.fBottom);
246 : return true;
247 : }
248 : return false;
249 : }
250 :
251 : /** If the rectangle specified by left,top,right,bottom intersects this rectangle,
252 : return true and set this rectangle to that intersection,
253 : otherwise return false and do not change this rectangle.
254 : If either rectangle is empty, do nothing and return false.
255 : */
256 : bool intersect(int32_t left, int32_t top, int32_t right, int32_t bottom) {
257 : if (left < right && top < bottom && !this->isEmpty() &&
258 : fLeft < right && left < fRight && fTop < bottom && top < fBottom) {
259 : if (fLeft < left) fLeft = left;
260 : if (fTop < top) fTop = top;
261 : if (fRight > right) fRight = right;
262 : if (fBottom > bottom) fBottom = bottom;
263 : return true;
264 : }
265 : return false;
266 : }
267 :
268 : /** Returns true if a and b are not empty, and they intersect
269 : */
270 : static bool Intersects(const SkIRect& a, const SkIRect& b) {
271 : return !a.isEmpty() && !b.isEmpty() && // check for empties
272 : a.fLeft < b.fRight && b.fLeft < a.fRight &&
273 : a.fTop < b.fBottom && b.fTop < a.fBottom;
274 : }
275 :
276 : /** Update this rectangle to enclose itself and the specified rectangle.
277 : If this rectangle is empty, just set it to the specified rectangle. If the specified
278 : rectangle is empty, do nothing.
279 : */
280 : void join(int32_t left, int32_t top, int32_t right, int32_t bottom);
281 :
282 : /** Update this rectangle to enclose itself and the specified rectangle.
283 : If this rectangle is empty, just set it to the specified rectangle. If the specified
284 : rectangle is empty, do nothing.
285 : */
286 : void join(const SkIRect& r) {
287 : this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
288 : }
289 :
290 : /** Swap top/bottom or left/right if there are flipped.
291 : This can be called if the edges are computed separately,
292 : and may have crossed over each other.
293 : When this returns, left <= right && top <= bottom
294 : */
295 : void sort();
296 :
297 : static const SkIRect& EmptyIRect() {
298 : static const SkIRect gEmpty = { 0, 0, 0, 0 };
299 : return gEmpty;
300 : }
301 : };
302 :
303 : /** \struct SkRect
304 : */
305 : struct SK_API SkRect {
306 : SkScalar fLeft, fTop, fRight, fBottom;
307 :
308 : static SkRect MakeEmpty() {
309 : SkRect r;
310 : r.setEmpty();
311 : return r;
312 : }
313 :
314 0 : static SkRect MakeWH(SkScalar w, SkScalar h) {
315 : SkRect r;
316 0 : r.set(0, 0, w, h);
317 : return r;
318 : }
319 :
320 : static SkRect MakeSize(const SkSize& size) {
321 : SkRect r;
322 : r.set(0, 0, size.width(), size.height());
323 : return r;
324 : }
325 :
326 : static SkRect MakeLTRB(SkScalar l, SkScalar t, SkScalar r, SkScalar b) {
327 : SkRect rect;
328 : rect.set(l, t, r, b);
329 : return rect;
330 : }
331 :
332 0 : static SkRect MakeXYWH(SkScalar x, SkScalar y, SkScalar w, SkScalar h) {
333 : SkRect r;
334 0 : r.set(x, y, x + w, y + h);
335 : return r;
336 : }
337 :
338 : /**
339 : * Return true if the rectangle's width or height are <= 0
340 : */
341 : bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; }
342 :
343 : /**
344 : * Returns true iff all values in the rect are finite. If any are
345 : * infinite or NaN (or SK_FixedNaN when SkScalar is fixed) then this
346 : * returns false.
347 : */
348 : bool isFinite() const {
349 : #ifdef SK_SCALAR_IS_FLOAT
350 : // x * 0 will be NaN iff x is infinity or NaN.
351 : // a + b will be NaN iff either a or b is NaN.
352 : float value = fLeft * 0 + fTop * 0 + fRight * 0 + fBottom * 0;
353 :
354 : // value is either NaN or it is finite (zero).
355 : // value==value will be true iff value is not NaN
356 : return value == value;
357 : #else
358 : // use bit-or for speed, since we don't care about short-circuting the
359 : // tests, and we expect the common case will be that we need to check all.
360 : int isNaN = (SK_FixedNaN == fLeft) | (SK_FixedNaN == fTop) |
361 : (SK_FixedNaN == fRight) | (SK_FixedNaN == fBottom);
362 : return !isNaN;
363 : #endif
364 : }
365 :
366 : SkScalar left() const { return fLeft; }
367 : SkScalar top() const { return fTop; }
368 : SkScalar right() const { return fRight; }
369 : SkScalar bottom() const { return fBottom; }
370 : SkScalar width() const { return fRight - fLeft; }
371 : SkScalar height() const { return fBottom - fTop; }
372 : SkScalar centerX() const { return SkScalarHalf(fLeft + fRight); }
373 : SkScalar centerY() const { return SkScalarHalf(fTop + fBottom); }
374 :
375 : friend bool operator==(const SkRect& a, const SkRect& b) {
376 : return 0 == memcmp(&a, &b, sizeof(a));
377 : }
378 :
379 : friend bool operator!=(const SkRect& a, const SkRect& b) {
380 : return 0 != memcmp(&a, &b, sizeof(a));
381 : }
382 :
383 : /** return the 4 points that enclose the rectangle
384 : */
385 : void toQuad(SkPoint quad[4]) const;
386 :
387 : /** Set this rectangle to the empty rectangle (0,0,0,0)
388 : */
389 : void setEmpty() { memset(this, 0, sizeof(*this)); }
390 :
391 : void set(const SkIRect& src) {
392 : fLeft = SkIntToScalar(src.fLeft);
393 : fTop = SkIntToScalar(src.fTop);
394 : fRight = SkIntToScalar(src.fRight);
395 : fBottom = SkIntToScalar(src.fBottom);
396 : }
397 :
398 0 : void set(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
399 0 : fLeft = left;
400 0 : fTop = top;
401 0 : fRight = right;
402 0 : fBottom = bottom;
403 0 : }
404 : // alias for set(l, t, r, b)
405 : void setLTRB(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
406 : this->set(left, top, right, bottom);
407 : }
408 :
409 : /** Initialize the rect with the 4 specified integers. The routine handles
410 : converting them to scalars (by calling SkIntToScalar)
411 : */
412 : void iset(int left, int top, int right, int bottom) {
413 : fLeft = SkIntToScalar(left);
414 : fTop = SkIntToScalar(top);
415 : fRight = SkIntToScalar(right);
416 : fBottom = SkIntToScalar(bottom);
417 : }
418 :
419 : /** Set this rectangle to be the bounds of the array of points.
420 : If the array is empty (count == 0), then set this rectangle
421 : to the empty rectangle (0,0,0,0)
422 : */
423 : void set(const SkPoint pts[], int count);
424 :
425 : // alias for set(pts, count)
426 : void setBounds(const SkPoint pts[], int count) {
427 : this->set(pts, count);
428 : }
429 :
430 : void setXYWH(SkScalar x, SkScalar y, SkScalar width, SkScalar height) {
431 : fLeft = x;
432 : fTop = y;
433 : fRight = x + width;
434 : fBottom = y + height;
435 : }
436 :
437 : /**
438 : * Make the largest representable rectangle
439 : */
440 : void setLargest() {
441 : fLeft = fTop = SK_ScalarMin;
442 : fRight = fBottom = SK_ScalarMax;
443 : }
444 :
445 : /**
446 : * Make the largest representable rectangle, but inverted (e.g. fLeft will
447 : * be max and right will be min).
448 : */
449 : void setLargestInverted() {
450 : fLeft = fTop = SK_ScalarMax;
451 : fRight = fBottom = SK_ScalarMin;
452 : }
453 :
454 : /** Offset set the rectangle by adding dx to its left and right,
455 : and adding dy to its top and bottom.
456 : */
457 : void offset(SkScalar dx, SkScalar dy) {
458 : fLeft += dx;
459 : fTop += dy;
460 : fRight += dx;
461 : fBottom += dy;
462 : }
463 :
464 : void offset(const SkPoint& delta) {
465 : this->offset(delta.fX, delta.fY);
466 : }
467 :
468 : /** Inset the rectangle by (dx,dy). If dx is positive, then the sides are
469 : moved inwards, making the rectangle narrower. If dx is negative, then
470 : the sides are moved outwards, making the rectangle wider. The same holds
471 : true for dy and the top and bottom.
472 : */
473 : void inset(SkScalar dx, SkScalar dy) {
474 : fLeft += dx;
475 : fTop += dy;
476 : fRight -= dx;
477 : fBottom -= dy;
478 : }
479 :
480 : /** Outset the rectangle by (dx,dy). If dx is positive, then the sides are
481 : moved outwards, making the rectangle wider. If dx is negative, then the
482 : sides are moved inwards, making the rectangle narrower. The same hods
483 : true for dy and the top and bottom.
484 : */
485 : void outset(SkScalar dx, SkScalar dy) { this->inset(-dx, -dy); }
486 :
487 : /** If this rectangle intersects r, return true and set this rectangle to that
488 : intersection, otherwise return false and do not change this rectangle.
489 : If either rectangle is empty, do nothing and return false.
490 : */
491 : bool intersect(const SkRect& r);
492 :
493 : /** If this rectangle intersects the rectangle specified by left, top, right, bottom,
494 : return true and set this rectangle to that intersection, otherwise return false
495 : and do not change this rectangle.
496 : If either rectangle is empty, do nothing and return false.
497 : */
498 : bool intersect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
499 :
500 : /**
501 : * Return true if this rectangle is not empty, and the specified sides of
502 : * a rectangle are not empty, and they intersect.
503 : */
504 : bool intersects(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) const {
505 : return // first check that both are not empty
506 : left < right && top < bottom &&
507 : fLeft < fRight && fTop < fBottom &&
508 : // now check for intersection
509 : fLeft < right && left < fRight &&
510 : fTop < bottom && top < fBottom;
511 : }
512 :
513 : /** If rectangles a and b intersect, return true and set this rectangle to
514 : * that intersection, otherwise return false and do not change this
515 : * rectangle. If either rectangle is empty, do nothing and return false.
516 : */
517 : bool intersect(const SkRect& a, const SkRect& b);
518 :
519 : /**
520 : * Return true if rectangles a and b are not empty and intersect.
521 : */
522 : static bool Intersects(const SkRect& a, const SkRect& b) {
523 : return !a.isEmpty() && !b.isEmpty() &&
524 : a.fLeft < b.fRight && b.fLeft < a.fRight &&
525 : a.fTop < b.fBottom && b.fTop < a.fBottom;
526 : }
527 :
528 : /**
529 : * Update this rectangle to enclose itself and the specified rectangle.
530 : * If this rectangle is empty, just set it to the specified rectangle.
531 : * If the specified rectangle is empty, do nothing.
532 : */
533 : void join(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);
534 :
535 : /** Update this rectangle to enclose itself and the specified rectangle.
536 : If this rectangle is empty, just set it to the specified rectangle. If the specified
537 : rectangle is empty, do nothing.
538 : */
539 : void join(const SkRect& r) {
540 : this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
541 : }
542 : // alias for join()
543 : void growToInclude(const SkRect& r) { this->join(r); }
544 :
545 : /**
546 : * Grow the rect to include the specified (x,y). After this call, the
547 : * following will be true: fLeft <= x <= fRight && fTop <= y <= fBottom.
548 : *
549 : * This is close, but not quite the same contract as contains(), since
550 : * contains() treats the left and top different from the right and bottom.
551 : * contains(x,y) -> fLeft <= x < fRight && fTop <= y < fBottom. Also note
552 : * that contains(x,y) always returns false if the rect is empty.
553 : */
554 : void growToInclude(SkScalar x, SkScalar y) {
555 : fLeft = SkMinScalar(x, fLeft);
556 : fRight = SkMaxScalar(x, fRight);
557 : fTop = SkMinScalar(y, fTop);
558 : fBottom = SkMaxScalar(y, fBottom);
559 : }
560 :
561 : /**
562 : * Returns true if (p.fX,p.fY) is inside the rectangle, and the rectangle
563 : * is not empty.
564 : *
565 : * Contains treats the left and top differently from the right and bottom.
566 : * The left and top coordinates of the rectangle are themselves considered
567 : * to be inside, while the right and bottom are not. Thus for the rectangle
568 : * {0, 0, 5, 10}, (0,0) is contained, but (0,10), (5,0) and (5,10) are not.
569 : */
570 : bool contains(const SkPoint& p) const {
571 : return !this->isEmpty() &&
572 : fLeft <= p.fX && p.fX < fRight && fTop <= p.fY && p.fY < fBottom;
573 : }
574 :
575 : /**
576 : * Returns true if (x,y) is inside the rectangle, and the rectangle
577 : * is not empty.
578 : *
579 : * Contains treats the left and top differently from the right and bottom.
580 : * The left and top coordinates of the rectangle are themselves considered
581 : * to be inside, while the right and bottom are not. Thus for the rectangle
582 : * {0, 0, 5, 10}, (0,0) is contained, but (0,10), (5,0) and (5,10) are not.
583 : */
584 : bool contains(SkScalar x, SkScalar y) const {
585 : return !this->isEmpty() &&
586 : fLeft <= x && x < fRight && fTop <= y && y < fBottom;
587 : }
588 :
589 : /**
590 : * Return true if this rectangle contains r, and if both rectangles are
591 : * not empty.
592 : */
593 : bool contains(const SkRect& r) const {
594 : return !r.isEmpty() && !this->isEmpty() &&
595 : fLeft <= r.fLeft && fTop <= r.fTop &&
596 : fRight >= r.fRight && fBottom >= r.fBottom;
597 : }
598 :
599 : /**
600 : * Set the dst rectangle by rounding this rectangle's coordinates to their
601 : * nearest integer values using SkScalarRound.
602 : */
603 : void round(SkIRect* dst) const {
604 : SkASSERT(dst);
605 : dst->set(SkScalarRound(fLeft), SkScalarRound(fTop),
606 : SkScalarRound(fRight), SkScalarRound(fBottom));
607 : }
608 :
609 : /**
610 : * Set the dst rectangle by rounding "out" this rectangle, choosing the
611 : * SkScalarFloor of top and left, and the SkScalarCeil of right and bottom.
612 : */
613 : void roundOut(SkIRect* dst) const {
614 : SkASSERT(dst);
615 : dst->set(SkScalarFloor(fLeft), SkScalarFloor(fTop),
616 : SkScalarCeil(fRight), SkScalarCeil(fBottom));
617 : }
618 :
619 : /**
620 : * Expand this rectangle by rounding its coordinates "out", choosing the
621 : * floor of top and left, and the ceil of right and bottom. If this rect
622 : * is already on integer coordinates, then it will be unchanged.
623 : */
624 : void roundOut() {
625 : this->set(SkScalarFloorToScalar(fLeft),
626 : SkScalarFloorToScalar(fTop),
627 : SkScalarCeilToScalar(fRight),
628 : SkScalarCeilToScalar(fBottom));
629 : }
630 :
631 : /**
632 : * Swap top/bottom or left/right if there are flipped (i.e. if width()
633 : * or height() would have returned a negative value.) This should be called
634 : * if the edges are computed separately, and may have crossed over each
635 : * other. When this returns, left <= right && top <= bottom
636 : */
637 : void sort();
638 : };
639 :
640 : #endif
641 :
|