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