• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <algorithm>
17 #include <utility>
18 
19 struct SkRect;
20 
21 /** \struct SkIRect
22     SkIRect holds four 32-bit integer coordinates describing the upper and
23     lower bounds of a rectangle. SkIRect may be created from outer bounds or
24     from position, width, and height. SkIRect describes an area; if its right
25     is less than or equal to its left, or if its bottom is less than or equal to
26     its top, it is considered empty.
27 */
28 struct SK_API SkIRect {
29     int32_t fLeft;   //!< smaller x-axis bounds
30     int32_t fTop;    //!< smaller y-axis bounds
31     int32_t fRight;  //!< larger x-axis bounds
32     int32_t fBottom; //!< larger y-axis bounds
33 
34     /** Returns constructed SkIRect set to (0, 0, 0, 0).
35         Many other rectangles are empty; if left is equal to or greater than right,
36         or if top is equal to or greater than bottom. Setting all members to zero
37         is a convenience, but does not designate a special empty rectangle.
38 
39         @return  bounds (0, 0, 0, 0)
40     */
MakeEmptySkIRect41     static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeEmpty() {
42         return SkIRect{0, 0, 0, 0};
43     }
44 
45     /** Returns constructed SkIRect set to (0, 0, w, h). Does not validate input; w or h
46         may be negative.
47 
48         @param w  width of constructed SkIRect
49         @param h  height of constructed SkIRect
50         @return   bounds (0, 0, w, h)
51     */
MakeWHSkIRect52     static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeWH(int32_t w, int32_t h) {
53         return SkIRect{0, 0, w, h};
54     }
55 
56     /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
57         Does not validate input; size.width() or size.height() may be negative.
58 
59         @param size  values for SkIRect width and height
60         @return      bounds (0, 0, size.width(), size.height())
61     */
MakeSizeSkIRect62     static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeSize(const SkISize& size) {
63         return SkIRect{0, 0, size.fWidth, size.fHeight};
64     }
65 
66     /** Returns constructed SkIRect set to (pt.x(), pt.y(), pt.x() + size.width(),
67         pt.y() + size.height()). Does not validate input; size.width() or size.height() may be
68         negative.
69 
70         @param pt    values for SkIRect fLeft and fTop
71         @param size  values for SkIRect width and height
72         @return      bounds at pt with width and height of size
73     */
MakePtSizeSkIRect74     static constexpr SkIRect SK_WARN_UNUSED_RESULT MakePtSize(SkIPoint pt, SkISize size) {
75         return MakeXYWH(pt.x(), pt.y(), size.width(), size.height());
76     }
77 
78     /** Returns constructed SkIRect set to (l, t, r, b). Does not sort input; SkIRect may
79         result in fLeft greater than fRight, or fTop greater than fBottom.
80 
81         @param l  integer stored in fLeft
82         @param t  integer stored in fTop
83         @param r  integer stored in fRight
84         @param b  integer stored in fBottom
85         @return   bounds (l, t, r, b)
86     */
MakeLTRBSkIRect87     static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeLTRB(int32_t l, int32_t t,
88                                                             int32_t r, int32_t b) {
89         return SkIRect{l, t, r, b};
90     }
91 
92     /** Returns constructed SkIRect set to: (x, y, x + w, y + h).
93         Does not validate input; w or h may be negative.
94 
95         @param x  stored in fLeft
96         @param y  stored in fTop
97         @param w  added to x and stored in fRight
98         @param h  added to y and stored in fBottom
99         @return   bounds at (x, y) with width w and height h
100     */
MakeXYWHSkIRect101     static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeXYWH(int32_t x, int32_t y,
102                                                             int32_t w, int32_t h) {
103         return { x, y, Sk32_sat_add(x, w), Sk32_sat_add(y, h) };
104     }
105 
106     /** Returns left edge of SkIRect, if sorted.
107         Call sort() to reverse fLeft and fRight if needed.
108 
109         @return  fLeft
110     */
leftSkIRect111     int32_t left() const { return fLeft; }
112 
113     /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
114         and sort() to reverse fTop and fBottom if needed.
115 
116         @return  fTop
117     */
topSkIRect118     int32_t top() const { return fTop; }
119 
120     /** Returns right edge of SkIRect, if sorted.
121         Call sort() to reverse fLeft and fRight if needed.
122 
123         @return  fRight
124     */
rightSkIRect125     int32_t right() const { return fRight; }
126 
127     /** Returns bottom edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
128         and sort() to reverse fTop and fBottom if needed.
129 
130         @return  fBottom
131     */
bottomSkIRect132     int32_t bottom() const { return fBottom; }
133 
134     /** Returns left edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
135         and sort() to reverse fLeft and fRight if needed.
136 
137         @return  fLeft
138     */
xSkIRect139     int32_t x() const { return fLeft; }
140 
141     /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
142         and sort() to reverse fTop and fBottom if needed.
143 
144         @return  fTop
145     */
ySkIRect146     int32_t y() const { return fTop; }
147 
148     // Experimental
topLeftSkIRect149     SkIPoint topLeft() const { return {fLeft, fTop}; }
150 
151     /** Returns span on the x-axis. This does not check if SkIRect is sorted, or if
152         result fits in 32-bit signed integer; result may be negative.
153 
154         @return  fRight minus fLeft
155     */
widthSkIRect156     int32_t width() const { return Sk32_can_overflow_sub(fRight, fLeft); }
157 
158     /** Returns span on the y-axis. This does not check if SkIRect is sorted, or if
159         result fits in 32-bit signed integer; result may be negative.
160 
161         @return  fBottom minus fTop
162     */
heightSkIRect163     int32_t height() const { return Sk32_can_overflow_sub(fBottom, fTop); }
164 
165     /** Returns spans on the x-axis and y-axis. This does not check if SkIRect is sorted,
166         or if result fits in 32-bit signed integer; result may be negative.
167 
168         @return  SkISize (width, height)
169     */
sizeSkIRect170     SkISize size() const { return SkISize::Make(this->width(), this->height()); }
171 
172     /** Returns span on the x-axis. This does not check if SkIRect is sorted, so the
173         result may be negative. This is safer than calling width() since width() might
174         overflow in its calculation.
175 
176         @return  fRight minus fLeft cast to int64_t
177     */
width64SkIRect178     int64_t width64() const { return (int64_t)fRight - (int64_t)fLeft; }
179 
180     /** Returns span on the y-axis. This does not check if SkIRect is sorted, so the
181         result may be negative. This is safer than calling height() since height() might
182         overflow in its calculation.
183 
184         @return  fBottom minus fTop cast to int64_t
185     */
height64SkIRect186     int64_t height64() const { return (int64_t)fBottom - (int64_t)fTop; }
187 
188     /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
189         to or greater than fBottom. Call sort() to reverse rectangles with negative
190         width64() or height64().
191 
192         @return  true if width64() or height64() are zero or negative
193     */
isEmpty64SkIRect194     bool isEmpty64() const { return fRight <= fLeft || fBottom <= fTop; }
195 
196     /** Returns true if width() or height() are zero or negative.
197 
198         @return  true if width() or height() are zero or negative
199     */
isEmptySkIRect200     bool isEmpty() const {
201         int64_t w = this->width64();
202         int64_t h = this->height64();
203         if (w <= 0 || h <= 0) {
204             return true;
205         }
206         // Return true if either exceeds int32_t
207         return !SkTFitsIn<int32_t>(w | h);
208     }
209 
210     /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
211         identical to corresponding members in b.
212 
213         @param a  SkIRect to compare
214         @param b  SkIRect to compare
215         @return   true if members are equal
216     */
217     friend bool operator==(const SkIRect& a, const SkIRect& b) {
218         return !memcmp(&a, &b, sizeof(a));
219     }
220 
221     /** Returns true if any member in a: fLeft, fTop, fRight, and fBottom; is not
222         identical to the corresponding member in b.
223 
224         @param a  SkIRect to compare
225         @param b  SkIRect to compare
226         @return   true if members are not equal
227     */
228     friend bool operator!=(const SkIRect& a, const SkIRect& b) {
229         return !(a == b);
230     }
231 
232     /** Sets SkIRect to (0, 0, 0, 0).
233 
234         Many other rectangles are empty; if left is equal to or greater than right,
235         or if top is equal to or greater than bottom. Setting all members to zero
236         is a convenience, but does not designate a special empty rectangle.
237     */
setEmptySkIRect238     void setEmpty() { memset(this, 0, sizeof(*this)); }
239 
240     /** Sets SkIRect to (left, top, right, bottom).
241         left and right are not sorted; left is not necessarily less than right.
242         top and bottom are not sorted; top is not necessarily less than bottom.
243 
244         @param left    stored in fLeft
245         @param top     stored in fTop
246         @param right   stored in fRight
247         @param bottom  stored in fBottom
248     */
setLTRBSkIRect249     void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom) {
250         fLeft   = left;
251         fTop    = top;
252         fRight  = right;
253         fBottom = bottom;
254     }
255 
256     /** Sets SkIRect to: (x, y, x + width, y + height).
257         Does not validate input; width or height may be negative.
258 
259         @param x       stored in fLeft
260         @param y       stored in fTop
261         @param width   added to x and stored in fRight
262         @param height  added to y and stored in fBottom
263     */
setXYWHSkIRect264     void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height) {
265         fLeft   = x;
266         fTop    = y;
267         fRight  = Sk32_sat_add(x, width);
268         fBottom = Sk32_sat_add(y, height);
269     }
270 
setWHSkIRect271     void setWH(int32_t width, int32_t height) {
272         fLeft   = 0;
273         fTop    = 0;
274         fRight  = width;
275         fBottom = height;
276     }
277 
setSizeSkIRect278     void setSize(SkISize size) {
279         fLeft = 0;
280         fTop = 0;
281         fRight = size.width();
282         fBottom = size.height();
283     }
284 
285     /** Returns SkIRect offset by (dx, dy).
286 
287         If dx is negative, SkIRect returned is moved to the left.
288         If dx is positive, SkIRect returned is moved to the right.
289         If dy is negative, SkIRect returned is moved upward.
290         If dy is positive, SkIRect returned is moved downward.
291 
292         @param dx  offset added to fLeft and fRight
293         @param dy  offset added to fTop and fBottom
294         @return    SkIRect offset by dx and dy, with original width and height
295     */
makeOffsetSkIRect296     constexpr SkIRect makeOffset(int32_t dx, int32_t dy) const {
297         return {
298             Sk32_sat_add(fLeft,  dx), Sk32_sat_add(fTop,    dy),
299             Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),
300         };
301     }
302 
303     /** Returns SkIRect offset by (offset.x(), offset.y()).
304 
305         If offset.x() is negative, SkIRect returned is moved to the left.
306         If offset.x() is positive, SkIRect returned is moved to the right.
307         If offset.y() is negative, SkIRect returned is moved upward.
308         If offset.y() is positive, SkIRect returned is moved downward.
309 
310         @param offset  translation vector
311         @return    SkIRect translated by offset, with original width and height
312     */
makeOffsetSkIRect313     constexpr SkIRect makeOffset(SkIVector offset) const {
314         return this->makeOffset(offset.x(), offset.y());
315     }
316 
317     /** Returns SkIRect, inset by (dx, dy).
318 
319         If dx is negative, SkIRect returned is wider.
320         If dx is positive, SkIRect returned is narrower.
321         If dy is negative, SkIRect returned is taller.
322         If dy is positive, SkIRect returned is shorter.
323 
324         @param dx  offset added to fLeft and subtracted from fRight
325         @param dy  offset added to fTop and subtracted from fBottom
326         @return    SkIRect inset symmetrically left and right, top and bottom
327     */
makeInsetSkIRect328     SkIRect makeInset(int32_t dx, int32_t dy) const {
329         return {
330             Sk32_sat_add(fLeft,  dx), Sk32_sat_add(fTop,    dy),
331             Sk32_sat_sub(fRight, dx), Sk32_sat_sub(fBottom, dy),
332         };
333     }
334 
335     /** Returns SkIRect, outset by (dx, dy).
336 
337         If dx is negative, SkIRect returned is narrower.
338         If dx is positive, SkIRect returned is wider.
339         If dy is negative, SkIRect returned is shorter.
340         If dy is positive, SkIRect returned is taller.
341 
342         @param dx  offset subtracted to fLeft and added from fRight
343         @param dy  offset subtracted to fTop and added from fBottom
344         @return    SkIRect outset symmetrically left and right, top and bottom
345     */
makeOutsetSkIRect346     SkIRect makeOutset(int32_t dx, int32_t dy) const {
347         return {
348             Sk32_sat_sub(fLeft,  dx), Sk32_sat_sub(fTop,    dy),
349             Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),
350         };
351     }
352 
353     /** Offsets SkIRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
354 
355         If dx is negative, moves SkIRect returned to the left.
356         If dx is positive, moves SkIRect returned to the right.
357         If dy is negative, moves SkIRect returned upward.
358         If dy is positive, moves SkIRect returned downward.
359 
360         @param dx  offset added to fLeft and fRight
361         @param dy  offset added to fTop and fBottom
362     */
offsetSkIRect363     void offset(int32_t dx, int32_t dy) {
364         fLeft   = Sk32_sat_add(fLeft,   dx);
365         fTop    = Sk32_sat_add(fTop,    dy);
366         fRight  = Sk32_sat_add(fRight,  dx);
367         fBottom = Sk32_sat_add(fBottom, dy);
368     }
369 
370     /** Offsets SkIRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
371         fTop, fBottom.
372 
373         If delta.fX is negative, moves SkIRect returned to the left.
374         If delta.fX is positive, moves SkIRect returned to the right.
375         If delta.fY is negative, moves SkIRect returned upward.
376         If delta.fY is positive, moves SkIRect returned downward.
377 
378         @param delta  offset added to SkIRect
379     */
offsetSkIRect380     void offset(const SkIPoint& delta) {
381         this->offset(delta.fX, delta.fY);
382     }
383 
384     /** Offsets SkIRect so that fLeft equals newX, and fTop equals newY. width and height
385         are unchanged.
386 
387         @param newX  stored in fLeft, preserving width()
388         @param newY  stored in fTop, preserving height()
389     */
offsetToSkIRect390     void offsetTo(int32_t newX, int32_t newY) {
391         fRight  = Sk64_pin_to_s32((int64_t)fRight + newX - fLeft);
392         fBottom = Sk64_pin_to_s32((int64_t)fBottom + newY - fTop);
393         fLeft   = newX;
394         fTop    = newY;
395     }
396 
397     /** Insets SkIRect by (dx,dy).
398 
399         If dx is positive, makes SkIRect narrower.
400         If dx is negative, makes SkIRect wider.
401         If dy is positive, makes SkIRect shorter.
402         If dy is negative, makes SkIRect taller.
403 
404         @param dx  offset added to fLeft and subtracted from fRight
405         @param dy  offset added to fTop and subtracted from fBottom
406     */
insetSkIRect407     void inset(int32_t dx, int32_t dy) {
408         fLeft   = Sk32_sat_add(fLeft,   dx);
409         fTop    = Sk32_sat_add(fTop,    dy);
410         fRight  = Sk32_sat_sub(fRight,  dx);
411         fBottom = Sk32_sat_sub(fBottom, dy);
412     }
413 
414     /** Outsets SkIRect by (dx, dy).
415 
416         If dx is positive, makes SkIRect wider.
417         If dx is negative, makes SkIRect narrower.
418         If dy is positive, makes SkIRect taller.
419         If dy is negative, makes SkIRect shorter.
420 
421         @param dx  subtracted to fLeft and added from fRight
422         @param dy  subtracted to fTop and added from fBottom
423     */
outsetSkIRect424     void outset(int32_t dx, int32_t dy)  { this->inset(-dx, -dy); }
425 
426     /** Adjusts SkIRect by adding dL to fLeft, dT to fTop, dR to fRight, and dB to fBottom.
427 
428         If dL is positive, narrows SkIRect on the left. If negative, widens it on the left.
429         If dT is positive, shrinks SkIRect on the top. If negative, lengthens it on the top.
430         If dR is positive, narrows SkIRect on the right. If negative, widens it on the right.
431         If dB is positive, shrinks SkIRect on the bottom. If negative, lengthens it on the bottom.
432 
433         The resulting SkIRect is not checked for validity. Thus, if the resulting SkIRect left is
434         greater than right, the SkIRect will be considered empty. Call sort() after this call
435         if that is not the desired behavior.
436 
437         @param dL  offset added to fLeft
438         @param dT  offset added to fTop
439         @param dR  offset added to fRight
440         @param dB  offset added to fBottom
441     */
adjustSkIRect442     void adjust(int32_t dL, int32_t dT, int32_t dR, int32_t dB) {
443         fLeft   = Sk32_sat_add(fLeft,   dL);
444         fTop    = Sk32_sat_add(fTop,    dT);
445         fRight  = Sk32_sat_add(fRight,  dR);
446         fBottom = Sk32_sat_add(fBottom, dB);
447     }
448 
449     /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
450         Returns false if SkIRect is empty.
451 
452         Considers input to describe constructed SkIRect: (x, y, x + 1, y + 1) and
453         returns true if constructed area is completely enclosed by SkIRect area.
454 
455         @param x  test SkIPoint x-coordinate
456         @param y  test SkIPoint y-coordinate
457         @return   true if (x, y) is inside SkIRect
458     */
containsSkIRect459     bool contains(int32_t x, int32_t y) const {
460         return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
461     }
462 
463     /** Returns true if SkIRect contains r.
464      Returns false if SkIRect is empty or r is empty.
465 
466      SkIRect contains r when SkIRect area completely includes r area.
467 
468      @param r  SkIRect contained
469      @return   true if all sides of SkIRect are outside r
470      */
containsSkIRect471     bool contains(const SkIRect& r) const {
472         return  !r.isEmpty() && !this->isEmpty() &&     // check for empties
473                 fLeft <= r.fLeft && fTop <= r.fTop &&
474                 fRight >= r.fRight && fBottom >= r.fBottom;
475     }
476 
477     /** Returns true if SkIRect contains r.
478         Returns false if SkIRect is empty or r is empty.
479 
480         SkIRect contains r when SkIRect area completely includes r area.
481 
482         @param r  SkRect contained
483         @return   true if all sides of SkIRect are outside r
484     */
485     inline bool contains(const SkRect& r) const;
486 
487     /** Returns true if SkIRect contains construction.
488         Asserts if SkIRect is empty or construction is empty, and if SK_DEBUG is defined.
489 
490         Return is undefined if SkIRect is empty or construction is empty.
491 
492         @param r  SkIRect contained
493         @return   true if all sides of SkIRect are outside r
494     */
containsNoEmptyCheckSkIRect495     bool containsNoEmptyCheck(const SkIRect& r) const {
496         SkASSERT(fLeft < fRight && fTop < fBottom);
497         SkASSERT(r.fLeft < r.fRight && r.fTop < r.fBottom);
498         return fLeft <= r.fLeft && fTop <= r.fTop && fRight >= r.fRight && fBottom >= r.fBottom;
499     }
500 
501     /** Returns true if SkIRect intersects r, and sets SkIRect to intersection.
502         Returns false if SkIRect does not intersect r, and leaves SkIRect unchanged.
503 
504         Returns false if either r or SkIRect is empty, leaving SkIRect unchanged.
505 
506         @param r  limit of result
507         @return   true if r and SkIRect have area in common
508     */
intersectSkIRect509     bool intersect(const SkIRect& r) {
510         return this->intersect(*this, r);
511     }
512 
513     /** Returns true if a intersects b, and sets SkIRect to intersection.
514         Returns false if a does not intersect b, and leaves SkIRect unchanged.
515 
516         Returns false if either a or b is empty, leaving SkIRect unchanged.
517 
518         @param a  SkIRect to intersect
519         @param b  SkIRect to intersect
520         @return   true if a and b have area in common
521     */
522     bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& a, const SkIRect& b);
523 
524     /** Returns true if a intersects b.
525         Returns false if either a or b is empty, or do not intersect.
526 
527         @param a  SkIRect to intersect
528         @param b  SkIRect to intersect
529         @return   true if a and b have area in common
530     */
IntersectsSkIRect531     static bool Intersects(const SkIRect& a, const SkIRect& b) {
532         SkIRect dummy;
533         return dummy.intersect(a, b);
534     }
535 
536     /** Sets SkIRect to the union of itself and r.
537 
538      Has no effect if r is empty. Otherwise, if SkIRect is empty, sets SkIRect to r.
539 
540      @param r  expansion SkIRect
541 
542         example: https://fiddle.skia.org/c/@IRect_join_2
543      */
544     void join(const SkIRect& r);
545 
546     /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
547         fTop and fBottom if fTop is greater than fBottom. Result may be empty,
548         and width() and height() will be zero or positive.
549     */
sortSkIRect550     void sort() {
551         using std::swap;
552         if (fLeft > fRight) {
553             swap(fLeft, fRight);
554         }
555         if (fTop > fBottom) {
556             swap(fTop, fBottom);
557         }
558     }
559 
560     /** Returns SkIRect with fLeft and fRight swapped if fLeft is greater than fRight; and
561         with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
562         and width() and height() will be zero or positive.
563 
564         @return  sorted SkIRect
565     */
makeSortedSkIRect566     SkIRect makeSorted() const {
567         return MakeLTRB(std::min(fLeft, fRight), std::min(fTop, fBottom),
568                         std::max(fLeft, fRight), std::max(fTop, fBottom));
569     }
570 };
571 
572 /** \struct SkRect
573     SkRect holds four SkScalar coordinates describing the upper and
574     lower bounds of a rectangle. SkRect may be created from outer bounds or
575     from position, width, and height. SkRect describes an area; if its right
576     is less than or equal to its left, or if its bottom is less than or equal to
577     its top, it is considered empty.
578 */
579 struct SK_API SkRect {
580     SkScalar fLeft;   //!< smaller x-axis bounds
581     SkScalar fTop;    //!< smaller y-axis bounds
582     SkScalar fRight;  //!< larger x-axis bounds
583     SkScalar fBottom; //!< larger y-axis bounds
584 
585     /** Returns constructed SkRect set to (0, 0, 0, 0).
586         Many other rectangles are empty; if left is equal to or greater than right,
587         or if top is equal to or greater than bottom. Setting all members to zero
588         is a convenience, but does not designate a special empty rectangle.
589 
590         @return  bounds (0, 0, 0, 0)
591     */
MakeEmptySkRect592     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeEmpty() {
593         return SkRect{0, 0, 0, 0};
594     }
595 
596     /** Returns constructed SkRect set to SkScalar values (0, 0, w, h). Does not
597         validate input; w or h may be negative.
598 
599         Passing integer values may generate a compiler warning since SkRect cannot
600         represent 32-bit integers exactly. Use SkIRect for an exact integer rectangle.
601 
602         @param w  SkScalar width of constructed SkRect
603         @param h  SkScalar height of constructed SkRect
604         @return   bounds (0, 0, w, h)
605     */
MakeWHSkRect606     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeWH(SkScalar w, SkScalar h) {
607         return SkRect{0, 0, w, h};
608     }
609 
610     /** Returns constructed SkRect set to integer values (0, 0, w, h). Does not validate
611         input; w or h may be negative.
612 
613         Use to avoid a compiler warning that input may lose precision when stored.
614         Use SkIRect for an exact integer rectangle.
615 
616         @param w  integer width of constructed SkRect
617         @param h  integer height of constructed SkRect
618         @return   bounds (0, 0, w, h)
619     */
MakeIWHSkRect620     static SkRect SK_WARN_UNUSED_RESULT MakeIWH(int w, int h) {
621         return {0, 0, SkIntToScalar(w), SkIntToScalar(h)};
622     }
623 
624     /** Returns constructed SkRect set to (0, 0, size.width(), size.height()). Does not
625         validate input; size.width() or size.height() may be negative.
626 
627         @param size  SkScalar values for SkRect width and height
628         @return      bounds (0, 0, size.width(), size.height())
629     */
MakeSizeSkRect630     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeSize(const SkSize& size) {
631         return SkRect{0, 0, size.fWidth, size.fHeight};
632     }
633 
634     /** Returns constructed SkRect set to (l, t, r, b). Does not sort input; SkRect may
635         result in fLeft greater than fRight, or fTop greater than fBottom.
636 
637         @param l  SkScalar stored in fLeft
638         @param t  SkScalar stored in fTop
639         @param r  SkScalar stored in fRight
640         @param b  SkScalar stored in fBottom
641         @return   bounds (l, t, r, b)
642     */
MakeLTRBSkRect643     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeLTRB(SkScalar l, SkScalar t, SkScalar r,
644                                                            SkScalar b) {
645         return SkRect {l, t, r, b};
646     }
647 
648     /** Returns constructed SkRect set to (x, y, x + w, y + h).
649         Does not validate input; w or h may be negative.
650 
651         @param x  stored in fLeft
652         @param y  stored in fTop
653         @param w  added to x and stored in fRight
654         @param h  added to y and stored in fBottom
655         @return   bounds at (x, y) with width w and height h
656     */
MakeXYWHSkRect657     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeXYWH(SkScalar x, SkScalar y, SkScalar w,
658                                                            SkScalar h) {
659         return SkRect {x, y, x + w, y + h};
660     }
661 
662     /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
663         Does not validate input; size.width() or size.height() may be negative.
664 
665         @param size  integer values for SkRect width and height
666         @return      bounds (0, 0, size.width(), size.height())
667     */
MakeSkRect668     static SkRect Make(const SkISize& size) {
669         return MakeIWH(size.width(), size.height());
670     }
671 
672     /** Returns constructed SkIRect set to irect, promoting integers to scalar.
673         Does not validate input; fLeft may be greater than fRight, fTop may be greater
674         than fBottom.
675 
676         @param irect  integer unsorted bounds
677         @return       irect members converted to SkScalar
678     */
MakeSkRect679     static SkRect SK_WARN_UNUSED_RESULT Make(const SkIRect& irect) {
680         return {
681             SkIntToScalar(irect.fLeft), SkIntToScalar(irect.fTop),
682             SkIntToScalar(irect.fRight), SkIntToScalar(irect.fBottom)
683         };
684     }
685 
686     /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
687         to or greater than fBottom. Call sort() to reverse rectangles with negative
688         width() or height().
689 
690         @return  true if width() or height() are zero or negative
691     */
isEmptySkRect692     bool isEmpty() const {
693         // We write it as the NOT of a non-empty rect, so we will return true if any values
694         // are NaN.
695         return !(fLeft < fRight && fTop < fBottom);
696     }
697 
698     /** Returns true if fLeft is equal to or less than fRight, or if fTop is equal
699         to or less than fBottom. Call sort() to reverse rectangles with negative
700         width() or height().
701 
702         @return  true if width() or height() are zero or positive
703     */
isSortedSkRect704     bool isSorted() const { return fLeft <= fRight && fTop <= fBottom; }
705 
706     /** Returns true if all values in the rectangle are finite: SK_ScalarMin or larger,
707         and SK_ScalarMax or smaller.
708 
709         @return  true if no member is infinite or NaN
710     */
isFiniteSkRect711     bool isFinite() const {
712         float accum = 0;
713         accum *= fLeft;
714         accum *= fTop;
715         accum *= fRight;
716         accum *= fBottom;
717 
718         // accum is either NaN or it is finite (zero).
719         SkASSERT(0 == accum || SkScalarIsNaN(accum));
720 
721         // value==value will be true iff value is not NaN
722         // TODO: is it faster to say !accum or accum==accum?
723         return !SkScalarIsNaN(accum);
724     }
725 
726     /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
727         Call sort() to reverse fLeft and fRight if needed.
728 
729         @return  fLeft
730     */
xSkRect731     SkScalar    x() const { return fLeft; }
732 
733     /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
734         and sort() to reverse fTop and fBottom if needed.
735 
736         @return  fTop
737     */
ySkRect738     SkScalar    y() const { return fTop; }
739 
740     /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
741         Call sort() to reverse fLeft and fRight if needed.
742 
743         @return  fLeft
744     */
leftSkRect745     SkScalar    left() const { return fLeft; }
746 
747     /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
748         and sort() to reverse fTop and fBottom if needed.
749 
750         @return  fTop
751     */
topSkRect752     SkScalar    top() const { return fTop; }
753 
754     /** Returns right edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
755         Call sort() to reverse fLeft and fRight if needed.
756 
757         @return  fRight
758     */
rightSkRect759     SkScalar    right() const { return fRight; }
760 
761     /** Returns bottom edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
762         and sort() to reverse fTop and fBottom if needed.
763 
764         @return  fBottom
765     */
bottomSkRect766     SkScalar    bottom() const { return fBottom; }
767 
768     /** Returns span on the x-axis. This does not check if SkRect is sorted, or if
769         result fits in 32-bit float; result may be negative or infinity.
770 
771         @return  fRight minus fLeft
772     */
widthSkRect773     SkScalar    width() const { return fRight - fLeft; }
774 
775     /** Returns span on the y-axis. This does not check if SkRect is sorted, or if
776         result fits in 32-bit float; result may be negative or infinity.
777 
778         @return  fBottom minus fTop
779     */
heightSkRect780     SkScalar    height() const { return fBottom - fTop; }
781 
782     /** Returns average of left edge and right edge. Result does not change if SkRect
783         is sorted. Result may overflow to infinity if SkRect is far from the origin.
784 
785         @return  midpoint on x-axis
786     */
centerXSkRect787     SkScalar centerX() const {
788         // don't use SkScalarHalf(fLeft + fBottom) as that might overflow before the 0.5
789         return SkScalarHalf(fLeft) + SkScalarHalf(fRight);
790     }
791 
792     /** Returns average of top edge and bottom edge. Result does not change if SkRect
793         is sorted.
794 
795         @return  midpoint on y-axis
796     */
centerYSkRect797     SkScalar centerY() const {
798         // don't use SkScalarHalf(fTop + fBottom) as that might overflow before the 0.5
799         return SkScalarHalf(fTop) + SkScalarHalf(fBottom);
800     }
801 
802     /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
803         equal to the corresponding members in b.
804 
805         a and b are not equal if either contain NaN. a and b are equal if members
806         contain zeroes with different signs.
807 
808         @param a  SkRect to compare
809         @param b  SkRect to compare
810         @return   true if members are equal
811     */
812     friend bool operator==(const SkRect& a, const SkRect& b) {
813         return SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);
814     }
815 
816     /** Returns true if any in a: fLeft, fTop, fRight, and fBottom; does not
817         equal the corresponding members in b.
818 
819         a and b are not equal if either contain NaN. a and b are equal if members
820         contain zeroes with different signs.
821 
822         @param a  SkRect to compare
823         @param b  SkRect to compare
824         @return   true if members are not equal
825     */
826     friend bool operator!=(const SkRect& a, const SkRect& b) {
827         return !SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);
828     }
829 
830     /** Returns four points in quad that enclose SkRect ordered as: top-left, top-right,
831         bottom-right, bottom-left.
832 
833         TODO: Consider adding parameter to control whether quad is clockwise or counterclockwise.
834 
835         @param quad  storage for corners of SkRect
836 
837         example: https://fiddle.skia.org/c/@Rect_toQuad
838     */
839     void toQuad(SkPoint quad[4]) const;
840 
841     /** Sets SkRect to (0, 0, 0, 0).
842 
843         Many other rectangles are empty; if left is equal to or greater than right,
844         or if top is equal to or greater than bottom. Setting all members to zero
845         is a convenience, but does not designate a special empty rectangle.
846     */
setEmptySkRect847     void setEmpty() { *this = MakeEmpty(); }
848 
849     /** Sets SkRect to src, promoting src members from integer to scalar.
850         Very large values in src may lose precision.
851 
852         @param src  integer SkRect
853     */
setSkRect854     void set(const SkIRect& src) {
855         fLeft   = SkIntToScalar(src.fLeft);
856         fTop    = SkIntToScalar(src.fTop);
857         fRight  = SkIntToScalar(src.fRight);
858         fBottom = SkIntToScalar(src.fBottom);
859     }
860 
861     /** Sets SkRect to (left, top, right, bottom).
862         left and right are not sorted; left is not necessarily less than right.
863         top and bottom are not sorted; top is not necessarily less than bottom.
864 
865         @param left    stored in fLeft
866         @param top     stored in fTop
867         @param right   stored in fRight
868         @param bottom  stored in fBottom
869     */
setLTRBSkRect870     void setLTRB(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
871         fLeft   = left;
872         fTop    = top;
873         fRight  = right;
874         fBottom = bottom;
875     }
876 
877     /** Sets to bounds of SkPoint array with count entries. If count is zero or smaller,
878         or if SkPoint array contains an infinity or NaN, sets to (0, 0, 0, 0).
879 
880         Result is either empty or sorted: fLeft is less than or equal to fRight, and
881         fTop is less than or equal to fBottom.
882 
883         @param pts    SkPoint array
884         @param count  entries in array
885     */
setBoundsSkRect886     void setBounds(const SkPoint pts[], int count) {
887         (void)this->setBoundsCheck(pts, count);
888     }
889 
890     /** Sets to bounds of SkPoint array with count entries. Returns false if count is
891         zero or smaller, or if SkPoint array contains an infinity or NaN; in these cases
892         sets SkRect to (0, 0, 0, 0).
893 
894         Result is either empty or sorted: fLeft is less than or equal to fRight, and
895         fTop is less than or equal to fBottom.
896 
897         @param pts    SkPoint array
898         @param count  entries in array
899         @return       true if all SkPoint values are finite
900 
901         example: https://fiddle.skia.org/c/@Rect_setBoundsCheck
902     */
903     bool setBoundsCheck(const SkPoint pts[], int count);
904 
905     /** Sets to bounds of SkPoint pts array with count entries. If any SkPoint in pts
906         contains infinity or NaN, all SkRect dimensions are set to NaN.
907 
908         @param pts    SkPoint array
909         @param count  entries in array
910 
911         example: https://fiddle.skia.org/c/@Rect_setBoundsNoCheck
912     */
913     void setBoundsNoCheck(const SkPoint pts[], int count);
914 
915     /** Sets bounds to the smallest SkRect enclosing SkPoint p0 and p1. The result is
916         sorted and may be empty. Does not check to see if values are finite.
917 
918         @param p0  corner to include
919         @param p1  corner to include
920     */
setSkRect921     void set(const SkPoint& p0, const SkPoint& p1) {
922         fLeft =   std::min(p0.fX, p1.fX);
923         fRight =  std::max(p0.fX, p1.fX);
924         fTop =    std::min(p0.fY, p1.fY);
925         fBottom = std::max(p0.fY, p1.fY);
926     }
927 
928     /** Sets SkRect to (x, y, x + width, y + height).
929         Does not validate input; width or height may be negative.
930 
931         @param x       stored in fLeft
932         @param y       stored in fTop
933         @param width   added to x and stored in fRight
934         @param height  added to y and stored in fBottom
935     */
setXYWHSkRect936     void setXYWH(SkScalar x, SkScalar y, SkScalar width, SkScalar height) {
937         fLeft = x;
938         fTop = y;
939         fRight = x + width;
940         fBottom = y + height;
941     }
942 
943     /** Sets SkRect to (0, 0, width, height). Does not validate input;
944         width or height may be negative.
945 
946         @param width   stored in fRight
947         @param height  stored in fBottom
948     */
setWHSkRect949     void setWH(SkScalar width, SkScalar height) {
950         fLeft = 0;
951         fTop = 0;
952         fRight = width;
953         fBottom = height;
954     }
setIWHSkRect955     void setIWH(int32_t width, int32_t height) {
956         this->setWH(SkIntToScalar(width), SkIntToScalar(height));
957     }
958 
959     /** Returns SkRect offset by (dx, dy).
960 
961         If dx is negative, SkRect returned is moved to the left.
962         If dx is positive, SkRect returned is moved to the right.
963         If dy is negative, SkRect returned is moved upward.
964         If dy is positive, SkRect returned is moved downward.
965 
966         @param dx  added to fLeft and fRight
967         @param dy  added to fTop and fBottom
968         @return    SkRect offset on axes, with original width and height
969     */
makeOffsetSkRect970     constexpr SkRect makeOffset(SkScalar dx, SkScalar dy) const {
971         return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy);
972     }
973 
974     /** Returns SkRect offset by v.
975 
976         @param v  added to rect
977         @return    SkRect offset on axes, with original width and height
978     */
makeOffsetSkRect979     constexpr SkRect makeOffset(SkVector v) const { return this->makeOffset(v.x(), v.y()); }
980 
981     /** Returns SkRect, inset by (dx, dy).
982 
983         If dx is negative, SkRect returned is wider.
984         If dx is positive, SkRect returned is narrower.
985         If dy is negative, SkRect returned is taller.
986         If dy is positive, SkRect returned is shorter.
987 
988         @param dx  added to fLeft and subtracted from fRight
989         @param dy  added to fTop and subtracted from fBottom
990         @return    SkRect inset symmetrically left and right, top and bottom
991     */
makeInsetSkRect992     SkRect makeInset(SkScalar dx, SkScalar dy) const {
993         return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, fBottom - dy);
994     }
995 
996     /** Returns SkRect, outset by (dx, dy).
997 
998         If dx is negative, SkRect returned is narrower.
999         If dx is positive, SkRect returned is wider.
1000         If dy is negative, SkRect returned is shorter.
1001         If dy is positive, SkRect returned is taller.
1002 
1003         @param dx  subtracted to fLeft and added from fRight
1004         @param dy  subtracted to fTop and added from fBottom
1005         @return    SkRect outset symmetrically left and right, top and bottom
1006     */
makeOutsetSkRect1007     SkRect makeOutset(SkScalar dx, SkScalar dy) const {
1008         return MakeLTRB(fLeft - dx, fTop - dy, fRight + dx, fBottom + dy);
1009     }
1010 
1011     /** Offsets SkRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
1012 
1013         If dx is negative, moves SkRect to the left.
1014         If dx is positive, moves SkRect to the right.
1015         If dy is negative, moves SkRect upward.
1016         If dy is positive, moves SkRect downward.
1017 
1018         @param dx  offset added to fLeft and fRight
1019         @param dy  offset added to fTop and fBottom
1020     */
offsetSkRect1021     void offset(SkScalar dx, SkScalar dy) {
1022         fLeft   += dx;
1023         fTop    += dy;
1024         fRight  += dx;
1025         fBottom += dy;
1026     }
1027 
1028     /** Offsets SkRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
1029         fTop, fBottom.
1030 
1031         If delta.fX is negative, moves SkRect to the left.
1032         If delta.fX is positive, moves SkRect to the right.
1033         If delta.fY is negative, moves SkRect upward.
1034         If delta.fY is positive, moves SkRect downward.
1035 
1036         @param delta  added to SkRect
1037     */
offsetSkRect1038     void offset(const SkPoint& delta) {
1039         this->offset(delta.fX, delta.fY);
1040     }
1041 
1042     /** Offsets SkRect so that fLeft equals newX, and fTop equals newY. width and height
1043         are unchanged.
1044 
1045         @param newX  stored in fLeft, preserving width()
1046         @param newY  stored in fTop, preserving height()
1047     */
offsetToSkRect1048     void offsetTo(SkScalar newX, SkScalar newY) {
1049         fRight += newX - fLeft;
1050         fBottom += newY - fTop;
1051         fLeft = newX;
1052         fTop = newY;
1053     }
1054 
1055     /** Insets SkRect by (dx, dy).
1056 
1057         If dx is positive, makes SkRect narrower.
1058         If dx is negative, makes SkRect wider.
1059         If dy is positive, makes SkRect shorter.
1060         If dy is negative, makes SkRect taller.
1061 
1062         @param dx  added to fLeft and subtracted from fRight
1063         @param dy  added to fTop and subtracted from fBottom
1064     */
insetSkRect1065     void inset(SkScalar dx, SkScalar dy)  {
1066         fLeft   += dx;
1067         fTop    += dy;
1068         fRight  -= dx;
1069         fBottom -= dy;
1070     }
1071 
1072     /** Outsets SkRect by (dx, dy).
1073 
1074         If dx is positive, makes SkRect wider.
1075         If dx is negative, makes SkRect narrower.
1076         If dy is positive, makes SkRect taller.
1077         If dy is negative, makes SkRect shorter.
1078 
1079         @param dx  subtracted to fLeft and added from fRight
1080         @param dy  subtracted to fTop and added from fBottom
1081     */
outsetSkRect1082     void outset(SkScalar dx, SkScalar dy)  { this->inset(-dx, -dy); }
1083 
1084     /** Returns true if SkRect intersects r, and sets SkRect to intersection.
1085         Returns false if SkRect does not intersect r, and leaves SkRect unchanged.
1086 
1087         Returns false if either r or SkRect is empty, leaving SkRect unchanged.
1088 
1089         @param r  limit of result
1090         @return   true if r and SkRect have area in common
1091 
1092         example: https://fiddle.skia.org/c/@Rect_intersect
1093     */
1094     bool intersect(const SkRect& r);
1095 
1096     /** Returns true if a intersects b, and sets SkRect to intersection.
1097         Returns false if a does not intersect b, and leaves SkRect unchanged.
1098 
1099         Returns false if either a or b is empty, leaving SkRect unchanged.
1100 
1101         @param a  SkRect to intersect
1102         @param b  SkRect to intersect
1103         @return   true if a and b have area in common
1104     */
1105     bool SK_WARN_UNUSED_RESULT intersect(const SkRect& a, const SkRect& b);
1106 
1107 
1108 private:
IntersectsSkRect1109     static bool Intersects(SkScalar al, SkScalar at, SkScalar ar, SkScalar ab,
1110                            SkScalar bl, SkScalar bt, SkScalar br, SkScalar bb) {
1111         SkScalar L = std::max(al, bl);
1112         SkScalar R = std::min(ar, br);
1113         SkScalar T = std::max(at, bt);
1114         SkScalar B = std::min(ab, bb);
1115         return L < R && T < B;
1116     }
1117 
1118 public:
1119 
1120     /** Returns true if SkRect intersects r.
1121      Returns false if either r or SkRect is empty, or do not intersect.
1122 
1123      @param r  SkRect to intersect
1124      @return   true if r and SkRect have area in common
1125      */
intersectsSkRect1126     bool intersects(const SkRect& r) const {
1127         return Intersects(fLeft, fTop, fRight, fBottom,
1128                           r.fLeft, r.fTop, r.fRight, r.fBottom);
1129     }
1130 
1131     /** Returns true if a intersects b.
1132         Returns false if either a or b is empty, or do not intersect.
1133 
1134         @param a  SkRect to intersect
1135         @param b  SkRect to intersect
1136         @return   true if a and b have area in common
1137     */
IntersectsSkRect1138     static bool Intersects(const SkRect& a, const SkRect& b) {
1139         return Intersects(a.fLeft, a.fTop, a.fRight, a.fBottom,
1140                           b.fLeft, b.fTop, b.fRight, b.fBottom);
1141     }
1142 
1143     /** Sets SkRect to the union of itself and r.
1144 
1145         Has no effect if r is empty. Otherwise, if SkRect is empty, sets
1146         SkRect to r.
1147 
1148         @param r  expansion SkRect
1149 
1150         example: https://fiddle.skia.org/c/@Rect_join_2
1151     */
1152     void join(const SkRect& r);
1153 
1154     /** Sets SkRect to the union of itself and r.
1155 
1156         Asserts if r is empty and SK_DEBUG is defined.
1157         If SkRect is empty, sets SkRect to r.
1158 
1159         May produce incorrect results if r is empty.
1160 
1161         @param r  expansion SkRect
1162     */
joinNonEmptyArgSkRect1163     void joinNonEmptyArg(const SkRect& r) {
1164         SkASSERT(!r.isEmpty());
1165         // if we are empty, just assign
1166         if (fLeft >= fRight || fTop >= fBottom) {
1167             *this = r;
1168         } else {
1169             this->joinPossiblyEmptyRect(r);
1170         }
1171     }
1172 
1173     /** Sets SkRect to the union of itself and the construction.
1174 
1175         May produce incorrect results if SkRect or r is empty.
1176 
1177         @param r  expansion SkRect
1178     */
joinPossiblyEmptyRectSkRect1179     void joinPossiblyEmptyRect(const SkRect& r) {
1180         fLeft   = std::min(fLeft, r.left());
1181         fTop    = std::min(fTop, r.top());
1182         fRight  = std::max(fRight, r.right());
1183         fBottom = std::max(fBottom, r.bottom());
1184     }
1185 
1186     /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
1187         Returns false if SkRect is empty.
1188 
1189         @param x  test SkPoint x-coordinate
1190         @param y  test SkPoint y-coordinate
1191         @return   true if (x, y) is inside SkRect
1192     */
containsSkRect1193     bool contains(SkScalar x, SkScalar y) const {
1194         return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
1195     }
1196 
1197     /** Returns true if SkRect contains r.
1198         Returns false if SkRect is empty or r is empty.
1199 
1200         SkRect contains r when SkRect area completely includes r area.
1201 
1202         @param r  SkRect contained
1203         @return   true if all sides of SkRect are outside r
1204     */
containsSkRect1205     bool contains(const SkRect& r) const {
1206         // todo: can we eliminate the this->isEmpty check?
1207         return  !r.isEmpty() && !this->isEmpty() &&
1208                 fLeft <= r.fLeft && fTop <= r.fTop &&
1209                 fRight >= r.fRight && fBottom >= r.fBottom;
1210     }
1211 
1212     /** Returns true if SkRect contains r.
1213         Returns false if SkRect is empty or r is empty.
1214 
1215         SkRect contains r when SkRect area completely includes r area.
1216 
1217         @param r  SkIRect contained
1218         @return   true if all sides of SkRect are outside r
1219     */
containsSkRect1220     bool contains(const SkIRect& r) const {
1221         // todo: can we eliminate the this->isEmpty check?
1222         return  !r.isEmpty() && !this->isEmpty() &&
1223                 fLeft <= SkIntToScalar(r.fLeft) && fTop <= SkIntToScalar(r.fTop) &&
1224                 fRight >= SkIntToScalar(r.fRight) && fBottom >= SkIntToScalar(r.fBottom);
1225     }
1226 
1227     /** Sets SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1228         members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1229                         SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).
1230 
1231         @param dst  storage for SkIRect
1232     */
roundSkRect1233     void round(SkIRect* dst) const {
1234         SkASSERT(dst);
1235         dst->setLTRB(SkScalarRoundToInt(fLeft),  SkScalarRoundToInt(fTop),
1236                      SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom));
1237     }
1238 
1239     /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1240         up fRight and fBottom, using
1241         (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1242          SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1243 
1244         @param dst  storage for SkIRect
1245     */
roundOutSkRect1246     void roundOut(SkIRect* dst) const {
1247         SkASSERT(dst);
1248         dst->setLTRB(SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1249                      SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom));
1250     }
1251 
1252     /** Sets SkRect by discarding the fractional portion of fLeft and fTop; and rounding
1253         up fRight and fBottom, using
1254         (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1255          SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1256 
1257         @param dst  storage for SkRect
1258     */
roundOutSkRect1259     void roundOut(SkRect* dst) const {
1260         dst->setLTRB(SkScalarFloorToScalar(fLeft), SkScalarFloorToScalar(fTop),
1261                      SkScalarCeilToScalar(fRight), SkScalarCeilToScalar(fBottom));
1262     }
1263 
1264     /** Sets SkRect by rounding up fLeft and fTop; and discarding the fractional portion
1265         of fRight and fBottom, using
1266         (SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
1267          SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom)).
1268 
1269         @param dst  storage for SkIRect
1270     */
roundInSkRect1271     void roundIn(SkIRect* dst) const {
1272         SkASSERT(dst);
1273         dst->setLTRB(SkScalarCeilToInt(fLeft),   SkScalarCeilToInt(fTop),
1274                      SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom));
1275     }
1276 
1277     /** Returns SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1278         members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1279                         SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).
1280 
1281         @return  rounded SkIRect
1282     */
roundSkRect1283     SkIRect round() const {
1284         SkIRect ir;
1285         this->round(&ir);
1286         return ir;
1287     }
1288 
1289     /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1290         up fRight and fBottom, using
1291         (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1292          SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1293 
1294         @return  rounded SkIRect
1295     */
roundOutSkRect1296     SkIRect roundOut() const {
1297         SkIRect ir;
1298         this->roundOut(&ir);
1299         return ir;
1300     }
1301 
1302     /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
1303         fTop and fBottom if fTop is greater than fBottom. Result may be empty;
1304         and width() and height() will be zero or positive.
1305     */
sortSkRect1306     void sort() {
1307         using std::swap;
1308         if (fLeft > fRight) {
1309             swap(fLeft, fRight);
1310         }
1311 
1312         if (fTop > fBottom) {
1313             swap(fTop, fBottom);
1314         }
1315     }
1316 
1317     /** Returns SkRect with fLeft and fRight swapped if fLeft is greater than fRight; and
1318         with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
1319         and width() and height() will be zero or positive.
1320 
1321         @return  sorted SkRect
1322     */
makeSortedSkRect1323     SkRect makeSorted() const {
1324         return MakeLTRB(std::min(fLeft, fRight), std::min(fTop, fBottom),
1325                         std::max(fLeft, fRight), std::max(fTop, fBottom));
1326     }
1327 
1328     /** Returns pointer to first scalar in SkRect, to treat it as an array with four
1329         entries.
1330 
1331         @return  pointer to fLeft
1332     */
asScalarsSkRect1333     const SkScalar* asScalars() const { return &fLeft; }
1334 
1335     /** Writes text representation of SkRect to standard output. Set asHex to true to
1336         generate exact binary representations of floating point numbers.
1337 
1338         @param asHex  true if SkScalar values are written as hexadecimal
1339 
1340         example: https://fiddle.skia.org/c/@Rect_dump
1341     */
1342     void dump(bool asHex) const;
1343 
1344     /** Writes text representation of SkRect to standard output. The representation may be
1345         directly compiled as C++ code. Floating point values are written
1346         with limited precision; it may not be possible to reconstruct original SkRect
1347         from output.
1348     */
dumpSkRect1349     void dump() const { this->dump(false); }
1350 
1351     /** Writes text representation of SkRect to standard output. The representation may be
1352         directly compiled as C++ code. Floating point values are written
1353         in hexadecimal to preserve their exact bit pattern. The output reconstructs the
1354         original SkRect.
1355 
1356         Use instead of dump() when submitting
1357     */
dumpHexSkRect1358     void dumpHex() const { this->dump(true); }
1359 };
1360 
contains(const SkRect & r)1361 inline bool SkIRect::contains(const SkRect& r) const {
1362     return  !r.isEmpty() && !this->isEmpty() &&     // check for empties
1363             (SkScalar)fLeft <= r.fLeft && (SkScalar)fTop <= r.fTop &&
1364             (SkScalar)fRight >= r.fRight && (SkScalar)fBottom >= r.fBottom;
1365 }
1366 
1367 #endif
1368