• 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         return SkIRect{}.intersect(a, b);
533     }
534 
535     /** Sets SkIRect to the union of itself and r.
536 
537      Has no effect if r is empty. Otherwise, if SkIRect is empty, sets SkIRect to r.
538 
539      @param r  expansion SkIRect
540 
541         example: https://fiddle.skia.org/c/@IRect_join_2
542      */
543     void join(const SkIRect& r);
544 
545     /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
546         fTop and fBottom if fTop is greater than fBottom. Result may be empty,
547         and width() and height() will be zero or positive.
548     */
sortSkIRect549     void sort() {
550         using std::swap;
551         if (fLeft > fRight) {
552             swap(fLeft, fRight);
553         }
554         if (fTop > fBottom) {
555             swap(fTop, fBottom);
556         }
557     }
558 
559     /** Returns SkIRect with fLeft and fRight swapped if fLeft is greater than fRight; and
560         with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
561         and width() and height() will be zero or positive.
562 
563         @return  sorted SkIRect
564     */
makeSortedSkIRect565     SkIRect makeSorted() const {
566         return MakeLTRB(std::min(fLeft, fRight), std::min(fTop, fBottom),
567                         std::max(fLeft, fRight), std::max(fTop, fBottom));
568     }
569 };
570 
571 /** \struct SkRect
572     SkRect holds four SkScalar coordinates describing the upper and
573     lower bounds of a rectangle. SkRect may be created from outer bounds or
574     from position, width, and height. SkRect describes an area; if its right
575     is less than or equal to its left, or if its bottom is less than or equal to
576     its top, it is considered empty.
577 */
578 struct SK_API SkRect {
579     SkScalar fLeft;   //!< smaller x-axis bounds
580     SkScalar fTop;    //!< smaller y-axis bounds
581     SkScalar fRight;  //!< larger x-axis bounds
582     SkScalar fBottom; //!< larger y-axis bounds
583 
584     /** Returns constructed SkRect set to (0, 0, 0, 0).
585         Many other rectangles are empty; if left is equal to or greater than right,
586         or if top is equal to or greater than bottom. Setting all members to zero
587         is a convenience, but does not designate a special empty rectangle.
588 
589         @return  bounds (0, 0, 0, 0)
590     */
MakeEmptySkRect591     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeEmpty() {
592         return SkRect{0, 0, 0, 0};
593     }
594 
595     /** Returns constructed SkRect set to SkScalar values (0, 0, w, h). Does not
596         validate input; w or h may be negative.
597 
598         Passing integer values may generate a compiler warning since SkRect cannot
599         represent 32-bit integers exactly. Use SkIRect for an exact integer rectangle.
600 
601         @param w  SkScalar width of constructed SkRect
602         @param h  SkScalar height of constructed SkRect
603         @return   bounds (0, 0, w, h)
604     */
MakeWHSkRect605     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeWH(SkScalar w, SkScalar h) {
606         return SkRect{0, 0, w, h};
607     }
608 
609     /** Returns constructed SkRect set to integer values (0, 0, w, h). Does not validate
610         input; w or h may be negative.
611 
612         Use to avoid a compiler warning that input may lose precision when stored.
613         Use SkIRect for an exact integer rectangle.
614 
615         @param w  integer width of constructed SkRect
616         @param h  integer height of constructed SkRect
617         @return   bounds (0, 0, w, h)
618     */
MakeIWHSkRect619     static SkRect SK_WARN_UNUSED_RESULT MakeIWH(int w, int h) {
620         return {0, 0, SkIntToScalar(w), SkIntToScalar(h)};
621     }
622 
623     /** Returns constructed SkRect set to (0, 0, size.width(), size.height()). Does not
624         validate input; size.width() or size.height() may be negative.
625 
626         @param size  SkScalar values for SkRect width and height
627         @return      bounds (0, 0, size.width(), size.height())
628     */
MakeSizeSkRect629     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeSize(const SkSize& size) {
630         return SkRect{0, 0, size.fWidth, size.fHeight};
631     }
632 
633     /** Returns constructed SkRect set to (l, t, r, b). Does not sort input; SkRect may
634         result in fLeft greater than fRight, or fTop greater than fBottom.
635 
636         @param l  SkScalar stored in fLeft
637         @param t  SkScalar stored in fTop
638         @param r  SkScalar stored in fRight
639         @param b  SkScalar stored in fBottom
640         @return   bounds (l, t, r, b)
641     */
MakeLTRBSkRect642     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeLTRB(SkScalar l, SkScalar t, SkScalar r,
643                                                            SkScalar b) {
644         return SkRect {l, t, r, b};
645     }
646 
647     /** Returns constructed SkRect set to (x, y, x + w, y + h).
648         Does not validate input; w or h may be negative.
649 
650         @param x  stored in fLeft
651         @param y  stored in fTop
652         @param w  added to x and stored in fRight
653         @param h  added to y and stored in fBottom
654         @return   bounds at (x, y) with width w and height h
655     */
MakeXYWHSkRect656     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeXYWH(SkScalar x, SkScalar y, SkScalar w,
657                                                            SkScalar h) {
658         return SkRect {x, y, x + w, y + h};
659     }
660 
661     /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
662         Does not validate input; size.width() or size.height() may be negative.
663 
664         @param size  integer values for SkRect width and height
665         @return      bounds (0, 0, size.width(), size.height())
666     */
MakeSkRect667     static SkRect Make(const SkISize& size) {
668         return MakeIWH(size.width(), size.height());
669     }
670 
671     /** Returns constructed SkIRect set to irect, promoting integers to scalar.
672         Does not validate input; fLeft may be greater than fRight, fTop may be greater
673         than fBottom.
674 
675         @param irect  integer unsorted bounds
676         @return       irect members converted to SkScalar
677     */
MakeSkRect678     static SkRect SK_WARN_UNUSED_RESULT Make(const SkIRect& irect) {
679         return {
680             SkIntToScalar(irect.fLeft), SkIntToScalar(irect.fTop),
681             SkIntToScalar(irect.fRight), SkIntToScalar(irect.fBottom)
682         };
683     }
684 
685     /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
686         to or greater than fBottom. Call sort() to reverse rectangles with negative
687         width() or height().
688 
689         @return  true if width() or height() are zero or negative
690     */
isEmptySkRect691     bool isEmpty() const {
692         // We write it as the NOT of a non-empty rect, so we will return true if any values
693         // are NaN.
694         return !(fLeft < fRight && fTop < fBottom);
695     }
696 
697     /** Returns true if fLeft is equal to or less than fRight, or if fTop is equal
698         to or less than fBottom. Call sort() to reverse rectangles with negative
699         width() or height().
700 
701         @return  true if width() or height() are zero or positive
702     */
isSortedSkRect703     bool isSorted() const { return fLeft <= fRight && fTop <= fBottom; }
704 
705     /** Returns true if all values in the rectangle are finite: SK_ScalarMin or larger,
706         and SK_ScalarMax or smaller.
707 
708         @return  true if no member is infinite or NaN
709     */
isFiniteSkRect710     bool isFinite() const {
711         float accum = 0;
712         accum *= fLeft;
713         accum *= fTop;
714         accum *= fRight;
715         accum *= fBottom;
716 
717         // accum is either NaN or it is finite (zero).
718         SkASSERT(0 == accum || SkScalarIsNaN(accum));
719 
720         // value==value will be true iff value is not NaN
721         // TODO: is it faster to say !accum or accum==accum?
722         return !SkScalarIsNaN(accum);
723     }
724 
725     /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
726         Call sort() to reverse fLeft and fRight if needed.
727 
728         @return  fLeft
729     */
xSkRect730     SkScalar    x() const { return fLeft; }
731 
732     /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
733         and sort() to reverse fTop and fBottom if needed.
734 
735         @return  fTop
736     */
ySkRect737     SkScalar    y() const { return fTop; }
738 
739     /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
740         Call sort() to reverse fLeft and fRight if needed.
741 
742         @return  fLeft
743     */
leftSkRect744     SkScalar    left() const { return fLeft; }
745 
746     /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
747         and sort() to reverse fTop and fBottom if needed.
748 
749         @return  fTop
750     */
topSkRect751     SkScalar    top() const { return fTop; }
752 
753     /** Returns right edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
754         Call sort() to reverse fLeft and fRight if needed.
755 
756         @return  fRight
757     */
rightSkRect758     SkScalar    right() const { return fRight; }
759 
760     /** Returns bottom edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
761         and sort() to reverse fTop and fBottom if needed.
762 
763         @return  fBottom
764     */
bottomSkRect765     SkScalar    bottom() const { return fBottom; }
766 
767     /** Returns span on the x-axis. This does not check if SkRect is sorted, or if
768         result fits in 32-bit float; result may be negative or infinity.
769 
770         @return  fRight minus fLeft
771     */
widthSkRect772     SkScalar    width() const { return fRight - fLeft; }
773 
774     /** Returns span on the y-axis. This does not check if SkRect is sorted, or if
775         result fits in 32-bit float; result may be negative or infinity.
776 
777         @return  fBottom minus fTop
778     */
heightSkRect779     SkScalar    height() const { return fBottom - fTop; }
780 
781     /** Returns average of left edge and right edge. Result does not change if SkRect
782         is sorted. Result may overflow to infinity if SkRect is far from the origin.
783 
784         @return  midpoint on x-axis
785     */
centerXSkRect786     SkScalar centerX() const {
787         // don't use SkScalarHalf(fLeft + fBottom) as that might overflow before the 0.5
788         return SkScalarHalf(fLeft) + SkScalarHalf(fRight);
789     }
790 
791     /** Returns average of top edge and bottom edge. Result does not change if SkRect
792         is sorted.
793 
794         @return  midpoint on y-axis
795     */
centerYSkRect796     SkScalar centerY() const {
797         // don't use SkScalarHalf(fTop + fBottom) as that might overflow before the 0.5
798         return SkScalarHalf(fTop) + SkScalarHalf(fBottom);
799     }
800 
801     /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
802         equal to the corresponding members in b.
803 
804         a and b are not equal if either contain NaN. a and b are equal if members
805         contain zeroes with different signs.
806 
807         @param a  SkRect to compare
808         @param b  SkRect to compare
809         @return   true if members are equal
810     */
811     friend bool operator==(const SkRect& a, const SkRect& b) {
812         return SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);
813     }
814 
815     /** Returns true if any in a: fLeft, fTop, fRight, and fBottom; does not
816         equal the corresponding members in b.
817 
818         a and b are not equal if either contain NaN. a and b are equal if members
819         contain zeroes with different signs.
820 
821         @param a  SkRect to compare
822         @param b  SkRect to compare
823         @return   true if members are not equal
824     */
825     friend bool operator!=(const SkRect& a, const SkRect& b) {
826         return !SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);
827     }
828 
829     /** Returns four points in quad that enclose SkRect ordered as: top-left, top-right,
830         bottom-right, bottom-left.
831 
832         TODO: Consider adding parameter to control whether quad is clockwise or counterclockwise.
833 
834         @param quad  storage for corners of SkRect
835 
836         example: https://fiddle.skia.org/c/@Rect_toQuad
837     */
838     void toQuad(SkPoint quad[4]) const;
839 
840     /** Sets SkRect to (0, 0, 0, 0).
841 
842         Many other rectangles are empty; if left is equal to or greater than right,
843         or if top is equal to or greater than bottom. Setting all members to zero
844         is a convenience, but does not designate a special empty rectangle.
845     */
setEmptySkRect846     void setEmpty() { *this = MakeEmpty(); }
847 
848     /** Sets SkRect to src, promoting src members from integer to scalar.
849         Very large values in src may lose precision.
850 
851         @param src  integer SkRect
852     */
setSkRect853     void set(const SkIRect& src) {
854         fLeft   = SkIntToScalar(src.fLeft);
855         fTop    = SkIntToScalar(src.fTop);
856         fRight  = SkIntToScalar(src.fRight);
857         fBottom = SkIntToScalar(src.fBottom);
858     }
859 
860     /** Sets SkRect to (left, top, right, bottom).
861         left and right are not sorted; left is not necessarily less than right.
862         top and bottom are not sorted; top is not necessarily less than bottom.
863 
864         @param left    stored in fLeft
865         @param top     stored in fTop
866         @param right   stored in fRight
867         @param bottom  stored in fBottom
868     */
setLTRBSkRect869     void setLTRB(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
870         fLeft   = left;
871         fTop    = top;
872         fRight  = right;
873         fBottom = bottom;
874     }
875 
876     /** Sets to bounds of SkPoint array with count entries. If count is zero or smaller,
877         or if SkPoint array contains an infinity or NaN, sets 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     */
setBoundsSkRect885     void setBounds(const SkPoint pts[], int count) {
886         (void)this->setBoundsCheck(pts, count);
887     }
888 
889     /** Sets to bounds of SkPoint array with count entries. Returns false if count is
890         zero or smaller, or if SkPoint array contains an infinity or NaN; in these cases
891         sets SkRect to (0, 0, 0, 0).
892 
893         Result is either empty or sorted: fLeft is less than or equal to fRight, and
894         fTop is less than or equal to fBottom.
895 
896         @param pts    SkPoint array
897         @param count  entries in array
898         @return       true if all SkPoint values are finite
899 
900         example: https://fiddle.skia.org/c/@Rect_setBoundsCheck
901     */
902     bool setBoundsCheck(const SkPoint pts[], int count);
903 
904     /** Sets to bounds of SkPoint pts array with count entries. If any SkPoint in pts
905         contains infinity or NaN, all SkRect dimensions are set to NaN.
906 
907         @param pts    SkPoint array
908         @param count  entries in array
909 
910         example: https://fiddle.skia.org/c/@Rect_setBoundsNoCheck
911     */
912     void setBoundsNoCheck(const SkPoint pts[], int count);
913 
914     /** Sets bounds to the smallest SkRect enclosing SkPoint p0 and p1. The result is
915         sorted and may be empty. Does not check to see if values are finite.
916 
917         @param p0  corner to include
918         @param p1  corner to include
919     */
setSkRect920     void set(const SkPoint& p0, const SkPoint& p1) {
921         fLeft =   std::min(p0.fX, p1.fX);
922         fRight =  std::max(p0.fX, p1.fX);
923         fTop =    std::min(p0.fY, p1.fY);
924         fBottom = std::max(p0.fY, p1.fY);
925     }
926 
927     /** Sets SkRect to (x, y, x + width, y + height).
928         Does not validate input; width or height may be negative.
929 
930         @param x       stored in fLeft
931         @param y       stored in fTop
932         @param width   added to x and stored in fRight
933         @param height  added to y and stored in fBottom
934     */
setXYWHSkRect935     void setXYWH(SkScalar x, SkScalar y, SkScalar width, SkScalar height) {
936         fLeft = x;
937         fTop = y;
938         fRight = x + width;
939         fBottom = y + height;
940     }
941 
942     /** Sets SkRect to (0, 0, width, height). Does not validate input;
943         width or height may be negative.
944 
945         @param width   stored in fRight
946         @param height  stored in fBottom
947     */
setWHSkRect948     void setWH(SkScalar width, SkScalar height) {
949         fLeft = 0;
950         fTop = 0;
951         fRight = width;
952         fBottom = height;
953     }
setIWHSkRect954     void setIWH(int32_t width, int32_t height) {
955         this->setWH(SkIntToScalar(width), SkIntToScalar(height));
956     }
957 
958     /** Returns SkRect offset by (dx, dy).
959 
960         If dx is negative, SkRect returned is moved to the left.
961         If dx is positive, SkRect returned is moved to the right.
962         If dy is negative, SkRect returned is moved upward.
963         If dy is positive, SkRect returned is moved downward.
964 
965         @param dx  added to fLeft and fRight
966         @param dy  added to fTop and fBottom
967         @return    SkRect offset on axes, with original width and height
968     */
makeOffsetSkRect969     constexpr SkRect makeOffset(SkScalar dx, SkScalar dy) const {
970         return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy);
971     }
972 
973     /** Returns SkRect offset by v.
974 
975         @param v  added to rect
976         @return    SkRect offset on axes, with original width and height
977     */
makeOffsetSkRect978     constexpr SkRect makeOffset(SkVector v) const { return this->makeOffset(v.x(), v.y()); }
979 
980     /** Returns SkRect, inset by (dx, dy).
981 
982         If dx is negative, SkRect returned is wider.
983         If dx is positive, SkRect returned is narrower.
984         If dy is negative, SkRect returned is taller.
985         If dy is positive, SkRect returned is shorter.
986 
987         @param dx  added to fLeft and subtracted from fRight
988         @param dy  added to fTop and subtracted from fBottom
989         @return    SkRect inset symmetrically left and right, top and bottom
990     */
makeInsetSkRect991     SkRect makeInset(SkScalar dx, SkScalar dy) const {
992         return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, fBottom - dy);
993     }
994 
995     /** Returns SkRect, outset by (dx, dy).
996 
997         If dx is negative, SkRect returned is narrower.
998         If dx is positive, SkRect returned is wider.
999         If dy is negative, SkRect returned is shorter.
1000         If dy is positive, SkRect returned is taller.
1001 
1002         @param dx  subtracted to fLeft and added from fRight
1003         @param dy  subtracted to fTop and added from fBottom
1004         @return    SkRect outset symmetrically left and right, top and bottom
1005     */
makeOutsetSkRect1006     SkRect makeOutset(SkScalar dx, SkScalar dy) const {
1007         return MakeLTRB(fLeft - dx, fTop - dy, fRight + dx, fBottom + dy);
1008     }
1009 
1010     /** Offsets SkRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
1011 
1012         If dx is negative, moves SkRect to the left.
1013         If dx is positive, moves SkRect to the right.
1014         If dy is negative, moves SkRect upward.
1015         If dy is positive, moves SkRect downward.
1016 
1017         @param dx  offset added to fLeft and fRight
1018         @param dy  offset added to fTop and fBottom
1019     */
offsetSkRect1020     void offset(SkScalar dx, SkScalar dy) {
1021         fLeft   += dx;
1022         fTop    += dy;
1023         fRight  += dx;
1024         fBottom += dy;
1025     }
1026 
1027     /** Offsets SkRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
1028         fTop, fBottom.
1029 
1030         If delta.fX is negative, moves SkRect to the left.
1031         If delta.fX is positive, moves SkRect to the right.
1032         If delta.fY is negative, moves SkRect upward.
1033         If delta.fY is positive, moves SkRect downward.
1034 
1035         @param delta  added to SkRect
1036     */
offsetSkRect1037     void offset(const SkPoint& delta) {
1038         this->offset(delta.fX, delta.fY);
1039     }
1040 
1041     /** Offsets SkRect so that fLeft equals newX, and fTop equals newY. width and height
1042         are unchanged.
1043 
1044         @param newX  stored in fLeft, preserving width()
1045         @param newY  stored in fTop, preserving height()
1046     */
offsetToSkRect1047     void offsetTo(SkScalar newX, SkScalar newY) {
1048         fRight += newX - fLeft;
1049         fBottom += newY - fTop;
1050         fLeft = newX;
1051         fTop = newY;
1052     }
1053 
1054     /** Insets SkRect by (dx, dy).
1055 
1056         If dx is positive, makes SkRect narrower.
1057         If dx is negative, makes SkRect wider.
1058         If dy is positive, makes SkRect shorter.
1059         If dy is negative, makes SkRect taller.
1060 
1061         @param dx  added to fLeft and subtracted from fRight
1062         @param dy  added to fTop and subtracted from fBottom
1063     */
insetSkRect1064     void inset(SkScalar dx, SkScalar dy)  {
1065         fLeft   += dx;
1066         fTop    += dy;
1067         fRight  -= dx;
1068         fBottom -= dy;
1069     }
1070 
1071     /** Outsets SkRect by (dx, dy).
1072 
1073         If dx is positive, makes SkRect wider.
1074         If dx is negative, makes SkRect narrower.
1075         If dy is positive, makes SkRect taller.
1076         If dy is negative, makes SkRect shorter.
1077 
1078         @param dx  subtracted to fLeft and added from fRight
1079         @param dy  subtracted to fTop and added from fBottom
1080     */
outsetSkRect1081     void outset(SkScalar dx, SkScalar dy)  { this->inset(-dx, -dy); }
1082 
1083     /** Returns true if SkRect intersects r, and sets SkRect to intersection.
1084         Returns false if SkRect does not intersect r, and leaves SkRect unchanged.
1085 
1086         Returns false if either r or SkRect is empty, leaving SkRect unchanged.
1087 
1088         @param r  limit of result
1089         @return   true if r and SkRect have area in common
1090 
1091         example: https://fiddle.skia.org/c/@Rect_intersect
1092     */
1093     bool intersect(const SkRect& r);
1094 
1095     /** Returns true if a intersects b, and sets SkRect to intersection.
1096         Returns false if a does not intersect b, and leaves SkRect unchanged.
1097 
1098         Returns false if either a or b is empty, leaving SkRect unchanged.
1099 
1100         @param a  SkRect to intersect
1101         @param b  SkRect to intersect
1102         @return   true if a and b have area in common
1103     */
1104     bool SK_WARN_UNUSED_RESULT intersect(const SkRect& a, const SkRect& b);
1105 
1106 
1107 private:
IntersectsSkRect1108     static bool Intersects(SkScalar al, SkScalar at, SkScalar ar, SkScalar ab,
1109                            SkScalar bl, SkScalar bt, SkScalar br, SkScalar bb) {
1110         SkScalar L = std::max(al, bl);
1111         SkScalar R = std::min(ar, br);
1112         SkScalar T = std::max(at, bt);
1113         SkScalar B = std::min(ab, bb);
1114         return L < R && T < B;
1115     }
1116 
1117 public:
1118 
1119     /** Returns true if SkRect intersects r.
1120      Returns false if either r or SkRect is empty, or do not intersect.
1121 
1122      @param r  SkRect to intersect
1123      @return   true if r and SkRect have area in common
1124      */
intersectsSkRect1125     bool intersects(const SkRect& r) const {
1126         return Intersects(fLeft, fTop, fRight, fBottom,
1127                           r.fLeft, r.fTop, r.fRight, r.fBottom);
1128     }
1129 
1130     /** Returns true if a intersects b.
1131         Returns false if either a or b is empty, or do not intersect.
1132 
1133         @param a  SkRect to intersect
1134         @param b  SkRect to intersect
1135         @return   true if a and b have area in common
1136     */
IntersectsSkRect1137     static bool Intersects(const SkRect& a, const SkRect& b) {
1138         return Intersects(a.fLeft, a.fTop, a.fRight, a.fBottom,
1139                           b.fLeft, b.fTop, b.fRight, b.fBottom);
1140     }
1141 
1142     /** Sets SkRect to the union of itself and r.
1143 
1144         Has no effect if r is empty. Otherwise, if SkRect is empty, sets
1145         SkRect to r.
1146 
1147         @param r  expansion SkRect
1148 
1149         example: https://fiddle.skia.org/c/@Rect_join_2
1150     */
1151     void join(const SkRect& r);
1152 
1153     /** Sets SkRect to the union of itself and r.
1154 
1155         Asserts if r is empty and SK_DEBUG is defined.
1156         If SkRect is empty, sets SkRect to r.
1157 
1158         May produce incorrect results if r is empty.
1159 
1160         @param r  expansion SkRect
1161     */
joinNonEmptyArgSkRect1162     void joinNonEmptyArg(const SkRect& r) {
1163         SkASSERT(!r.isEmpty());
1164         // if we are empty, just assign
1165         if (fLeft >= fRight || fTop >= fBottom) {
1166             *this = r;
1167         } else {
1168             this->joinPossiblyEmptyRect(r);
1169         }
1170     }
1171 
1172     /** Sets SkRect to the union of itself and the construction.
1173 
1174         May produce incorrect results if SkRect or r is empty.
1175 
1176         @param r  expansion SkRect
1177     */
joinPossiblyEmptyRectSkRect1178     void joinPossiblyEmptyRect(const SkRect& r) {
1179         fLeft   = std::min(fLeft, r.left());
1180         fTop    = std::min(fTop, r.top());
1181         fRight  = std::max(fRight, r.right());
1182         fBottom = std::max(fBottom, r.bottom());
1183     }
1184 
1185     /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
1186         Returns false if SkRect is empty.
1187 
1188         @param x  test SkPoint x-coordinate
1189         @param y  test SkPoint y-coordinate
1190         @return   true if (x, y) is inside SkRect
1191     */
containsSkRect1192     bool contains(SkScalar x, SkScalar y) const {
1193         return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
1194     }
1195 
1196     /** Returns true if SkRect contains r.
1197         Returns false if SkRect is empty or r is empty.
1198 
1199         SkRect contains r when SkRect area completely includes r area.
1200 
1201         @param r  SkRect contained
1202         @return   true if all sides of SkRect are outside r
1203     */
containsSkRect1204     bool contains(const SkRect& r) const {
1205         // todo: can we eliminate the this->isEmpty check?
1206         return  !r.isEmpty() && !this->isEmpty() &&
1207                 fLeft <= r.fLeft && fTop <= r.fTop &&
1208                 fRight >= r.fRight && fBottom >= r.fBottom;
1209     }
1210 
1211     /** Returns true if SkRect contains r.
1212         Returns false if SkRect is empty or r is empty.
1213 
1214         SkRect contains r when SkRect area completely includes r area.
1215 
1216         @param r  SkIRect contained
1217         @return   true if all sides of SkRect are outside r
1218     */
containsSkRect1219     bool contains(const SkIRect& r) const {
1220         // todo: can we eliminate the this->isEmpty check?
1221         return  !r.isEmpty() && !this->isEmpty() &&
1222                 fLeft <= SkIntToScalar(r.fLeft) && fTop <= SkIntToScalar(r.fTop) &&
1223                 fRight >= SkIntToScalar(r.fRight) && fBottom >= SkIntToScalar(r.fBottom);
1224     }
1225 
1226     /** Sets SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1227         members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1228                         SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).
1229 
1230         @param dst  storage for SkIRect
1231     */
roundSkRect1232     void round(SkIRect* dst) const {
1233         SkASSERT(dst);
1234         dst->setLTRB(SkScalarRoundToInt(fLeft),  SkScalarRoundToInt(fTop),
1235                      SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom));
1236     }
1237 
1238     /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1239         up fRight and fBottom, using
1240         (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1241          SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1242 
1243         @param dst  storage for SkIRect
1244     */
roundOutSkRect1245     void roundOut(SkIRect* dst) const {
1246         SkASSERT(dst);
1247         dst->setLTRB(SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1248                      SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom));
1249     }
1250 
1251     /** Sets SkRect by discarding the fractional portion of fLeft and fTop; and rounding
1252         up fRight and fBottom, using
1253         (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1254          SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1255 
1256         @param dst  storage for SkRect
1257     */
roundOutSkRect1258     void roundOut(SkRect* dst) const {
1259         dst->setLTRB(SkScalarFloorToScalar(fLeft), SkScalarFloorToScalar(fTop),
1260                      SkScalarCeilToScalar(fRight), SkScalarCeilToScalar(fBottom));
1261     }
1262 
1263     /** Sets SkRect by rounding up fLeft and fTop; and discarding the fractional portion
1264         of fRight and fBottom, using
1265         (SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
1266          SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom)).
1267 
1268         @param dst  storage for SkIRect
1269     */
roundInSkRect1270     void roundIn(SkIRect* dst) const {
1271         SkASSERT(dst);
1272         dst->setLTRB(SkScalarCeilToInt(fLeft),   SkScalarCeilToInt(fTop),
1273                      SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom));
1274     }
1275 
1276     /** Returns SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1277         members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1278                         SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).
1279 
1280         @return  rounded SkIRect
1281     */
roundSkRect1282     SkIRect round() const {
1283         SkIRect ir;
1284         this->round(&ir);
1285         return ir;
1286     }
1287 
1288     /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1289         up fRight and fBottom, using
1290         (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1291          SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1292 
1293         @return  rounded SkIRect
1294     */
roundOutSkRect1295     SkIRect roundOut() const {
1296         SkIRect ir;
1297         this->roundOut(&ir);
1298         return ir;
1299     }
1300     /** Sets SkIRect by rounding up fLeft and fTop; and discarding the fractional portion
1301         of fRight and fBottom, using
1302         (SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
1303          SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom)).
1304 
1305         @return  rounded SkIRect
1306     */
roundInSkRect1307     SkIRect roundIn() const {
1308         SkIRect ir;
1309         this->roundIn(&ir);
1310         return ir;
1311     }
1312 
1313     /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
1314         fTop and fBottom if fTop is greater than fBottom. Result may be empty;
1315         and width() and height() will be zero or positive.
1316     */
sortSkRect1317     void sort() {
1318         using std::swap;
1319         if (fLeft > fRight) {
1320             swap(fLeft, fRight);
1321         }
1322 
1323         if (fTop > fBottom) {
1324             swap(fTop, fBottom);
1325         }
1326     }
1327 
1328     /** Returns SkRect with fLeft and fRight swapped if fLeft is greater than fRight; and
1329         with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
1330         and width() and height() will be zero or positive.
1331 
1332         @return  sorted SkRect
1333     */
makeSortedSkRect1334     SkRect makeSorted() const {
1335         return MakeLTRB(std::min(fLeft, fRight), std::min(fTop, fBottom),
1336                         std::max(fLeft, fRight), std::max(fTop, fBottom));
1337     }
1338 
1339     /** Returns pointer to first scalar in SkRect, to treat it as an array with four
1340         entries.
1341 
1342         @return  pointer to fLeft
1343     */
asScalarsSkRect1344     const SkScalar* asScalars() const { return &fLeft; }
1345 
1346     /** Writes text representation of SkRect to standard output. Set asHex to true to
1347         generate exact binary representations of floating point numbers.
1348 
1349         @param asHex  true if SkScalar values are written as hexadecimal
1350 
1351         example: https://fiddle.skia.org/c/@Rect_dump
1352     */
1353     void dump(bool asHex) const;
1354 
1355     /** Writes text representation of SkRect to standard output. The representation may be
1356         directly compiled as C++ code. Floating point values are written
1357         with limited precision; it may not be possible to reconstruct original SkRect
1358         from output.
1359     */
dumpSkRect1360     void dump() const { this->dump(false); }
1361 
1362     /** Writes text representation of SkRect to standard output. The representation may be
1363         directly compiled as C++ code. Floating point values are written
1364         in hexadecimal to preserve their exact bit pattern. The output reconstructs the
1365         original SkRect.
1366 
1367         Use instead of dump() when submitting
1368     */
dumpHexSkRect1369     void dumpHex() const { this->dump(true); }
1370 };
1371 
contains(const SkRect & r)1372 inline bool SkIRect::contains(const SkRect& r) const {
1373     return  !r.isEmpty() && !this->isEmpty() &&     // check for empties
1374             (SkScalar)fLeft <= r.fLeft && (SkScalar)fTop <= r.fTop &&
1375             (SkScalar)fRight >= r.fRight && (SkScalar)fBottom >= r.fBottom;
1376 }
1377 
1378 #endif
1379