1 /*
2 * Copyright 2006 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #ifndef SkRect_DEFINED
9 #define SkRect_DEFINED
10
11 #include "include/core/SkPoint.h"
12 #include "include/core/SkSize.h"
13 #include "include/private/SkSafe32.h"
14 #include "include/private/SkTFitsIn.h"
15
16 #include <utility>
17
18 struct SkRect;
19
20 /** \struct SkIRect
21 SkIRect holds four 32-bit integer coordinates describing the upper and
22 lower bounds of a rectangle. SkIRect may be created from outer bounds or
23 from position, width, and height. SkIRect describes an area; if its right
24 is less than or equal to its left, or if its bottom is less than or equal to
25 its top, it is considered empty.
26 */
27 struct SK_API SkIRect {
28 int32_t fLeft; //!< smaller x-axis bounds
29 int32_t fTop; //!< smaller y-axis bounds
30 int32_t fRight; //!< larger x-axis bounds
31 int32_t fBottom; //!< larger y-axis bounds
32
33 /** Returns constructed SkIRect set to (0, 0, 0, 0).
34 Many other rectangles are empty; if left is equal to or greater than right,
35 or if top is equal to or greater than bottom. Setting all members to zero
36 is a convenience, but does not designate a special empty rectangle.
37
38 @return bounds (0, 0, 0, 0)
39 */
MakeEmptySkIRect40 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeEmpty() {
41 return SkIRect{0, 0, 0, 0};
42 }
43
44 /** Returns constructed SkIRect set to (0, 0, w, h). Does not validate input; w or h
45 may be negative.
46
47 @param w width of constructed SkIRect
48 @param h height of constructed SkIRect
49 @return bounds (0, 0, w, h)
50 */
MakeWHSkIRect51 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeWH(int32_t w, int32_t h) {
52 return SkIRect{0, 0, w, h};
53 }
54
55 /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
56 Does not validate input; size.width() or size.height() may be negative.
57
58 @param size values for SkIRect width and height
59 @return bounds (0, 0, size.width(), size.height())
60 */
MakeSizeSkIRect61 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeSize(const SkISize& size) {
62 return SkIRect{0, 0, size.fWidth, size.fHeight};
63 }
64
65 /** Returns constructed SkIRect set to (l, t, r, b). Does not sort input; SkIRect may
66 result in fLeft greater than fRight, or fTop greater than fBottom.
67
68 @param l integer stored in fLeft
69 @param t integer stored in fTop
70 @param r integer stored in fRight
71 @param b integer stored in fBottom
72 @return bounds (l, t, r, b)
73 */
MakeLTRBSkIRect74 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeLTRB(int32_t l, int32_t t,
75 int32_t r, int32_t b) {
76 return SkIRect{l, t, r, b};
77 }
78
79 /** Returns constructed SkIRect set to: (x, y, x + w, y + h).
80 Does not validate input; w or h may be negative.
81
82 @param x stored in fLeft
83 @param y stored in fTop
84 @param w added to x and stored in fRight
85 @param h added to y and stored in fBottom
86 @return bounds at (x, y) with width w and height h
87 */
MakeXYWHSkIRect88 static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeXYWH(int32_t x, int32_t y,
89 int32_t w, int32_t h) {
90 return { x, y, Sk32_sat_add(x, w), Sk32_sat_add(y, h) };
91 }
92
93 /** Returns left edge of SkIRect, if sorted.
94 Call sort() to reverse fLeft and fRight if needed.
95
96 @return fLeft
97 */
leftSkIRect98 int32_t left() const { return fLeft; }
99
100 /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
101 and sort() to reverse fTop and fBottom if needed.
102
103 @return fTop
104 */
topSkIRect105 int32_t top() const { return fTop; }
106
107 /** Returns right edge of SkIRect, if sorted.
108 Call sort() to reverse fLeft and fRight if needed.
109
110 @return fRight
111 */
rightSkIRect112 int32_t right() const { return fRight; }
113
114 /** Returns bottom edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
115 and sort() to reverse fTop and fBottom if needed.
116
117 @return fBottom
118 */
bottomSkIRect119 int32_t bottom() const { return fBottom; }
120
121 /** Returns left edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
122 and sort() to reverse fLeft and fRight if needed.
123
124 @return fLeft
125 */
xSkIRect126 int32_t x() const { return fLeft; }
127
128 /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
129 and sort() to reverse fTop and fBottom if needed.
130
131 @return fTop
132 */
ySkIRect133 int32_t y() const { return fTop; }
134
135 // Experimental
topLeftSkIRect136 SkIPoint topLeft() const { return {fLeft, fTop}; }
137
138 /** Returns span on the x-axis. This does not check if SkIRect is sorted, or if
139 result fits in 32-bit signed integer; result may be negative.
140
141 @return fRight minus fLeft
142 */
widthSkIRect143 int32_t width() const { return Sk32_can_overflow_sub(fRight, fLeft); }
144
145 /** Returns span on the y-axis. This does not check if SkIRect is sorted, or if
146 result fits in 32-bit signed integer; result may be negative.
147
148 @return fBottom minus fTop
149 */
heightSkIRect150 int32_t height() const { return Sk32_can_overflow_sub(fBottom, fTop); }
151
152 /** Returns spans on the x-axis and y-axis. This does not check if SkIRect is sorted,
153 or if result fits in 32-bit signed integer; result may be negative.
154
155 @return SkISize (width, height)
156 */
sizeSkIRect157 SkISize size() const { return SkISize::Make(this->width(), this->height()); }
158
159 /** Returns span on the x-axis. This does not check if SkIRect is sorted, so the
160 result may be negative. This is safer than calling width() since width() might
161 overflow in its calculation.
162
163 @return fRight minus fLeft cast to int64_t
164 */
width64SkIRect165 int64_t width64() const { return (int64_t)fRight - (int64_t)fLeft; }
166
167 /** Returns span on the y-axis. This does not check if SkIRect is sorted, so the
168 result may be negative. This is safer than calling height() since height() might
169 overflow in its calculation.
170
171 @return fBottom minus fTop cast to int64_t
172 */
height64SkIRect173 int64_t height64() const { return (int64_t)fBottom - (int64_t)fTop; }
174
175 /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
176 to or greater than fBottom. Call sort() to reverse rectangles with negative
177 width64() or height64().
178
179 @return true if width64() or height64() are zero or negative
180 */
isEmpty64SkIRect181 bool isEmpty64() const { return fRight <= fLeft || fBottom <= fTop; }
182
183 /** Returns true if width() or height() are zero or negative.
184
185 @return true if width() or height() are zero or negative
186 */
isEmptySkIRect187 bool isEmpty() const {
188 int64_t w = this->width64();
189 int64_t h = this->height64();
190 if (w <= 0 || h <= 0) {
191 return true;
192 }
193 // Return true if either exceeds int32_t
194 return !SkTFitsIn<int32_t>(w | h);
195 }
196
197 /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
198 identical to corresponding members in b.
199
200 @param a SkIRect to compare
201 @param b SkIRect to compare
202 @return true if members are equal
203 */
204 friend bool operator==(const SkIRect& a, const SkIRect& b) {
205 return !memcmp(&a, &b, sizeof(a));
206 }
207
208 /** Returns true if any member in a: fLeft, fTop, fRight, and fBottom; is not
209 identical to the corresponding member in b.
210
211 @param a SkIRect to compare
212 @param b SkIRect to compare
213 @return true if members are not equal
214 */
215 friend bool operator!=(const SkIRect& a, const SkIRect& b) {
216 return !(a == b);
217 }
218
219 /** Sets SkIRect to (0, 0, 0, 0).
220
221 Many other rectangles are empty; if left is equal to or greater than right,
222 or if top is equal to or greater than bottom. Setting all members to zero
223 is a convenience, but does not designate a special empty rectangle.
224 */
setEmptySkIRect225 void setEmpty() { memset(this, 0, sizeof(*this)); }
226
227 /** Sets SkIRect to (left, top, right, bottom).
228 left and right are not sorted; left is not necessarily less than right.
229 top and bottom are not sorted; top is not necessarily less than bottom.
230
231 @param left stored in fLeft
232 @param top stored in fTop
233 @param right stored in fRight
234 @param bottom stored in fBottom
235 */
setLTRBSkIRect236 void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom) {
237 fLeft = left;
238 fTop = top;
239 fRight = right;
240 fBottom = bottom;
241 }
242
243 /** Sets SkIRect to: (x, y, x + width, y + height).
244 Does not validate input; width or height may be negative.
245
246 @param x stored in fLeft
247 @param y stored in fTop
248 @param width added to x and stored in fRight
249 @param height added to y and stored in fBottom
250 */
setXYWHSkIRect251 void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height) {
252 fLeft = x;
253 fTop = y;
254 fRight = Sk32_sat_add(x, width);
255 fBottom = Sk32_sat_add(y, height);
256 }
257
setWHSkIRect258 void setWH(int32_t width, int32_t height) {
259 fLeft = 0;
260 fTop = 0;
261 fRight = width;
262 fBottom = height;
263 }
264
265 /** Returns SkIRect offset by (dx, dy).
266
267 If dx is negative, SkIRect returned is moved to the left.
268 If dx is positive, SkIRect returned is moved to the right.
269 If dy is negative, SkIRect returned is moved upward.
270 If dy is positive, SkIRect returned is moved downward.
271
272 @param dx offset added to fLeft and fRight
273 @param dy offset added to fTop and fBottom
274 @return SkIRect offset by dx and dy, with original width and height
275 */
makeOffsetSkIRect276 constexpr SkIRect makeOffset(int32_t dx, int32_t dy) const {
277 return {
278 Sk32_sat_add(fLeft, dx), Sk32_sat_add(fTop, dy),
279 Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),
280 };
281 }
282
283 /** Returns SkIRect offset by (offset.x(), offset.y()).
284
285 If offset.x() is negative, SkIRect returned is moved to the left.
286 If offset.x() is positive, SkIRect returned is moved to the right.
287 If offset.y() is negative, SkIRect returned is moved upward.
288 If offset.y() is positive, SkIRect returned is moved downward.
289
290 @param offset translation vector
291 @return SkIRect translated by offset, with original width and height
292 */
makeOffsetSkIRect293 constexpr SkIRect makeOffset(SkIVector offset) const {
294 return this->makeOffset(offset.x(), offset.y());
295 }
296
297 /** Returns SkIRect, inset by (dx, dy).
298
299 If dx is negative, SkIRect returned is wider.
300 If dx is positive, SkIRect returned is narrower.
301 If dy is negative, SkIRect returned is taller.
302 If dy is positive, SkIRect returned is shorter.
303
304 @param dx offset added to fLeft and subtracted from fRight
305 @param dy offset added to fTop and subtracted from fBottom
306 @return SkIRect inset symmetrically left and right, top and bottom
307 */
makeInsetSkIRect308 SkIRect makeInset(int32_t dx, int32_t dy) const {
309 return {
310 Sk32_sat_add(fLeft, dx), Sk32_sat_add(fTop, dy),
311 Sk32_sat_sub(fRight, dx), Sk32_sat_sub(fBottom, dy),
312 };
313 }
314
315 /** Returns SkIRect, outset by (dx, dy).
316
317 If dx is negative, SkIRect returned is narrower.
318 If dx is positive, SkIRect returned is wider.
319 If dy is negative, SkIRect returned is shorter.
320 If dy is positive, SkIRect returned is taller.
321
322 @param dx offset subtracted to fLeft and added from fRight
323 @param dy offset subtracted to fTop and added from fBottom
324 @return SkIRect outset symmetrically left and right, top and bottom
325 */
makeOutsetSkIRect326 SkIRect makeOutset(int32_t dx, int32_t dy) const {
327 return {
328 Sk32_sat_sub(fLeft, dx), Sk32_sat_sub(fTop, dy),
329 Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),
330 };
331 }
332
333 /** Offsets SkIRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
334
335 If dx is negative, moves SkIRect returned to the left.
336 If dx is positive, moves SkIRect returned to the right.
337 If dy is negative, moves SkIRect returned upward.
338 If dy is positive, moves SkIRect returned downward.
339
340 @param dx offset added to fLeft and fRight
341 @param dy offset added to fTop and fBottom
342 */
offsetSkIRect343 void offset(int32_t dx, int32_t dy) {
344 fLeft = Sk32_sat_add(fLeft, dx);
345 fTop = Sk32_sat_add(fTop, dy);
346 fRight = Sk32_sat_add(fRight, dx);
347 fBottom = Sk32_sat_add(fBottom, dy);
348 }
349
350 /** Offsets SkIRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
351 fTop, fBottom.
352
353 If delta.fX is negative, moves SkIRect returned to the left.
354 If delta.fX is positive, moves SkIRect returned to the right.
355 If delta.fY is negative, moves SkIRect returned upward.
356 If delta.fY is positive, moves SkIRect returned downward.
357
358 @param delta offset added to SkIRect
359 */
offsetSkIRect360 void offset(const SkIPoint& delta) {
361 this->offset(delta.fX, delta.fY);
362 }
363
364 /** Offsets SkIRect so that fLeft equals newX, and fTop equals newY. width and height
365 are unchanged.
366
367 @param newX stored in fLeft, preserving width()
368 @param newY stored in fTop, preserving height()
369 */
offsetToSkIRect370 void offsetTo(int32_t newX, int32_t newY) {
371 fRight = Sk64_pin_to_s32((int64_t)fRight + newX - fLeft);
372 fBottom = Sk64_pin_to_s32((int64_t)fBottom + newY - fTop);
373 fLeft = newX;
374 fTop = newY;
375 }
376
377 /** Insets SkIRect by (dx,dy).
378
379 If dx is positive, makes SkIRect narrower.
380 If dx is negative, makes SkIRect wider.
381 If dy is positive, makes SkIRect shorter.
382 If dy is negative, makes SkIRect taller.
383
384 @param dx offset added to fLeft and subtracted from fRight
385 @param dy offset added to fTop and subtracted from fBottom
386 */
insetSkIRect387 void inset(int32_t dx, int32_t dy) {
388 fLeft = Sk32_sat_add(fLeft, dx);
389 fTop = Sk32_sat_add(fTop, dy);
390 fRight = Sk32_sat_sub(fRight, dx);
391 fBottom = Sk32_sat_sub(fBottom, dy);
392 }
393
394 /** Outsets SkIRect by (dx, dy).
395
396 If dx is positive, makes SkIRect wider.
397 If dx is negative, makes SkIRect narrower.
398 If dy is positive, makes SkIRect taller.
399 If dy is negative, makes SkIRect shorter.
400
401 @param dx subtracted to fLeft and added from fRight
402 @param dy subtracted to fTop and added from fBottom
403 */
outsetSkIRect404 void outset(int32_t dx, int32_t dy) { this->inset(-dx, -dy); }
405
406 /** Adjusts SkIRect by adding dL to fLeft, dT to fTop, dR to fRight, and dB to fBottom.
407
408 If dL is positive, narrows SkIRect on the left. If negative, widens it on the left.
409 If dT is positive, shrinks SkIRect on the top. If negative, lengthens it on the top.
410 If dR is positive, narrows SkIRect on the right. If negative, widens it on the right.
411 If dB is positive, shrinks SkIRect on the bottom. If negative, lengthens it on the bottom.
412
413 The resulting SkIRect is not checked for validity. Thus, if the resulting SkIRect left is
414 greater than right, the SkIRect will be considered empty. Call sort() after this call
415 if that is not the desired behavior.
416
417 @param dL offset added to fLeft
418 @param dT offset added to fTop
419 @param dR offset added to fRight
420 @param dB offset added to fBottom
421 */
adjustSkIRect422 void adjust(int32_t dL, int32_t dT, int32_t dR, int32_t dB) {
423 fLeft = Sk32_sat_add(fLeft, dL);
424 fTop = Sk32_sat_add(fTop, dT);
425 fRight = Sk32_sat_add(fRight, dR);
426 fBottom = Sk32_sat_add(fBottom, dB);
427 }
428
429 /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
430 Returns false if SkIRect is empty.
431
432 Considers input to describe constructed SkIRect: (x, y, x + 1, y + 1) and
433 returns true if constructed area is completely enclosed by SkIRect area.
434
435 @param x test SkIPoint x-coordinate
436 @param y test SkIPoint y-coordinate
437 @return true if (x, y) is inside SkIRect
438 */
containsSkIRect439 bool contains(int32_t x, int32_t y) const {
440 return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
441 }
442
443 /** Returns true if SkIRect contains r.
444 Returns false if SkIRect is empty or r is empty.
445
446 SkIRect contains r when SkIRect area completely includes r area.
447
448 @param r SkIRect contained
449 @return true if all sides of SkIRect are outside r
450 */
containsSkIRect451 bool contains(const SkIRect& r) const {
452 return !r.isEmpty() && !this->isEmpty() && // check for empties
453 fLeft <= r.fLeft && fTop <= r.fTop &&
454 fRight >= r.fRight && fBottom >= r.fBottom;
455 }
456
457 /** Returns true if SkIRect contains r.
458 Returns false if SkIRect is empty or r is empty.
459
460 SkIRect contains r when SkIRect area completely includes r area.
461
462 @param r SkRect contained
463 @return true if all sides of SkIRect are outside r
464 */
465 inline bool contains(const SkRect& r) const;
466
467 /** Returns true if SkIRect contains construction.
468 Asserts if SkIRect is empty or construction is empty, and if SK_DEBUG is defined.
469
470 Return is undefined if SkIRect is empty or construction is empty.
471
472 @param r SkIRect contained
473 @return true if all sides of SkIRect are outside r
474 */
containsNoEmptyCheckSkIRect475 bool containsNoEmptyCheck(const SkIRect& r) const {
476 SkASSERT(fLeft < fRight && fTop < fBottom);
477 SkASSERT(r.fLeft < r.fRight && r.fTop < r.fBottom);
478 return fLeft <= r.fLeft && fTop <= r.fTop && fRight >= r.fRight && fBottom >= r.fBottom;
479 }
480
481 /** Returns true if SkIRect intersects r, and sets SkIRect to intersection.
482 Returns false if SkIRect does not intersect r, and leaves SkIRect unchanged.
483
484 Returns false if either r or SkIRect is empty, leaving SkIRect unchanged.
485
486 @param r limit of result
487 @return true if r and SkIRect have area in common
488 */
intersectSkIRect489 bool intersect(const SkIRect& r) {
490 return this->intersect(*this, r);
491 }
492
493 /** Returns true if a intersects b, and sets SkIRect to intersection.
494 Returns false if a does not intersect b, and leaves SkIRect unchanged.
495
496 Returns false if either a or b is empty, leaving SkIRect unchanged.
497
498 @param a SkIRect to intersect
499 @param b SkIRect to intersect
500 @return true if a and b have area in common
501 */
502 bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& a, const SkIRect& b);
503
504 /** Returns true if a intersects b.
505 Returns false if either a or b is empty, or do not intersect.
506
507 @param a SkIRect to intersect
508 @param b SkIRect to intersect
509 @return true if a and b have area in common
510 */
IntersectsSkIRect511 static bool Intersects(const SkIRect& a, const SkIRect& b) {
512 SkIRect dummy;
513 return dummy.intersect(a, b);
514 }
515
516 /** Sets SkIRect to the union of itself and r.
517
518 Has no effect if r is empty. Otherwise, if SkIRect is empty, sets SkIRect to r.
519
520 @param r expansion SkIRect
521 */
522 void join(const SkIRect& r);
523
524 /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
525 fTop and fBottom if fTop is greater than fBottom. Result may be empty,
526 and width() and height() will be zero or positive.
527 */
sortSkIRect528 void sort() {
529 using std::swap;
530 if (fLeft > fRight) {
531 swap(fLeft, fRight);
532 }
533 if (fTop > fBottom) {
534 swap(fTop, fBottom);
535 }
536 }
537
538 /** Returns SkIRect with fLeft and fRight swapped if fLeft is greater than fRight; and
539 with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
540 and width() and height() will be zero or positive.
541
542 @return sorted SkIRect
543 */
makeSortedSkIRect544 SkIRect makeSorted() const {
545 return MakeLTRB(SkMin32(fLeft, fRight), SkMin32(fTop, fBottom),
546 SkMax32(fLeft, fRight), SkMax32(fTop, fBottom));
547 }
548
549 /** Returns a reference to immutable empty SkIRect, set to (0, 0, 0, 0).
550
551 @return global SkIRect set to all zeroes
552 */
EmptyIRectSkIRect553 static const SkIRect& SK_WARN_UNUSED_RESULT EmptyIRect() {
554 static const SkIRect gEmpty = { 0, 0, 0, 0 };
555 return gEmpty;
556 }
557 };
558
559 /** \struct SkRect
560 SkRect holds four SkScalar coordinates describing the upper and
561 lower bounds of a rectangle. SkRect may be created from outer bounds or
562 from position, width, and height. SkRect describes an area; if its right
563 is less than or equal to its left, or if its bottom is less than or equal to
564 its top, it is considered empty.
565 */
566 struct SK_API SkRect {
567 SkScalar fLeft; //!< smaller x-axis bounds
568 SkScalar fTop; //!< smaller y-axis bounds
569 SkScalar fRight; //!< larger x-axis bounds
570 SkScalar fBottom; //!< larger y-axis bounds
571
572 /** Returns constructed SkRect set to (0, 0, 0, 0).
573 Many other rectangles are empty; if left is equal to or greater than right,
574 or if top is equal to or greater than bottom. Setting all members to zero
575 is a convenience, but does not designate a special empty rectangle.
576
577 @return bounds (0, 0, 0, 0)
578 */
MakeEmptySkRect579 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeEmpty() {
580 return SkRect{0, 0, 0, 0};
581 }
582
583 /** Returns constructed SkRect set to SkScalar values (0, 0, w, h). Does not
584 validate input; w or h may be negative.
585
586 Passing integer values may generate a compiler warning since SkRect cannot
587 represent 32-bit integers exactly. Use SkIRect for an exact integer rectangle.
588
589 @param w SkScalar width of constructed SkRect
590 @param h SkScalar height of constructed SkRect
591 @return bounds (0, 0, w, h)
592 */
MakeWHSkRect593 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeWH(SkScalar w, SkScalar h) {
594 return SkRect{0, 0, w, h};
595 }
596
597 /** Returns constructed SkRect set to integer values (0, 0, w, h). Does not validate
598 input; w or h may be negative.
599
600 Use to avoid a compiler warning that input may lose precision when stored.
601 Use SkIRect for an exact integer rectangle.
602
603 @param w integer width of constructed SkRect
604 @param h integer height of constructed SkRect
605 @return bounds (0, 0, w, h)
606 */
MakeIWHSkRect607 static SkRect SK_WARN_UNUSED_RESULT MakeIWH(int w, int h) {
608 return {0, 0, SkIntToScalar(w), SkIntToScalar(h)};
609 }
610
611 /** Returns constructed SkRect set to (0, 0, size.width(), size.height()). Does not
612 validate input; size.width() or size.height() may be negative.
613
614 @param size SkScalar values for SkRect width and height
615 @return bounds (0, 0, size.width(), size.height())
616 */
MakeSizeSkRect617 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeSize(const SkSize& size) {
618 return SkRect{0, 0, size.fWidth, size.fHeight};
619 }
620
621 /** Returns constructed SkRect set to (l, t, r, b). Does not sort input; SkRect may
622 result in fLeft greater than fRight, or fTop greater than fBottom.
623
624 @param l SkScalar stored in fLeft
625 @param t SkScalar stored in fTop
626 @param r SkScalar stored in fRight
627 @param b SkScalar stored in fBottom
628 @return bounds (l, t, r, b)
629 */
MakeLTRBSkRect630 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeLTRB(SkScalar l, SkScalar t, SkScalar r,
631 SkScalar b) {
632 return SkRect {l, t, r, b};
633 }
634
635 /** Returns constructed SkRect set to (x, y, x + w, y + h).
636 Does not validate input; w or h may be negative.
637
638 @param x stored in fLeft
639 @param y stored in fTop
640 @param w added to x and stored in fRight
641 @param h added to y and stored in fBottom
642 @return bounds at (x, y) with width w and height h
643 */
MakeXYWHSkRect644 static constexpr SkRect SK_WARN_UNUSED_RESULT MakeXYWH(SkScalar x, SkScalar y, SkScalar w,
645 SkScalar h) {
646 return SkRect {x, y, x + w, y + h};
647 }
648
649 /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
650 Does not validate input; size.width() or size.height() may be negative.
651
652 @param size integer values for SkRect width and height
653 @return bounds (0, 0, size.width(), size.height())
654 */
MakeSkRect655 static SkRect Make(const SkISize& size) {
656 return MakeIWH(size.width(), size.height());
657 }
658
659 /** Returns constructed SkIRect set to irect, promoting integers to scalar.
660 Does not validate input; fLeft may be greater than fRight, fTop may be greater
661 than fBottom.
662
663 @param irect integer unsorted bounds
664 @return irect members converted to SkScalar
665 */
MakeSkRect666 static SkRect SK_WARN_UNUSED_RESULT Make(const SkIRect& irect) {
667 return {
668 SkIntToScalar(irect.fLeft), SkIntToScalar(irect.fTop),
669 SkIntToScalar(irect.fRight), SkIntToScalar(irect.fBottom)
670 };
671 }
672
673 /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
674 to or greater than fBottom. Call sort() to reverse rectangles with negative
675 width() or height().
676
677 @return true if width() or height() are zero or negative
678 */
isEmptySkRect679 bool isEmpty() const {
680 // We write it as the NOT of a non-empty rect, so we will return true if any values
681 // are NaN.
682 return !(fLeft < fRight && fTop < fBottom);
683 }
684
685 /** Returns true if fLeft is equal to or less than fRight, or if fTop is equal
686 to or less than fBottom. Call sort() to reverse rectangles with negative
687 width() or height().
688
689 @return true if width() or height() are zero or positive
690 */
isSortedSkRect691 bool isSorted() const { return fLeft <= fRight && fTop <= fBottom; }
692
693 /** Returns true if all values in the rectangle are finite: SK_ScalarMin or larger,
694 and SK_ScalarMax or smaller.
695
696 @return true if no member is infinite or NaN
697 */
isFiniteSkRect698 bool isFinite() const {
699 float accum = 0;
700 accum *= fLeft;
701 accum *= fTop;
702 accum *= fRight;
703 accum *= fBottom;
704
705 // accum is either NaN or it is finite (zero).
706 SkASSERT(0 == accum || SkScalarIsNaN(accum));
707
708 // value==value will be true iff value is not NaN
709 // TODO: is it faster to say !accum or accum==accum?
710 return !SkScalarIsNaN(accum);
711 }
712
713 /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
714 Call sort() to reverse fLeft and fRight if needed.
715
716 @return fLeft
717 */
xSkRect718 SkScalar x() const { return fLeft; }
719
720 /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
721 and sort() to reverse fTop and fBottom if needed.
722
723 @return fTop
724 */
ySkRect725 SkScalar y() const { return fTop; }
726
727 /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
728 Call sort() to reverse fLeft and fRight if needed.
729
730 @return fLeft
731 */
leftSkRect732 SkScalar left() const { return fLeft; }
733
734 /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
735 and sort() to reverse fTop and fBottom if needed.
736
737 @return fTop
738 */
topSkRect739 SkScalar top() const { return fTop; }
740
741 /** Returns right edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
742 Call sort() to reverse fLeft and fRight if needed.
743
744 @return fRight
745 */
rightSkRect746 SkScalar right() const { return fRight; }
747
748 /** Returns bottom edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
749 and sort() to reverse fTop and fBottom if needed.
750
751 @return fBottom
752 */
bottomSkRect753 SkScalar bottom() const { return fBottom; }
754
755 /** Returns span on the x-axis. This does not check if SkRect is sorted, or if
756 result fits in 32-bit float; result may be negative or infinity.
757
758 @return fRight minus fLeft
759 */
widthSkRect760 SkScalar width() const { return fRight - fLeft; }
761
762 /** Returns span on the y-axis. This does not check if SkRect is sorted, or if
763 result fits in 32-bit float; result may be negative or infinity.
764
765 @return fBottom minus fTop
766 */
heightSkRect767 SkScalar height() const { return fBottom - fTop; }
768
769 /** Returns average of left edge and right edge. Result does not change if SkRect
770 is sorted. Result may overflow to infinity if SkRect is far from the origin.
771
772 @return midpoint on x-axis
773 */
centerXSkRect774 SkScalar centerX() const {
775 // don't use SkScalarHalf(fLeft + fBottom) as that might overflow before the 0.5
776 return SkScalarHalf(fLeft) + SkScalarHalf(fRight);
777 }
778
779 /** Returns average of top edge and bottom edge. Result does not change if SkRect
780 is sorted.
781
782 @return midpoint on y-axis
783 */
centerYSkRect784 SkScalar centerY() const {
785 // don't use SkScalarHalf(fTop + fBottom) as that might overflow before the 0.5
786 return SkScalarHalf(fTop) + SkScalarHalf(fBottom);
787 }
788
789 /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
790 equal to the corresponding members in b.
791
792 a and b are not equal if either contain NaN. a and b are equal if members
793 contain zeroes with different signs.
794
795 @param a SkRect to compare
796 @param b SkRect to compare
797 @return true if members are equal
798 */
799 friend bool operator==(const SkRect& a, const SkRect& b) {
800 return SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);
801 }
802
803 /** Returns true if any in a: fLeft, fTop, fRight, and fBottom; does not
804 equal the corresponding members in b.
805
806 a and b are not equal if either contain NaN. a and b are equal if members
807 contain zeroes with different signs.
808
809 @param a SkRect to compare
810 @param b SkRect to compare
811 @return true if members are not equal
812 */
813 friend bool operator!=(const SkRect& a, const SkRect& b) {
814 return !SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);
815 }
816
817 /** Returns four points in quad that enclose SkRect ordered as: top-left, top-right,
818 bottom-right, bottom-left.
819
820 TODO: Consider adding parameter to control whether quad is clockwise or counterclockwise.
821
822 @param quad storage for corners of SkRect
823 */
824 void toQuad(SkPoint quad[4]) const;
825
826 /** Sets SkRect to (0, 0, 0, 0).
827
828 Many other rectangles are empty; if left is equal to or greater than right,
829 or if top is equal to or greater than bottom. Setting all members to zero
830 is a convenience, but does not designate a special empty rectangle.
831 */
setEmptySkRect832 void setEmpty() { *this = MakeEmpty(); }
833
834 /** Sets SkRect to src, promoting src members from integer to scalar.
835 Very large values in src may lose precision.
836
837 @param src integer SkRect
838 */
setSkRect839 void set(const SkIRect& src) {
840 fLeft = SkIntToScalar(src.fLeft);
841 fTop = SkIntToScalar(src.fTop);
842 fRight = SkIntToScalar(src.fRight);
843 fBottom = SkIntToScalar(src.fBottom);
844 }
845
846 /** Sets SkRect to (left, top, right, bottom).
847 left and right are not sorted; left is not necessarily less than right.
848 top and bottom are not sorted; top is not necessarily less than bottom.
849
850 @param left stored in fLeft
851 @param top stored in fTop
852 @param right stored in fRight
853 @param bottom stored in fBottom
854 */
setLTRBSkRect855 void setLTRB(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
856 fLeft = left;
857 fTop = top;
858 fRight = right;
859 fBottom = bottom;
860 }
861
862 /** Sets to bounds of SkPoint array with count entries. If count is zero or smaller,
863 or if SkPoint array contains an infinity or NaN, sets to (0, 0, 0, 0).
864
865 Result is either empty or sorted: fLeft is less than or equal to fRight, and
866 fTop is less than or equal to fBottom.
867
868 @param pts SkPoint array
869 @param count entries in array
870 */
setBoundsSkRect871 void setBounds(const SkPoint pts[], int count) {
872 (void)this->setBoundsCheck(pts, count);
873 }
874
875 /** Sets to bounds of SkPoint array with count entries. Returns false if count is
876 zero or smaller, or if SkPoint array contains an infinity or NaN; in these cases
877 sets SkRect to (0, 0, 0, 0).
878
879 Result is either empty or sorted: fLeft is less than or equal to fRight, and
880 fTop is less than or equal to fBottom.
881
882 @param pts SkPoint array
883 @param count entries in array
884 @return true if all SkPoint values are finite
885 */
886 bool setBoundsCheck(const SkPoint pts[], int count);
887
888 /** Sets to bounds of SkPoint pts array with count entries. If any SkPoint in pts
889 contains infinity or NaN, all SkRect dimensions are set to NaN.
890
891 @param pts SkPoint array
892 @param count entries in array
893 */
894 void setBoundsNoCheck(const SkPoint pts[], int count);
895
896 /** Sets bounds to the smallest SkRect enclosing SkPoint p0 and p1. The result is
897 sorted and may be empty. Does not check to see if values are finite.
898
899 @param p0 corner to include
900 @param p1 corner to include
901 */
setSkRect902 void set(const SkPoint& p0, const SkPoint& p1) {
903 fLeft = SkMinScalar(p0.fX, p1.fX);
904 fRight = SkMaxScalar(p0.fX, p1.fX);
905 fTop = SkMinScalar(p0.fY, p1.fY);
906 fBottom = SkMaxScalar(p0.fY, p1.fY);
907 }
908
909 /** Sets SkRect to (x, y, x + width, y + height).
910 Does not validate input; width or height may be negative.
911
912 @param x stored in fLeft
913 @param y stored in fTop
914 @param width added to x and stored in fRight
915 @param height added to y and stored in fBottom
916 */
setXYWHSkRect917 void setXYWH(SkScalar x, SkScalar y, SkScalar width, SkScalar height) {
918 fLeft = x;
919 fTop = y;
920 fRight = x + width;
921 fBottom = y + height;
922 }
923
924 /** Sets SkRect to (0, 0, width, height). Does not validate input;
925 width or height may be negative.
926
927 @param width stored in fRight
928 @param height stored in fBottom
929 */
setWHSkRect930 void setWH(SkScalar width, SkScalar height) {
931 fLeft = 0;
932 fTop = 0;
933 fRight = width;
934 fBottom = height;
935 }
setIWHSkRect936 void setIWH(int32_t width, int32_t height) {
937 this->setWH(SkIntToScalar(width), SkIntToScalar(height));
938 }
939
940 /** Returns SkRect offset by (dx, dy).
941
942 If dx is negative, SkRect returned is moved to the left.
943 If dx is positive, SkRect returned is moved to the right.
944 If dy is negative, SkRect returned is moved upward.
945 If dy is positive, SkRect returned is moved downward.
946
947 @param dx added to fLeft and fRight
948 @param dy added to fTop and fBottom
949 @return SkRect offset on axes, with original width and height
950 */
makeOffsetSkRect951 SkRect makeOffset(SkScalar dx, SkScalar dy) const {
952 return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy);
953 }
954
955 /** Returns SkRect, inset by (dx, dy).
956
957 If dx is negative, SkRect returned is wider.
958 If dx is positive, SkRect returned is narrower.
959 If dy is negative, SkRect returned is taller.
960 If dy is positive, SkRect returned is shorter.
961
962 @param dx added to fLeft and subtracted from fRight
963 @param dy added to fTop and subtracted from fBottom
964 @return SkRect inset symmetrically left and right, top and bottom
965 */
makeInsetSkRect966 SkRect makeInset(SkScalar dx, SkScalar dy) const {
967 return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, fBottom - dy);
968 }
969
970 /** Returns SkRect, outset by (dx, dy).
971
972 If dx is negative, SkRect returned is narrower.
973 If dx is positive, SkRect returned is wider.
974 If dy is negative, SkRect returned is shorter.
975 If dy is positive, SkRect returned is taller.
976
977 @param dx subtracted to fLeft and added from fRight
978 @param dy subtracted to fTop and added from fBottom
979 @return SkRect outset symmetrically left and right, top and bottom
980 */
makeOutsetSkRect981 SkRect makeOutset(SkScalar dx, SkScalar dy) const {
982 return MakeLTRB(fLeft - dx, fTop - dy, fRight + dx, fBottom + dy);
983 }
984
985 /** Offsets SkRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
986
987 If dx is negative, moves SkRect to the left.
988 If dx is positive, moves SkRect to the right.
989 If dy is negative, moves SkRect upward.
990 If dy is positive, moves SkRect downward.
991
992 @param dx offset added to fLeft and fRight
993 @param dy offset added to fTop and fBottom
994 */
offsetSkRect995 void offset(SkScalar dx, SkScalar dy) {
996 fLeft += dx;
997 fTop += dy;
998 fRight += dx;
999 fBottom += dy;
1000 }
1001
1002 /** Offsets SkRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
1003 fTop, fBottom.
1004
1005 If delta.fX is negative, moves SkRect to the left.
1006 If delta.fX is positive, moves SkRect to the right.
1007 If delta.fY is negative, moves SkRect upward.
1008 If delta.fY is positive, moves SkRect downward.
1009
1010 @param delta added to SkRect
1011 */
offsetSkRect1012 void offset(const SkPoint& delta) {
1013 this->offset(delta.fX, delta.fY);
1014 }
1015
1016 /** Offsets SkRect so that fLeft equals newX, and fTop equals newY. width and height
1017 are unchanged.
1018
1019 @param newX stored in fLeft, preserving width()
1020 @param newY stored in fTop, preserving height()
1021 */
offsetToSkRect1022 void offsetTo(SkScalar newX, SkScalar newY) {
1023 fRight += newX - fLeft;
1024 fBottom += newY - fTop;
1025 fLeft = newX;
1026 fTop = newY;
1027 }
1028
1029 /** Insets SkRect by (dx, dy).
1030
1031 If dx is positive, makes SkRect narrower.
1032 If dx is negative, makes SkRect wider.
1033 If dy is positive, makes SkRect shorter.
1034 If dy is negative, makes SkRect taller.
1035
1036 @param dx added to fLeft and subtracted from fRight
1037 @param dy added to fTop and subtracted from fBottom
1038 */
insetSkRect1039 void inset(SkScalar dx, SkScalar dy) {
1040 fLeft += dx;
1041 fTop += dy;
1042 fRight -= dx;
1043 fBottom -= dy;
1044 }
1045
1046 /** Outsets SkRect by (dx, dy).
1047
1048 If dx is positive, makes SkRect wider.
1049 If dx is negative, makes SkRect narrower.
1050 If dy is positive, makes SkRect taller.
1051 If dy is negative, makes SkRect shorter.
1052
1053 @param dx subtracted to fLeft and added from fRight
1054 @param dy subtracted to fTop and added from fBottom
1055 */
outsetSkRect1056 void outset(SkScalar dx, SkScalar dy) { this->inset(-dx, -dy); }
1057
1058 /** Returns true if SkRect intersects r, and sets SkRect to intersection.
1059 Returns false if SkRect does not intersect r, and leaves SkRect unchanged.
1060
1061 Returns false if either r or SkRect is empty, leaving SkRect unchanged.
1062
1063 @param r limit of result
1064 @return true if r and SkRect have area in common
1065 */
1066 bool intersect(const SkRect& r);
1067
1068 /** Returns true if a intersects b, and sets SkRect to intersection.
1069 Returns false if a does not intersect b, and leaves SkRect unchanged.
1070
1071 Returns false if either a or b is empty, leaving SkRect unchanged.
1072
1073 @param a SkRect to intersect
1074 @param b SkRect to intersect
1075 @return true if a and b have area in common
1076 */
1077 bool SK_WARN_UNUSED_RESULT intersect(const SkRect& a, const SkRect& b);
1078
1079
1080 private:
IntersectsSkRect1081 static bool Intersects(SkScalar al, SkScalar at, SkScalar ar, SkScalar ab,
1082 SkScalar bl, SkScalar bt, SkScalar br, SkScalar bb) {
1083 SkScalar L = SkMaxScalar(al, bl);
1084 SkScalar R = SkMinScalar(ar, br);
1085 SkScalar T = SkMaxScalar(at, bt);
1086 SkScalar B = SkMinScalar(ab, bb);
1087 return L < R && T < B;
1088 }
1089
1090 public:
1091
1092 /** Returns true if SkRect intersects r.
1093 Returns false if either r or SkRect is empty, or do not intersect.
1094
1095 @param r SkRect to intersect
1096 @return true if r and SkRect have area in common
1097 */
intersectsSkRect1098 bool intersects(const SkRect& r) const {
1099 return Intersects(fLeft, fTop, fRight, fBottom,
1100 r.fLeft, r.fTop, r.fRight, r.fBottom);
1101 }
1102
1103 /** Returns true if a intersects b.
1104 Returns false if either a or b is empty, or do not intersect.
1105
1106 @param a SkRect to intersect
1107 @param b SkRect to intersect
1108 @return true if a and b have area in common
1109 */
IntersectsSkRect1110 static bool Intersects(const SkRect& a, const SkRect& b) {
1111 return Intersects(a.fLeft, a.fTop, a.fRight, a.fBottom,
1112 b.fLeft, b.fTop, b.fRight, b.fBottom);
1113 }
1114
1115 /** Sets SkRect to the union of itself and r.
1116
1117 Has no effect if r is empty. Otherwise, if SkRect is empty, sets
1118 SkRect to r.
1119
1120 @param r expansion SkRect
1121 */
1122 void join(const SkRect& r);
1123
1124 /** Sets SkRect to the union of itself and r.
1125
1126 Asserts if r is empty and SK_DEBUG is defined.
1127 If SkRect is empty, sets SkRect to r.
1128
1129 May produce incorrect results if r is empty.
1130
1131 @param r expansion SkRect
1132 */
joinNonEmptyArgSkRect1133 void joinNonEmptyArg(const SkRect& r) {
1134 SkASSERT(!r.isEmpty());
1135 // if we are empty, just assign
1136 if (fLeft >= fRight || fTop >= fBottom) {
1137 *this = r;
1138 } else {
1139 this->joinPossiblyEmptyRect(r);
1140 }
1141 }
1142
1143 /** Sets SkRect to the union of itself and the construction.
1144
1145 May produce incorrect results if SkRect or r is empty.
1146
1147 @param r expansion SkRect
1148 */
joinPossiblyEmptyRectSkRect1149 void joinPossiblyEmptyRect(const SkRect& r) {
1150 fLeft = SkMinScalar(fLeft, r.left());
1151 fTop = SkMinScalar(fTop, r.top());
1152 fRight = SkMaxScalar(fRight, r.right());
1153 fBottom = SkMaxScalar(fBottom, r.bottom());
1154 }
1155
1156 /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
1157 Returns false if SkRect is empty.
1158
1159 @param x test SkPoint x-coordinate
1160 @param y test SkPoint y-coordinate
1161 @return true if (x, y) is inside SkRect
1162 */
containsSkRect1163 bool contains(SkScalar x, SkScalar y) const {
1164 return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
1165 }
1166
1167 /** Returns true if SkRect contains r.
1168 Returns false if SkRect is empty or r is empty.
1169
1170 SkRect contains r when SkRect area completely includes r area.
1171
1172 @param r SkRect contained
1173 @return true if all sides of SkRect are outside r
1174 */
containsSkRect1175 bool contains(const SkRect& r) const {
1176 // todo: can we eliminate the this->isEmpty check?
1177 return !r.isEmpty() && !this->isEmpty() &&
1178 fLeft <= r.fLeft && fTop <= r.fTop &&
1179 fRight >= r.fRight && fBottom >= r.fBottom;
1180 }
1181
1182 /** Returns true if SkRect contains r.
1183 Returns false if SkRect is empty or r is empty.
1184
1185 SkRect contains r when SkRect area completely includes r area.
1186
1187 @param r SkIRect contained
1188 @return true if all sides of SkRect are outside r
1189 */
containsSkRect1190 bool contains(const SkIRect& r) const {
1191 // todo: can we eliminate the this->isEmpty check?
1192 return !r.isEmpty() && !this->isEmpty() &&
1193 fLeft <= SkIntToScalar(r.fLeft) && fTop <= SkIntToScalar(r.fTop) &&
1194 fRight >= SkIntToScalar(r.fRight) && fBottom >= SkIntToScalar(r.fBottom);
1195 }
1196
1197 /** Sets SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1198 members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1199 SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).
1200
1201 @param dst storage for SkIRect
1202 */
roundSkRect1203 void round(SkIRect* dst) const {
1204 SkASSERT(dst);
1205 dst->setLTRB(SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1206 SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom));
1207 }
1208
1209 /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1210 up fRight and fBottom, using
1211 (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1212 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1213
1214 @param dst storage for SkIRect
1215 */
roundOutSkRect1216 void roundOut(SkIRect* dst) const {
1217 SkASSERT(dst);
1218 dst->setLTRB(SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1219 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom));
1220 }
1221
1222 /** Sets SkRect by discarding the fractional portion of fLeft and fTop; and rounding
1223 up fRight and fBottom, using
1224 (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1225 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1226
1227 @param dst storage for SkRect
1228 */
roundOutSkRect1229 void roundOut(SkRect* dst) const {
1230 dst->setLTRB(SkScalarFloorToScalar(fLeft), SkScalarFloorToScalar(fTop),
1231 SkScalarCeilToScalar(fRight), SkScalarCeilToScalar(fBottom));
1232 }
1233
1234 /** Sets SkRect by rounding up fLeft and fTop; and discarding the fractional portion
1235 of fRight and fBottom, using
1236 (SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
1237 SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom)).
1238
1239 @param dst storage for SkIRect
1240 */
roundInSkRect1241 void roundIn(SkIRect* dst) const {
1242 SkASSERT(dst);
1243 dst->setLTRB(SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
1244 SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom));
1245 }
1246
1247 /** Returns SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1248 members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1249 SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).
1250
1251 @return rounded SkIRect
1252 */
roundSkRect1253 SkIRect round() const {
1254 SkIRect ir;
1255 this->round(&ir);
1256 return ir;
1257 }
1258
1259 /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1260 up fRight and fBottom, using
1261 (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1262 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1263
1264 @return rounded SkIRect
1265 */
roundOutSkRect1266 SkIRect roundOut() const {
1267 SkIRect ir;
1268 this->roundOut(&ir);
1269 return ir;
1270 }
1271
1272 /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
1273 fTop and fBottom if fTop is greater than fBottom. Result may be empty;
1274 and width() and height() will be zero or positive.
1275 */
sortSkRect1276 void sort() {
1277 using std::swap;
1278 if (fLeft > fRight) {
1279 swap(fLeft, fRight);
1280 }
1281
1282 if (fTop > fBottom) {
1283 swap(fTop, fBottom);
1284 }
1285 }
1286
1287 /** Returns SkRect with fLeft and fRight swapped if fLeft is greater than fRight; and
1288 with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
1289 and width() and height() will be zero or positive.
1290
1291 @return sorted SkRect
1292 */
makeSortedSkRect1293 SkRect makeSorted() const {
1294 return MakeLTRB(SkMinScalar(fLeft, fRight), SkMinScalar(fTop, fBottom),
1295 SkMaxScalar(fLeft, fRight), SkMaxScalar(fTop, fBottom));
1296 }
1297
1298 /** Returns pointer to first scalar in SkRect, to treat it as an array with four
1299 entries.
1300
1301 @return pointer to fLeft
1302 */
asScalarsSkRect1303 const SkScalar* asScalars() const { return &fLeft; }
1304
1305 /** Writes text representation of SkRect to standard output. Set asHex to true to
1306 generate exact binary representations of floating point numbers.
1307
1308 @param asHex true if SkScalar values are written as hexadecimal
1309 */
1310 void dump(bool asHex) const;
1311
1312 /** Writes text representation of SkRect to standard output. The representation may be
1313 directly compiled as C++ code. Floating point values are written
1314 with limited precision; it may not be possible to reconstruct original SkRect
1315 from output.
1316 */
dumpSkRect1317 void dump() const { this->dump(false); }
1318
1319 /** Writes text representation of SkRect to standard output. The representation may be
1320 directly compiled as C++ code. Floating point values are written
1321 in hexadecimal to preserve their exact bit pattern. The output reconstructs the
1322 original SkRect.
1323
1324 Use instead of dump() when submitting
1325 */
dumpHexSkRect1326 void dumpHex() const { this->dump(true); }
1327 };
1328
contains(const SkRect & r)1329 inline bool SkIRect::contains(const SkRect& r) const {
1330 return !r.isEmpty() && !this->isEmpty() && // check for empties
1331 (SkScalar)fLeft <= r.fLeft && (SkScalar)fTop <= r.fTop &&
1332 (SkScalar)fRight >= r.fRight && (SkScalar)fBottom >= r.fBottom;
1333 }
1334
1335 #endif
1336