• 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/SkScalar.h"
13 #include "include/core/SkSize.h"
14 #include "include/core/SkTypes.h"
15 #include "include/private/base/SkSafe32.h"
16 #include "include/private/base/SkTFitsIn.h"
17 
18 #include <string>
19 #include <algorithm>
20 #include <cstdint>
21 
22 struct SkRect;
23 
24 /** \struct SkIRect
25     SkIRect holds four 32-bit integer coordinates describing the upper and
26     lower bounds of a rectangle. SkIRect may be created from outer bounds or
27     from position, width, and height. SkIRect describes an area; if its right
28     is less than or equal to its left, or if its bottom is less than or equal to
29     its top, it is considered empty.
30 */
31 struct SK_API SkIRect {
32     int32_t fLeft;   //!< smaller x-axis bounds
33     int32_t fTop;    //!< smaller y-axis bounds
34     int32_t fRight;  //!< larger x-axis bounds
35     int32_t fBottom; //!< larger y-axis bounds
36 
37     /** Returns constructed SkIRect set to (0, 0, 0, 0).
38         Many other rectangles are empty; if left is equal to or greater than right,
39         or if top is equal to or greater than bottom. Setting all members to zero
40         is a convenience, but does not designate a special empty rectangle.
41 
42         @return  bounds (0, 0, 0, 0)
43     */
MakeEmptySkIRect44     static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeEmpty() {
45         return SkIRect{0, 0, 0, 0};
46     }
47 
48     /** Returns constructed SkIRect set to (0, 0, w, h). Does not validate input; w or h
49         may be negative.
50 
51         @param w  width of constructed SkIRect
52         @param h  height of constructed SkIRect
53         @return   bounds (0, 0, w, h)
54     */
MakeWHSkIRect55     static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeWH(int32_t w, int32_t h) {
56         return SkIRect{0, 0, w, h};
57     }
58 
59     /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
60         Does not validate input; size.width() or size.height() may be negative.
61 
62         @param size  values for SkIRect width and height
63         @return      bounds (0, 0, size.width(), size.height())
64     */
MakeSizeSkIRect65     static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeSize(const SkISize& size) {
66         return SkIRect{0, 0, size.fWidth, size.fHeight};
67     }
68 
69     /** Returns constructed SkIRect set to (pt.x(), pt.y(), pt.x() + size.width(),
70         pt.y() + size.height()). Does not validate input; size.width() or size.height() may be
71         negative.
72 
73         @param pt    values for SkIRect fLeft and fTop
74         @param size  values for SkIRect width and height
75         @return      bounds at pt with width and height of size
76     */
MakePtSizeSkIRect77     static constexpr SkIRect SK_WARN_UNUSED_RESULT MakePtSize(SkIPoint pt, SkISize size) {
78         return MakeXYWH(pt.x(), pt.y(), size.width(), size.height());
79     }
80 
81     /** Returns constructed SkIRect set to (l, t, r, b). Does not sort input; SkIRect may
82         result in fLeft greater than fRight, or fTop greater than fBottom.
83 
84         @param l  integer stored in fLeft
85         @param t  integer stored in fTop
86         @param r  integer stored in fRight
87         @param b  integer stored in fBottom
88         @return   bounds (l, t, r, b)
89     */
MakeLTRBSkIRect90     static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeLTRB(int32_t l, int32_t t,
91                                                             int32_t r, int32_t b) {
92         return SkIRect{l, t, r, b};
93     }
94 
95     /** Returns constructed SkIRect set to: (x, y, x + w, y + h).
96         Does not validate input; w or h may be negative.
97 
98         @param x  stored in fLeft
99         @param y  stored in fTop
100         @param w  added to x and stored in fRight
101         @param h  added to y and stored in fBottom
102         @return   bounds at (x, y) with width w and height h
103     */
MakeXYWHSkIRect104     static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeXYWH(int32_t x, int32_t y,
105                                                             int32_t w, int32_t h) {
106         return { x, y, Sk32_sat_add(x, w), Sk32_sat_add(y, h) };
107     }
108 
109     /** Returns left edge of SkIRect, if sorted.
110         Call sort() to reverse fLeft and fRight if needed.
111 
112         @return  fLeft
113     */
leftSkIRect114     constexpr int32_t left() const { return fLeft; }
115 
116     /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
117         and sort() to reverse fTop and fBottom if needed.
118 
119         @return  fTop
120     */
topSkIRect121     constexpr int32_t top() const { return fTop; }
122 
123     /** Returns right edge of SkIRect, if sorted.
124         Call sort() to reverse fLeft and fRight if needed.
125 
126         @return  fRight
127     */
rightSkIRect128     constexpr int32_t right() const { return fRight; }
129 
130     /** Returns bottom edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
131         and sort() to reverse fTop and fBottom if needed.
132 
133         @return  fBottom
134     */
bottomSkIRect135     constexpr int32_t bottom() const { return fBottom; }
136 
137     /** Returns left edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
138         and sort() to reverse fLeft and fRight if needed.
139 
140         @return  fLeft
141     */
xSkIRect142     constexpr int32_t x() const { return fLeft; }
143 
144     /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
145         and sort() to reverse fTop and fBottom if needed.
146 
147         @return  fTop
148     */
ySkIRect149     constexpr int32_t y() const { return fTop; }
150 
151     // Experimental
topLeftSkIRect152     constexpr SkIPoint topLeft() const { return {fLeft, fTop}; }
153 
154     /** Returns span on the x-axis. This does not check if SkIRect is sorted, or if
155         result fits in 32-bit signed integer; result may be negative.
156 
157         @return  fRight minus fLeft
158     */
widthSkIRect159     constexpr int32_t width() const { return Sk32_can_overflow_sub(fRight, fLeft); }
160 
161     /** Returns span on the y-axis. This does not check if SkIRect is sorted, or if
162         result fits in 32-bit signed integer; result may be negative.
163 
164         @return  fBottom minus fTop
165     */
heightSkIRect166     constexpr int32_t height() const { return Sk32_can_overflow_sub(fBottom, fTop); }
167 
168     /** Returns spans on the x-axis and y-axis. This does not check if SkIRect is sorted,
169         or if result fits in 32-bit signed integer; result may be negative.
170 
171         @return  SkISize (width, height)
172     */
sizeSkIRect173     constexpr SkISize size() const { return SkISize::Make(this->width(), this->height()); }
174 
175     /** Returns span on the x-axis. This does not check if SkIRect is sorted, so the
176         result may be negative. This is safer than calling width() since width() might
177         overflow in its calculation.
178 
179         @return  fRight minus fLeft cast to int64_t
180     */
width64SkIRect181     constexpr int64_t width64() const { return (int64_t)fRight - (int64_t)fLeft; }
182 
183     /** Returns span on the y-axis. This does not check if SkIRect is sorted, so the
184         result may be negative. This is safer than calling height() since height() might
185         overflow in its calculation.
186 
187         @return  fBottom minus fTop cast to int64_t
188     */
height64SkIRect189     constexpr int64_t height64() const { return (int64_t)fBottom - (int64_t)fTop; }
190 
191     /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
192         to or greater than fBottom. Call sort() to reverse rectangles with negative
193         width64() or height64().
194 
195         @return  true if width64() or height64() are zero or negative
196     */
isEmpty64SkIRect197     bool isEmpty64() const { return fRight <= fLeft || fBottom <= fTop; }
198 
199     /** Returns true if width() or height() are zero or negative.
200 
201         @return  true if width() or height() are zero or negative
202     */
isEmptySkIRect203     bool isEmpty() const {
204         int64_t w = this->width64();
205         int64_t h = this->height64();
206         if (w <= 0 || h <= 0) {
207             return true;
208         }
209         // Return true if either exceeds int32_t
210         return !SkTFitsIn<int32_t>(w | h);
211     }
212 
213     /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
214         identical to corresponding members in b.
215 
216         @param a  SkIRect to compare
217         @param b  SkIRect to compare
218         @return   true if members are equal
219     */
220     friend bool operator==(const SkIRect& a, const SkIRect& b) {
221         return a.fLeft == b.fLeft && a.fTop == b.fTop &&
222                a.fRight == b.fRight && a.fBottom == b.fBottom;
223     }
224 
225     /** Returns true if any member in a: fLeft, fTop, fRight, and fBottom; is not
226         identical to the corresponding member in b.
227 
228         @param a  SkIRect to compare
229         @param b  SkIRect to compare
230         @return   true if members are not equal
231     */
232     friend bool operator!=(const SkIRect& a, const SkIRect& b) {
233         return a.fLeft != b.fLeft || a.fTop != b.fTop ||
234                a.fRight != b.fRight || a.fBottom != b.fBottom;
235     }
236 
237     /** Sets SkIRect to (0, 0, 0, 0).
238 
239         Many other rectangles are empty; if left is equal to or greater than right,
240         or if top is equal to or greater than bottom. Setting all members to zero
241         is a convenience, but does not designate a special empty rectangle.
242     */
setEmptySkIRect243     void setEmpty() { memset(this, 0, sizeof(*this)); }
244 
245     /** Sets SkIRect to (left, top, right, bottom).
246         left and right are not sorted; left is not necessarily less than right.
247         top and bottom are not sorted; top is not necessarily less than bottom.
248 
249         @param left    stored in fLeft
250         @param top     stored in fTop
251         @param right   stored in fRight
252         @param bottom  stored in fBottom
253     */
setLTRBSkIRect254     void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom) {
255         fLeft   = left;
256         fTop    = top;
257         fRight  = right;
258         fBottom = bottom;
259     }
260 
261     /** Sets SkIRect to: (x, y, x + width, y + height).
262         Does not validate input; width or height may be negative.
263 
264         @param x       stored in fLeft
265         @param y       stored in fTop
266         @param width   added to x and stored in fRight
267         @param height  added to y and stored in fBottom
268     */
setXYWHSkIRect269     void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height) {
270         fLeft   = x;
271         fTop    = y;
272         fRight  = Sk32_sat_add(x, width);
273         fBottom = Sk32_sat_add(y, height);
274     }
275 
setWHSkIRect276     void setWH(int32_t width, int32_t height) {
277         fLeft   = 0;
278         fTop    = 0;
279         fRight  = width;
280         fBottom = height;
281     }
282 
setSizeSkIRect283     void setSize(SkISize size) {
284         fLeft = 0;
285         fTop = 0;
286         fRight = size.width();
287         fBottom = size.height();
288     }
289 
290     /** Returns SkIRect offset by (dx, dy).
291 
292         If dx is negative, SkIRect returned is moved to the left.
293         If dx is positive, SkIRect returned is moved to the right.
294         If dy is negative, SkIRect returned is moved upward.
295         If dy is positive, SkIRect returned is moved downward.
296 
297         @param dx  offset added to fLeft and fRight
298         @param dy  offset added to fTop and fBottom
299         @return    SkIRect offset by dx and dy, with original width and height
300     */
makeOffsetSkIRect301     constexpr SkIRect makeOffset(int32_t dx, int32_t dy) const {
302         return {
303             Sk32_sat_add(fLeft,  dx), Sk32_sat_add(fTop,    dy),
304             Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),
305         };
306     }
307 
308     /** Returns SkIRect offset by (offset.x(), offset.y()).
309 
310         If offset.x() is negative, SkIRect returned is moved to the left.
311         If offset.x() is positive, SkIRect returned is moved to the right.
312         If offset.y() is negative, SkIRect returned is moved upward.
313         If offset.y() is positive, SkIRect returned is moved downward.
314 
315         @param offset  translation vector
316         @return    SkIRect translated by offset, with original width and height
317     */
makeOffsetSkIRect318     constexpr SkIRect makeOffset(SkIVector offset) const {
319         return this->makeOffset(offset.x(), offset.y());
320     }
321 
322     /** Returns SkIRect, inset by (dx, dy).
323 
324         If dx is negative, SkIRect returned is wider.
325         If dx is positive, SkIRect returned is narrower.
326         If dy is negative, SkIRect returned is taller.
327         If dy is positive, SkIRect returned is shorter.
328 
329         @param dx  offset added to fLeft and subtracted from fRight
330         @param dy  offset added to fTop and subtracted from fBottom
331         @return    SkIRect inset symmetrically left and right, top and bottom
332     */
makeInsetSkIRect333     SkIRect makeInset(int32_t dx, int32_t dy) const {
334         return {
335             Sk32_sat_add(fLeft,  dx), Sk32_sat_add(fTop,    dy),
336             Sk32_sat_sub(fRight, dx), Sk32_sat_sub(fBottom, dy),
337         };
338     }
339 
340     /** Returns SkIRect, outset by (dx, dy).
341 
342         If dx is negative, SkIRect returned is narrower.
343         If dx is positive, SkIRect returned is wider.
344         If dy is negative, SkIRect returned is shorter.
345         If dy is positive, SkIRect returned is taller.
346 
347         @param dx  offset subtracted to fLeft and added from fRight
348         @param dy  offset subtracted to fTop and added from fBottom
349         @return    SkIRect outset symmetrically left and right, top and bottom
350     */
makeOutsetSkIRect351     SkIRect makeOutset(int32_t dx, int32_t dy) const {
352         return {
353             Sk32_sat_sub(fLeft,  dx), Sk32_sat_sub(fTop,    dy),
354             Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),
355         };
356     }
357 
358     /** Offsets SkIRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
359 
360         If dx is negative, moves SkIRect returned to the left.
361         If dx is positive, moves SkIRect returned to the right.
362         If dy is negative, moves SkIRect returned upward.
363         If dy is positive, moves SkIRect returned downward.
364 
365         @param dx  offset added to fLeft and fRight
366         @param dy  offset added to fTop and fBottom
367     */
offsetSkIRect368     void offset(int32_t dx, int32_t dy) {
369         fLeft   = Sk32_sat_add(fLeft,   dx);
370         fTop    = Sk32_sat_add(fTop,    dy);
371         fRight  = Sk32_sat_add(fRight,  dx);
372         fBottom = Sk32_sat_add(fBottom, dy);
373     }
374 
375     /** Offsets SkIRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
376         fTop, fBottom.
377 
378         If delta.fX is negative, moves SkIRect returned to the left.
379         If delta.fX is positive, moves SkIRect returned to the right.
380         If delta.fY is negative, moves SkIRect returned upward.
381         If delta.fY is positive, moves SkIRect returned downward.
382 
383         @param delta  offset added to SkIRect
384     */
offsetSkIRect385     void offset(const SkIPoint& delta) {
386         this->offset(delta.fX, delta.fY);
387     }
388 
389     /** Offsets SkIRect so that fLeft equals newX, and fTop equals newY. width and height
390         are unchanged.
391 
392         @param newX  stored in fLeft, preserving width()
393         @param newY  stored in fTop, preserving height()
394     */
offsetToSkIRect395     void offsetTo(int32_t newX, int32_t newY) {
396         fRight  = Sk64_pin_to_s32((int64_t)fRight + newX - fLeft);
397         fBottom = Sk64_pin_to_s32((int64_t)fBottom + newY - fTop);
398         fLeft   = newX;
399         fTop    = newY;
400     }
401 
402     /** Insets SkIRect by (dx,dy).
403 
404         If dx is positive, makes SkIRect narrower.
405         If dx is negative, makes SkIRect wider.
406         If dy is positive, makes SkIRect shorter.
407         If dy is negative, makes SkIRect taller.
408 
409         @param dx  offset added to fLeft and subtracted from fRight
410         @param dy  offset added to fTop and subtracted from fBottom
411     */
insetSkIRect412     void inset(int32_t dx, int32_t dy) {
413         fLeft   = Sk32_sat_add(fLeft,   dx);
414         fTop    = Sk32_sat_add(fTop,    dy);
415         fRight  = Sk32_sat_sub(fRight,  dx);
416         fBottom = Sk32_sat_sub(fBottom, dy);
417     }
418 
419     /** Outsets SkIRect by (dx, dy).
420 
421         If dx is positive, makes SkIRect wider.
422         If dx is negative, makes SkIRect narrower.
423         If dy is positive, makes SkIRect taller.
424         If dy is negative, makes SkIRect shorter.
425 
426         @param dx  subtracted to fLeft and added from fRight
427         @param dy  subtracted to fTop and added from fBottom
428     */
outsetSkIRect429     void outset(int32_t dx, int32_t dy)  { this->inset(-dx, -dy); }
430 
431     /** Adjusts SkIRect by adding dL to fLeft, dT to fTop, dR to fRight, and dB to fBottom.
432 
433         If dL is positive, narrows SkIRect on the left. If negative, widens it on the left.
434         If dT is positive, shrinks SkIRect on the top. If negative, lengthens it on the top.
435         If dR is positive, narrows SkIRect on the right. If negative, widens it on the right.
436         If dB is positive, shrinks SkIRect on the bottom. If negative, lengthens it on the bottom.
437 
438         The resulting SkIRect is not checked for validity. Thus, if the resulting SkIRect left is
439         greater than right, the SkIRect will be considered empty. Call sort() after this call
440         if that is not the desired behavior.
441 
442         @param dL  offset added to fLeft
443         @param dT  offset added to fTop
444         @param dR  offset added to fRight
445         @param dB  offset added to fBottom
446     */
adjustSkIRect447     void adjust(int32_t dL, int32_t dT, int32_t dR, int32_t dB) {
448         fLeft   = Sk32_sat_add(fLeft,   dL);
449         fTop    = Sk32_sat_add(fTop,    dT);
450         fRight  = Sk32_sat_add(fRight,  dR);
451         fBottom = Sk32_sat_add(fBottom, dB);
452     }
453 
454     /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
455         Returns false if SkIRect is empty.
456 
457         Considers input to describe constructed SkIRect: (x, y, x + 1, y + 1) and
458         returns true if constructed area is completely enclosed by SkIRect area.
459 
460         @param x  test SkIPoint x-coordinate
461         @param y  test SkIPoint y-coordinate
462         @return   true if (x, y) is inside SkIRect
463     */
containsSkIRect464     bool contains(int32_t x, int32_t y) const {
465         return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
466     }
467 
468     /** Returns true if SkIRect contains r.
469      Returns false if SkIRect is empty or r is empty.
470 
471      SkIRect contains r when SkIRect area completely includes r area.
472 
473      @param r  SkIRect contained
474      @return   true if all sides of SkIRect are outside r
475      */
containsSkIRect476     bool contains(const SkIRect& r) const {
477         return  !r.isEmpty() && !this->isEmpty() &&     // check for empties
478                 fLeft <= r.fLeft && fTop <= r.fTop &&
479                 fRight >= r.fRight && fBottom >= r.fBottom;
480     }
481 
482     /** Returns true if SkIRect contains r.
483         Returns false if SkIRect is empty or r is empty.
484 
485         SkIRect contains r when SkIRect area completely includes r area.
486 
487         @param r  SkRect contained
488         @return   true if all sides of SkIRect are outside r
489     */
490     inline bool contains(const SkRect& r) const;
491 
492     /** Returns true if SkIRect contains construction.
493         Asserts if SkIRect is empty or construction is empty, and if SK_DEBUG is defined.
494 
495         Return is undefined if SkIRect is empty or construction is empty.
496 
497         @param r  SkIRect contained
498         @return   true if all sides of SkIRect are outside r
499     */
containsNoEmptyCheckSkIRect500     bool containsNoEmptyCheck(const SkIRect& r) const {
501         SkASSERT(fLeft < fRight && fTop < fBottom);
502         SkASSERT(r.fLeft < r.fRight && r.fTop < r.fBottom);
503         return fLeft <= r.fLeft && fTop <= r.fTop && fRight >= r.fRight && fBottom >= r.fBottom;
504     }
505 
506     /** Returns true if SkIRect intersects r, and sets SkIRect to intersection.
507         Returns false if SkIRect does not intersect r, and leaves SkIRect unchanged.
508 
509         Returns false if either r or SkIRect is empty, leaving SkIRect unchanged.
510 
511         @param r  limit of result
512         @return   true if r and SkIRect have area in common
513     */
intersectSkIRect514     bool intersect(const SkIRect& r) {
515         return this->intersect(*this, r);
516     }
517 
518     /** Returns true if a intersects b, and sets SkIRect to intersection.
519         Returns false if a does not intersect b, and leaves SkIRect unchanged.
520 
521         Returns false if either a or b is empty, leaving SkIRect unchanged.
522 
523         @param a  SkIRect to intersect
524         @param b  SkIRect to intersect
525         @return   true if a and b have area in common
526     */
527     bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& a, const SkIRect& b);
528 
529     /** Returns true if a intersects b.
530         Returns false if either a or b is empty, or do not intersect.
531 
532         @param a  SkIRect to intersect
533         @param b  SkIRect to intersect
534         @return   true if a and b have area in common
535     */
IntersectsSkIRect536     static bool Intersects(const SkIRect& a, const SkIRect& b) {
537         return SkIRect{}.intersect(a, b);
538     }
539 
540     /** Sets SkIRect to the union of itself and r.
541 
542      Has no effect if r is empty. Otherwise, if SkIRect is empty, sets SkIRect to r.
543 
544      @param r  expansion SkIRect
545 
546         example: https://fiddle.skia.org/c/@IRect_join_2
547      */
548     void join(const SkIRect& r);
549 
550     /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
551         fTop and fBottom if fTop is greater than fBottom. Result may be empty,
552         and width() and height() will be zero or positive.
553     */
sortSkIRect554     void sort() {
555         using std::swap;
556         if (fLeft > fRight) {
557             swap(fLeft, fRight);
558         }
559         if (fTop > fBottom) {
560             swap(fTop, fBottom);
561         }
562     }
563 
564     /** Returns SkIRect with fLeft and fRight swapped if fLeft is greater than fRight; and
565         with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
566         and width() and height() will be zero or positive.
567 
568         @return  sorted SkIRect
569     */
makeSortedSkIRect570     SkIRect makeSorted() const {
571         return MakeLTRB(std::min(fLeft, fRight), std::min(fTop, fBottom),
572                         std::max(fLeft, fRight), std::max(fTop, fBottom));
573     }
574 };
575 
576 /** \struct SkRect
577     SkRect holds four SkScalar coordinates describing the upper and
578     lower bounds of a rectangle. SkRect may be created from outer bounds or
579     from position, width, and height. SkRect describes an area; if its right
580     is less than or equal to its left, or if its bottom is less than or equal to
581     its top, it is considered empty.
582 */
583 struct SK_API SkRect {
584     SkScalar fLeft;   //!< smaller x-axis bounds
585     SkScalar fTop;    //!< smaller y-axis bounds
586     SkScalar fRight;  //!< larger x-axis bounds
587     SkScalar fBottom; //!< larger y-axis bounds
588 
589     /** Returns constructed SkRect set to (0, 0, 0, 0).
590         Many other rectangles are empty; if left is equal to or greater than right,
591         or if top is equal to or greater than bottom. Setting all members to zero
592         is a convenience, but does not designate a special empty rectangle.
593 
594         @return  bounds (0, 0, 0, 0)
595     */
MakeEmptySkRect596     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeEmpty() {
597         return SkRect{0, 0, 0, 0};
598     }
599 
600     /** Returns constructed SkRect set to SkScalar values (0, 0, w, h). Does not
601         validate input; w or h may be negative.
602 
603         Passing integer values may generate a compiler warning since SkRect cannot
604         represent 32-bit integers exactly. Use SkIRect for an exact integer rectangle.
605 
606         @param w  SkScalar width of constructed SkRect
607         @param h  SkScalar height of constructed SkRect
608         @return   bounds (0, 0, w, h)
609     */
MakeWHSkRect610     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeWH(SkScalar w, SkScalar h) {
611         return SkRect{0, 0, w, h};
612     }
613 
614     /** Returns constructed SkRect set to integer values (0, 0, w, h). Does not validate
615         input; w or h may be negative.
616 
617         Use to avoid a compiler warning that input may lose precision when stored.
618         Use SkIRect for an exact integer rectangle.
619 
620         @param w  integer width of constructed SkRect
621         @param h  integer height of constructed SkRect
622         @return   bounds (0, 0, w, h)
623     */
MakeIWHSkRect624     static SkRect SK_WARN_UNUSED_RESULT MakeIWH(int w, int h) {
625         return {0, 0, SkIntToScalar(w), SkIntToScalar(h)};
626     }
627 
628     /** Returns constructed SkRect set to (0, 0, size.width(), size.height()). Does not
629         validate input; size.width() or size.height() may be negative.
630 
631         @param size  SkScalar values for SkRect width and height
632         @return      bounds (0, 0, size.width(), size.height())
633     */
MakeSizeSkRect634     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeSize(const SkSize& size) {
635         return SkRect{0, 0, size.fWidth, size.fHeight};
636     }
637 
638     /** Returns constructed SkRect set to (l, t, r, b). Does not sort input; SkRect may
639         result in fLeft greater than fRight, or fTop greater than fBottom.
640 
641         @param l  SkScalar stored in fLeft
642         @param t  SkScalar stored in fTop
643         @param r  SkScalar stored in fRight
644         @param b  SkScalar stored in fBottom
645         @return   bounds (l, t, r, b)
646     */
MakeLTRBSkRect647     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeLTRB(SkScalar l, SkScalar t, SkScalar r,
648                                                            SkScalar b) {
649         return SkRect {l, t, r, b};
650     }
651 
652     /** Returns constructed SkRect set to (x, y, x + w, y + h).
653         Does not validate input; w or h may be negative.
654 
655         @param x  stored in fLeft
656         @param y  stored in fTop
657         @param w  added to x and stored in fRight
658         @param h  added to y and stored in fBottom
659         @return   bounds at (x, y) with width w and height h
660     */
MakeXYWHSkRect661     static constexpr SkRect SK_WARN_UNUSED_RESULT MakeXYWH(SkScalar x, SkScalar y, SkScalar w,
662                                                            SkScalar h) {
663         return SkRect {x, y, x + w, y + h};
664     }
665 
666     /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
667         Does not validate input; size.width() or size.height() may be negative.
668 
669         @param size  integer values for SkRect width and height
670         @return      bounds (0, 0, size.width(), size.height())
671     */
MakeSkRect672     static SkRect Make(const SkISize& size) {
673         return MakeIWH(size.width(), size.height());
674     }
675 
676     /** Returns constructed SkIRect set to irect, promoting integers to scalar.
677         Does not validate input; fLeft may be greater than fRight, fTop may be greater
678         than fBottom.
679 
680         @param irect  integer unsorted bounds
681         @return       irect members converted to SkScalar
682     */
MakeSkRect683     static SkRect SK_WARN_UNUSED_RESULT Make(const SkIRect& irect) {
684         return {
685             SkIntToScalar(irect.fLeft), SkIntToScalar(irect.fTop),
686             SkIntToScalar(irect.fRight), SkIntToScalar(irect.fBottom)
687         };
688     }
689 
690     /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
691         to or greater than fBottom. Call sort() to reverse rectangles with negative
692         width() or height().
693 
694         @return  true if width() or height() are zero or negative
695     */
isEmptySkRect696     bool isEmpty() const {
697         // We write it as the NOT of a non-empty rect, so we will return true if any values
698         // are NaN.
699         return !(fLeft < fRight && fTop < fBottom);
700     }
701 
702     /** Returns true if fLeft is equal to or less than fRight, or if fTop is equal
703         to or less than fBottom. Call sort() to reverse rectangles with negative
704         width() or height().
705 
706         @return  true if width() or height() are zero or positive
707     */
isSortedSkRect708     bool isSorted() const { return fLeft <= fRight && fTop <= fBottom; }
709 
710     /** Returns true if all values in the rectangle are finite: SK_ScalarMin or larger,
711         and SK_ScalarMax or smaller.
712 
713         @return  true if no member is infinite or NaN
714     */
isFiniteSkRect715     bool isFinite() const {
716         float accum = 0;
717         accum *= fLeft;
718         accum *= fTop;
719         accum *= fRight;
720         accum *= fBottom;
721 
722         // accum is either NaN or it is finite (zero).
723         SkASSERT(0 == accum || SkScalarIsNaN(accum));
724 
725         // value==value will be true iff value is not NaN
726         // TODO: is it faster to say !accum or accum==accum?
727         return !SkScalarIsNaN(accum);
728     }
729 
730     /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
731         Call sort() to reverse fLeft and fRight if needed.
732 
733         @return  fLeft
734     */
xSkRect735     constexpr SkScalar x() const { return fLeft; }
736 
737     /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
738         and sort() to reverse fTop and fBottom if needed.
739 
740         @return  fTop
741     */
ySkRect742     constexpr SkScalar y() const { return fTop; }
743 
744     /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
745         Call sort() to reverse fLeft and fRight if needed.
746 
747         @return  fLeft
748     */
leftSkRect749     constexpr SkScalar left() const { return fLeft; }
750 
751     /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
752         and sort() to reverse fTop and fBottom if needed.
753 
754         @return  fTop
755     */
topSkRect756     constexpr SkScalar top() const { return fTop; }
757 
758     /** Returns right edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
759         Call sort() to reverse fLeft and fRight if needed.
760 
761         @return  fRight
762     */
rightSkRect763     constexpr SkScalar right() const { return fRight; }
764 
765     /** Returns bottom edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
766         and sort() to reverse fTop and fBottom if needed.
767 
768         @return  fBottom
769     */
bottomSkRect770     constexpr SkScalar bottom() const { return fBottom; }
771 
772     /** Returns span on the x-axis. This does not check if SkRect is sorted, or if
773         result fits in 32-bit float; result may be negative or infinity.
774 
775         @return  fRight minus fLeft
776     */
widthSkRect777     constexpr SkScalar width() const { return fRight - fLeft; }
778 
779     /** Returns span on the y-axis. This does not check if SkRect is sorted, or if
780         result fits in 32-bit float; result may be negative or infinity.
781 
782         @return  fBottom minus fTop
783     */
heightSkRect784     constexpr SkScalar height() const { return fBottom - fTop; }
785 
786     /** Returns average of left edge and right edge. Result does not change if SkRect
787         is sorted. Result may overflow to infinity if SkRect is far from the origin.
788 
789         @return  midpoint on x-axis
790     */
centerXSkRect791     constexpr SkScalar centerX() const {
792         // don't use SkScalarHalf(fLeft + fBottom) as that might overflow before the 0.5
793         return SkScalarHalf(fLeft) + SkScalarHalf(fRight);
794     }
795 
796     /** Returns average of top edge and bottom edge. Result does not change if SkRect
797         is sorted.
798 
799         @return  midpoint on y-axis
800     */
centerYSkRect801     constexpr SkScalar centerY() const {
802         // don't use SkScalarHalf(fTop + fBottom) as that might overflow before the 0.5
803         return SkScalarHalf(fTop) + SkScalarHalf(fBottom);
804     }
805 
806     /** Returns the point this->centerX(), this->centerY().
807         @return  rectangle center
808      */
centerSkRect809     constexpr SkPoint center() const { return {this->centerX(), this->centerY()}; }
810 
811     /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
812         equal to the corresponding members in b.
813 
814         a and b are not equal if either contain NaN. a and b are equal if members
815         contain zeroes with different signs.
816 
817         @param a  SkRect to compare
818         @param b  SkRect to compare
819         @return   true if members are equal
820     */
821     friend bool operator==(const SkRect& a, const SkRect& b) {
822         return SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);
823     }
824 
825     /** Returns true if any in a: fLeft, fTop, fRight, and fBottom; does not
826         equal the corresponding members in b.
827 
828         a and b are not equal if either contain NaN. a and b are equal if members
829         contain zeroes with different signs.
830 
831         @param a  SkRect to compare
832         @param b  SkRect to compare
833         @return   true if members are not equal
834     */
835     friend bool operator!=(const SkRect& a, const SkRect& b) {
836         return !SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);
837     }
838 
839     /** Returns four points in quad that enclose SkRect ordered as: top-left, top-right,
840         bottom-right, bottom-left.
841 
842         TODO: Consider adding parameter to control whether quad is clockwise or counterclockwise.
843 
844         @param quad  storage for corners of SkRect
845 
846         example: https://fiddle.skia.org/c/@Rect_toQuad
847     */
848     void toQuad(SkPoint quad[4]) const;
849 
850     /** Sets SkRect to (0, 0, 0, 0).
851 
852         Many other rectangles are empty; if left is equal to or greater than right,
853         or if top is equal to or greater than bottom. Setting all members to zero
854         is a convenience, but does not designate a special empty rectangle.
855     */
setEmptySkRect856     void setEmpty() { *this = MakeEmpty(); }
857 
858     /** Sets SkRect to src, promoting src members from integer to scalar.
859         Very large values in src may lose precision.
860 
861         @param src  integer SkRect
862     */
setSkRect863     void set(const SkIRect& src) {
864         fLeft   = SkIntToScalar(src.fLeft);
865         fTop    = SkIntToScalar(src.fTop);
866         fRight  = SkIntToScalar(src.fRight);
867         fBottom = SkIntToScalar(src.fBottom);
868     }
869 
870     /** Sets SkRect to (left, top, right, bottom).
871         left and right are not sorted; left is not necessarily less than right.
872         top and bottom are not sorted; top is not necessarily less than bottom.
873 
874         @param left    stored in fLeft
875         @param top     stored in fTop
876         @param right   stored in fRight
877         @param bottom  stored in fBottom
878     */
setLTRBSkRect879     void setLTRB(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
880         fLeft   = left;
881         fTop    = top;
882         fRight  = right;
883         fBottom = bottom;
884     }
885 
886     /** Sets to bounds of SkPoint array with count entries. If count is zero or smaller,
887         or if SkPoint array contains an infinity or NaN, sets to (0, 0, 0, 0).
888 
889         Result is either empty or sorted: fLeft is less than or equal to fRight, and
890         fTop is less than or equal to fBottom.
891 
892         @param pts    SkPoint array
893         @param count  entries in array
894     */
setBoundsSkRect895     void setBounds(const SkPoint pts[], int count) {
896         (void)this->setBoundsCheck(pts, count);
897     }
898 
899     /** Sets to bounds of SkPoint array with count entries. Returns false if count is
900         zero or smaller, or if SkPoint array contains an infinity or NaN; in these cases
901         sets SkRect to (0, 0, 0, 0).
902 
903         Result is either empty or sorted: fLeft is less than or equal to fRight, and
904         fTop is less than or equal to fBottom.
905 
906         @param pts    SkPoint array
907         @param count  entries in array
908         @return       true if all SkPoint values are finite
909 
910         example: https://fiddle.skia.org/c/@Rect_setBoundsCheck
911     */
912     bool setBoundsCheck(const SkPoint pts[], int count);
913 
914     /** Sets to bounds of SkPoint pts array with count entries. If any SkPoint in pts
915         contains infinity or NaN, all SkRect dimensions are set to NaN.
916 
917         @param pts    SkPoint array
918         @param count  entries in array
919 
920         example: https://fiddle.skia.org/c/@Rect_setBoundsNoCheck
921     */
922     void setBoundsNoCheck(const SkPoint pts[], int count);
923 
924     /** Sets bounds to the smallest SkRect enclosing SkPoint p0 and p1. The result is
925         sorted and may be empty. Does not check to see if values are finite.
926 
927         @param p0  corner to include
928         @param p1  corner to include
929     */
setSkRect930     void set(const SkPoint& p0, const SkPoint& p1) {
931         fLeft =   std::min(p0.fX, p1.fX);
932         fRight =  std::max(p0.fX, p1.fX);
933         fTop =    std::min(p0.fY, p1.fY);
934         fBottom = std::max(p0.fY, p1.fY);
935     }
936 
937     /** Sets SkRect to (x, y, x + width, y + height).
938         Does not validate input; width or height may be negative.
939 
940         @param x       stored in fLeft
941         @param y       stored in fTop
942         @param width   added to x and stored in fRight
943         @param height  added to y and stored in fBottom
944     */
setXYWHSkRect945     void setXYWH(SkScalar x, SkScalar y, SkScalar width, SkScalar height) {
946         fLeft = x;
947         fTop = y;
948         fRight = x + width;
949         fBottom = y + height;
950     }
951 
952     /** Sets SkRect to (0, 0, width, height). Does not validate input;
953         width or height may be negative.
954 
955         @param width   stored in fRight
956         @param height  stored in fBottom
957     */
setWHSkRect958     void setWH(SkScalar width, SkScalar height) {
959         fLeft = 0;
960         fTop = 0;
961         fRight = width;
962         fBottom = height;
963     }
setIWHSkRect964     void setIWH(int32_t width, int32_t height) {
965         this->setWH(SkIntToScalar(width), SkIntToScalar(height));
966     }
967 
968     /** Returns SkRect offset by (dx, dy).
969 
970         If dx is negative, SkRect returned is moved to the left.
971         If dx is positive, SkRect returned is moved to the right.
972         If dy is negative, SkRect returned is moved upward.
973         If dy is positive, SkRect returned is moved downward.
974 
975         @param dx  added to fLeft and fRight
976         @param dy  added to fTop and fBottom
977         @return    SkRect offset on axes, with original width and height
978     */
makeOffsetSkRect979     constexpr SkRect makeOffset(SkScalar dx, SkScalar dy) const {
980         return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy);
981     }
982 
983     /** Returns SkRect offset by v.
984 
985         @param v  added to rect
986         @return    SkRect offset on axes, with original width and height
987     */
makeOffsetSkRect988     constexpr SkRect makeOffset(SkVector v) const { return this->makeOffset(v.x(), v.y()); }
989 
990     /** Returns SkRect, inset by (dx, dy).
991 
992         If dx is negative, SkRect returned is wider.
993         If dx is positive, SkRect returned is narrower.
994         If dy is negative, SkRect returned is taller.
995         If dy is positive, SkRect returned is shorter.
996 
997         @param dx  added to fLeft and subtracted from fRight
998         @param dy  added to fTop and subtracted from fBottom
999         @return    SkRect inset symmetrically left and right, top and bottom
1000     */
makeInsetSkRect1001     SkRect makeInset(SkScalar dx, SkScalar dy) const {
1002         return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, fBottom - dy);
1003     }
1004 
1005     /** Returns SkRect, outset by (dx, dy).
1006 
1007         If dx is negative, SkRect returned is narrower.
1008         If dx is positive, SkRect returned is wider.
1009         If dy is negative, SkRect returned is shorter.
1010         If dy is positive, SkRect returned is taller.
1011 
1012         @param dx  subtracted to fLeft and added from fRight
1013         @param dy  subtracted to fTop and added from fBottom
1014         @return    SkRect outset symmetrically left and right, top and bottom
1015     */
makeOutsetSkRect1016     SkRect makeOutset(SkScalar dx, SkScalar dy) const {
1017         return MakeLTRB(fLeft - dx, fTop - dy, fRight + dx, fBottom + dy);
1018     }
1019 
1020     /** Offsets SkRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
1021 
1022         If dx is negative, moves SkRect to the left.
1023         If dx is positive, moves SkRect to the right.
1024         If dy is negative, moves SkRect upward.
1025         If dy is positive, moves SkRect downward.
1026 
1027         @param dx  offset added to fLeft and fRight
1028         @param dy  offset added to fTop and fBottom
1029     */
offsetSkRect1030     void offset(SkScalar dx, SkScalar dy) {
1031         fLeft   += dx;
1032         fTop    += dy;
1033         fRight  += dx;
1034         fBottom += dy;
1035     }
1036 
1037     /** Offsets SkRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
1038         fTop, fBottom.
1039 
1040         If delta.fX is negative, moves SkRect to the left.
1041         If delta.fX is positive, moves SkRect to the right.
1042         If delta.fY is negative, moves SkRect upward.
1043         If delta.fY is positive, moves SkRect downward.
1044 
1045         @param delta  added to SkRect
1046     */
offsetSkRect1047     void offset(const SkPoint& delta) {
1048         this->offset(delta.fX, delta.fY);
1049     }
1050 
1051     /** Offsets SkRect so that fLeft equals newX, and fTop equals newY. width and height
1052         are unchanged.
1053 
1054         @param newX  stored in fLeft, preserving width()
1055         @param newY  stored in fTop, preserving height()
1056     */
offsetToSkRect1057     void offsetTo(SkScalar newX, SkScalar newY) {
1058         fRight += newX - fLeft;
1059         fBottom += newY - fTop;
1060         fLeft = newX;
1061         fTop = newY;
1062     }
1063 
1064     /** Insets SkRect by (dx, dy).
1065 
1066         If dx is positive, makes SkRect narrower.
1067         If dx is negative, makes SkRect wider.
1068         If dy is positive, makes SkRect shorter.
1069         If dy is negative, makes SkRect taller.
1070 
1071         @param dx  added to fLeft and subtracted from fRight
1072         @param dy  added to fTop and subtracted from fBottom
1073     */
insetSkRect1074     void inset(SkScalar dx, SkScalar dy)  {
1075         fLeft   += dx;
1076         fTop    += dy;
1077         fRight  -= dx;
1078         fBottom -= dy;
1079     }
1080 
1081     /** Outsets SkRect by (dx, dy).
1082 
1083         If dx is positive, makes SkRect wider.
1084         If dx is negative, makes SkRect narrower.
1085         If dy is positive, makes SkRect taller.
1086         If dy is negative, makes SkRect shorter.
1087 
1088         @param dx  subtracted to fLeft and added from fRight
1089         @param dy  subtracted to fTop and added from fBottom
1090     */
outsetSkRect1091     void outset(SkScalar dx, SkScalar dy)  { this->inset(-dx, -dy); }
1092 
1093     /** Returns true if SkRect intersects r, and sets SkRect to intersection.
1094         Returns false if SkRect does not intersect r, and leaves SkRect unchanged.
1095 
1096         Returns false if either r or SkRect is empty, leaving SkRect unchanged.
1097 
1098         @param r  limit of result
1099         @return   true if r and SkRect have area in common
1100 
1101         example: https://fiddle.skia.org/c/@Rect_intersect
1102     */
1103     bool intersect(const SkRect& r);
1104 
1105     /** Returns true if a intersects b, and sets SkRect to intersection.
1106         Returns false if a does not intersect b, and leaves SkRect unchanged.
1107 
1108         Returns false if either a or b is empty, leaving SkRect unchanged.
1109 
1110         @param a  SkRect to intersect
1111         @param b  SkRect to intersect
1112         @return   true if a and b have area in common
1113     */
1114     bool SK_WARN_UNUSED_RESULT intersect(const SkRect& a, const SkRect& b);
1115 
1116 
1117 private:
IntersectsSkRect1118     static bool Intersects(SkScalar al, SkScalar at, SkScalar ar, SkScalar ab,
1119                            SkScalar bl, SkScalar bt, SkScalar br, SkScalar bb) {
1120         SkScalar L = std::max(al, bl);
1121         SkScalar R = std::min(ar, br);
1122         SkScalar T = std::max(at, bt);
1123         SkScalar B = std::min(ab, bb);
1124         return L < R && T < B;
1125     }
1126 
1127 public:
1128 
1129     /** Returns true if SkRect intersects r.
1130      Returns false if either r or SkRect is empty, or do not intersect.
1131 
1132      @param r  SkRect to intersect
1133      @return   true if r and SkRect have area in common
1134      */
intersectsSkRect1135     bool intersects(const SkRect& r) const {
1136         return Intersects(fLeft, fTop, fRight, fBottom,
1137                           r.fLeft, r.fTop, r.fRight, r.fBottom);
1138     }
1139 
1140     /** Returns true if a intersects b.
1141         Returns false if either a or b is empty, or do not intersect.
1142 
1143         @param a  SkRect to intersect
1144         @param b  SkRect to intersect
1145         @return   true if a and b have area in common
1146     */
IntersectsSkRect1147     static bool Intersects(const SkRect& a, const SkRect& b) {
1148         return Intersects(a.fLeft, a.fTop, a.fRight, a.fBottom,
1149                           b.fLeft, b.fTop, b.fRight, b.fBottom);
1150     }
1151 
1152     /** Sets SkRect to the union of itself and r.
1153 
1154         Has no effect if r is empty. Otherwise, if SkRect is empty, sets
1155         SkRect to r.
1156 
1157         @param r  expansion SkRect
1158 
1159         example: https://fiddle.skia.org/c/@Rect_join_2
1160     */
1161     void join(const SkRect& r);
1162 
1163     /** Sets SkRect to the union of itself and r.
1164 
1165         Asserts if r is empty and SK_DEBUG is defined.
1166         If SkRect is empty, sets SkRect to r.
1167 
1168         May produce incorrect results if r is empty.
1169 
1170         @param r  expansion SkRect
1171     */
joinNonEmptyArgSkRect1172     void joinNonEmptyArg(const SkRect& r) {
1173         SkASSERT(!r.isEmpty());
1174         // if we are empty, just assign
1175         if (fLeft >= fRight || fTop >= fBottom) {
1176             *this = r;
1177         } else {
1178             this->joinPossiblyEmptyRect(r);
1179         }
1180     }
1181 
1182     /** Sets SkRect to the union of itself and the construction.
1183 
1184         May produce incorrect results if SkRect or r is empty.
1185 
1186         @param r  expansion SkRect
1187     */
joinPossiblyEmptyRectSkRect1188     void joinPossiblyEmptyRect(const SkRect& r) {
1189         fLeft   = std::min(fLeft, r.left());
1190         fTop    = std::min(fTop, r.top());
1191         fRight  = std::max(fRight, r.right());
1192         fBottom = std::max(fBottom, r.bottom());
1193     }
1194 
1195     /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
1196         Returns false if SkRect is empty.
1197 
1198         @param x  test SkPoint x-coordinate
1199         @param y  test SkPoint y-coordinate
1200         @return   true if (x, y) is inside SkRect
1201     */
containsSkRect1202     bool contains(SkScalar x, SkScalar y) const {
1203         return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
1204     }
1205 
1206     /** Returns true if SkRect contains r.
1207         Returns false if SkRect is empty or r is empty.
1208 
1209         SkRect contains r when SkRect area completely includes r area.
1210 
1211         @param r  SkRect contained
1212         @return   true if all sides of SkRect are outside r
1213     */
containsSkRect1214     bool contains(const SkRect& r) const {
1215         // todo: can we eliminate the this->isEmpty check?
1216         return  !r.isEmpty() && !this->isEmpty() &&
1217                 fLeft <= r.fLeft && fTop <= r.fTop &&
1218                 fRight >= r.fRight && fBottom >= r.fBottom;
1219     }
1220 
1221     /** Returns true if SkRect contains r.
1222         Returns false if SkRect is empty or r is empty.
1223 
1224         SkRect contains r when SkRect area completely includes r area.
1225 
1226         @param r  SkIRect contained
1227         @return   true if all sides of SkRect are outside r
1228     */
containsSkRect1229     bool contains(const SkIRect& r) const {
1230         // todo: can we eliminate the this->isEmpty check?
1231         return  !r.isEmpty() && !this->isEmpty() &&
1232                 fLeft <= SkIntToScalar(r.fLeft) && fTop <= SkIntToScalar(r.fTop) &&
1233                 fRight >= SkIntToScalar(r.fRight) && fBottom >= SkIntToScalar(r.fBottom);
1234     }
1235 
1236     /** Sets SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1237         members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1238                         SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).
1239 
1240         @param dst  storage for SkIRect
1241     */
roundSkRect1242     void round(SkIRect* dst) const {
1243         SkASSERT(dst);
1244         dst->setLTRB(SkScalarRoundToInt(fLeft),  SkScalarRoundToInt(fTop),
1245                      SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom));
1246     }
1247 
1248     /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1249         up fRight and fBottom, using
1250         (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1251          SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1252 
1253         @param dst  storage for SkIRect
1254     */
roundOutSkRect1255     void roundOut(SkIRect* dst) const {
1256         SkASSERT(dst);
1257         dst->setLTRB(SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1258                      SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom));
1259     }
1260 
1261     /** Sets SkRect by discarding the fractional portion of fLeft and fTop; and rounding
1262         up fRight and fBottom, using
1263         (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1264          SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1265 
1266         @param dst  storage for SkRect
1267     */
roundOutSkRect1268     void roundOut(SkRect* dst) const {
1269         dst->setLTRB(SkScalarFloorToScalar(fLeft), SkScalarFloorToScalar(fTop),
1270                      SkScalarCeilToScalar(fRight), SkScalarCeilToScalar(fBottom));
1271     }
1272 
1273     /** Sets SkRect by rounding up fLeft and fTop; and discarding the fractional portion
1274         of fRight and fBottom, using
1275         (SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
1276          SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom)).
1277 
1278         @param dst  storage for SkIRect
1279     */
roundInSkRect1280     void roundIn(SkIRect* dst) const {
1281         SkASSERT(dst);
1282         dst->setLTRB(SkScalarCeilToInt(fLeft),   SkScalarCeilToInt(fTop),
1283                      SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom));
1284     }
1285 
1286     /** Returns SkIRect by adding 0.5 and discarding the fractional portion of SkRect
1287         members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
1288                         SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).
1289 
1290         @return  rounded SkIRect
1291     */
roundSkRect1292     SkIRect round() const {
1293         SkIRect ir;
1294         this->round(&ir);
1295         return ir;
1296     }
1297 
1298     /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
1299         up fRight and fBottom, using
1300         (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
1301          SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
1302 
1303         @return  rounded SkIRect
1304     */
roundOutSkRect1305     SkIRect roundOut() const {
1306         SkIRect ir;
1307         this->roundOut(&ir);
1308         return ir;
1309     }
1310     /** Sets SkIRect by rounding up fLeft and fTop; and discarding the fractional portion
1311         of fRight and fBottom, using
1312         (SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
1313          SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom)).
1314 
1315         @return  rounded SkIRect
1316     */
roundInSkRect1317     SkIRect roundIn() const {
1318         SkIRect ir;
1319         this->roundIn(&ir);
1320         return ir;
1321     }
1322 
1323     /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
1324         fTop and fBottom if fTop is greater than fBottom. Result may be empty;
1325         and width() and height() will be zero or positive.
1326     */
sortSkRect1327     void sort() {
1328         using std::swap;
1329         if (fLeft > fRight) {
1330             swap(fLeft, fRight);
1331         }
1332 
1333         if (fTop > fBottom) {
1334             swap(fTop, fBottom);
1335         }
1336     }
1337 
1338     /** Returns SkRect with fLeft and fRight swapped if fLeft is greater than fRight; and
1339         with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
1340         and width() and height() will be zero or positive.
1341 
1342         @return  sorted SkRect
1343     */
makeSortedSkRect1344     SkRect makeSorted() const {
1345         return MakeLTRB(std::min(fLeft, fRight), std::min(fTop, fBottom),
1346                         std::max(fLeft, fRight), std::max(fTop, fBottom));
1347     }
1348 
1349     /** Returns pointer to first scalar in SkRect, to treat it as an array with four
1350         entries.
1351 
1352         @return  pointer to fLeft
1353     */
asScalarsSkRect1354     const SkScalar* asScalars() const { return &fLeft; }
1355 
1356     /** Writes text representation of SkRect to standard output. Set asHex to true to
1357         generate exact binary representations of floating point numbers.
1358 
1359         @param asHex  true if SkScalar values are written as hexadecimal
1360 
1361         example: https://fiddle.skia.org/c/@Rect_dump
1362     */
1363     void dump(bool asHex) const;
1364 
1365     /** Writes text representation of SkRect to standard output. The representation may be
1366         directly compiled as C++ code. Floating point values are written
1367         with limited precision; it may not be possible to reconstruct original SkRect
1368         from output.
1369     */
dumpSkRect1370     void dump() const { this->dump(false); }
1371 
1372     /** Writes text representation of SkRect to standard output. The representation may be
1373         directly compiled as C++ code. Floating point values are written
1374         in hexadecimal to preserve their exact bit pattern. The output reconstructs the
1375         original SkRect.
1376 
1377         Use instead of dump() when submitting
1378     */
dumpHexSkRect1379     void dumpHex() const { this->dump(true); }
1380 };
1381 
contains(const SkRect & r)1382 inline bool SkIRect::contains(const SkRect& r) const {
1383     return  !r.isEmpty() && !this->isEmpty() &&     // check for empties
1384             (SkScalar)fLeft <= r.fLeft && (SkScalar)fTop <= r.fTop &&
1385             (SkScalar)fRight >= r.fRight && (SkScalar)fBottom >= r.fBottom;
1386 }
1387 
1388 #endif
1389